1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Implements a PNG reader class + handler 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #  pragma implementation "pngread.h" 
  14 #  pragma implementation "pnghand.h" 
  17 // For compilers that support precompilation, includes "wx.h". 
  18 #include "wx/wxprec.h" 
  37 #include "wx/msgdlg.h" 
  38 #include "wx/palette.h" 
  39 #include "wx/bitmap.h" 
  40 #include "wx/mac/pnghand.h" 
  41 #include "wx/mac/pngread.h" 
  47 extern "C" void png_read_init 
PNGARG((png_structp png_ptr
)); 
  48 extern "C" void png_write_init 
PNGARG((png_structp png_ptr
)); 
  50 extern CTabHandle 
wxMacCreateColorTable( int numColors 
) ; 
  51 extern void wxMacDestroyColorTable( CTabHandle colors 
)  ; 
  52 extern void wxMacSetColorTableEntry( CTabHandle newColors 
, int index 
, int red 
, int green 
,  int blue 
) ; 
  53 extern GWorldPtr 
wxMacCreateGWorld( int width 
, int height 
, int depth 
) ; 
  54 extern void wxMacDestroyGWorld( GWorldPtr gw 
) ; 
  57 ima_png_error(png_struct 
*png_ptr
, char *message
) 
  59         wxMessageBox(message
, "PNG error"); 
  60   longjmp(png_ptr
->jmpbuf
, 1); 
  64 // static wxGifReaderIter* iter; 
  65 wxPalette 
*wxCopyPalette(const wxPalette 
*cmap
); 
  67 wxPNGReader::wxPNGReader(void) 
  70   RawImage 
= NULL
;      //  Image data 
  72   Width 
= 0; Height 
= 0;       //  Dimensions 
  73   Depth 
= 0;           // (bits x pixel) 
  74   ColorType 
= 0;        // Bit 1 = Palette used 
  78   EfeWidth 
= 0;         // Efective Width 
  86 wxPNGReader::wxPNGReader ( char* ImageFileName 
) 
  90   RawImage 
= NULL
;      //  Image data 
  92   Width 
= 0; Height 
= 0;       //  Dimensions 
  93   Depth 
= 0;           // (bits x pixel) 
  94   ColorType 
= 0;        // Bit 1 = m_palette used 
  98   EfeWidth 
= 0;         // Efective Width 
 104   imageOK 
= ReadFile (ImageFileName
); 
 108 wxPNGReader::Create(int width
, int height
, int depth
, int colortype
) 
 110   Width 
= width
; Height 
= height
; Depth 
= depth
; 
 111   ColorType 
= (colortype
>=0) ? colortype
: ((Depth
>8) ? COLORTYPE_COLOR
: 0); 
 119         wxMacDestroyGWorld( lpbi 
) ; 
 121   lpbi 
= wxMacCreateGWorld( Width 
, Height 
, Depth
); 
 124     EfeWidth 
= (long)(((long)Width
*Depth 
+ 31) / 32) * 4; 
 125     int bitwidth 
= width 
; 
 126     if ( EfeWidth 
> bitwidth 
) 
 127         bitwidth 
= EfeWidth 
; 
 129                 RawImage 
= (byte
*) new char[ ( bitwidth 
* Height 
* ((Depth
+7)>>3) ) ]; 
 134 wxPNGReader::~wxPNGReader ( ) 
 138         wxMacDestroyGWorld( lpbi 
) ; 
 144 int wxPNGReader::GetIndex(int x
, int y
) 
 146   if (!Inside(x
, y
) || (Depth
>8)) return -1; 
 148   ImagePointerType ImagePointer 
= RawImage 
+ EfeWidth
*y 
+ (x
*Depth 
>> 3); 
 149   int index 
= (int)(*ImagePointer
); 
 153 bool wxPNGReader::GetRGB(int x
, int y
, byte
* r
, byte
* g
, byte
* b
) 
 155   if (!Inside(x
, y
)) return FALSE
; 
 158    return m_palette
->GetRGB(GetIndex(x
, y
), r
, g
, b
); 
 159 /*   PALETTEENTRY entry; 
 160    ::GetPaletteEntries((HPALETTE) m_palette->GetHPALETTE(), GetIndex(x, y), 1, &entry); 
 163    *b = entry.peBlue;  */ 
 165    ImagePointerType ImagePointer 
= RawImage 
+ EfeWidth
*y 
+ (x
*Depth 
>> 3); 
 166    *b 
= ImagePointer
[0]; 
 167    *g 
= ImagePointer
[1]; 
 168    *r 
= ImagePointer
[2]; 
 174 bool wxPNGReader::SetIndex(int x
, int y
, int index
) 
 176   if (!Inside(x
, y
) || (Depth
>8)) return FALSE
; 
 178   ImagePointerType ImagePointer 
= RawImage 
+ EfeWidth
*y 
+ (x
*Depth 
>> 3); 
 179   *ImagePointer 
= index
; 
 184 bool wxPNGReader::SetRGB(int x
, int y
, byte r
, byte g
, byte b
) 
 186   if (!Inside(x
, y
)) return FALSE
; 
 188   if (ColorType 
& COLORTYPE_PALETTE
) 
 190    if (!m_palette
) return FALSE
; 
 191    SetIndex(x
, y
, m_palette
->GetPixel(r
, g
, b
)); 
 194    ImagePointerType ImagePointer 
= RawImage 
+ EfeWidth
*y 
+ (x
*Depth 
>> 3); 
 203 bool wxPNGReader::SetPalette(wxPalette
* colourmap
) 
 208   ColorType 
|= (COLORTYPE_PALETTE 
| COLORTYPE_COLOR
); 
 209   m_palette 
= new wxPalette( *colourmap 
); 
 211 //  return (DibSetUsage(lpbi, (HPALETTE) m_palette->GetHPALETTE(), WXIMA_COLORS ) != 0); 
 215 wxPNGReader::SetPalette(int n
, byte 
*r
, byte 
*g
, byte 
*b
) 
 218   m_palette 
= new wxPalette(); 
 224   m_palette
->Create(n
, r
, g
, b
); 
 225   ColorType 
|= (COLORTYPE_PALETTE 
| COLORTYPE_COLOR
); 
 227 //    return (DibSetUsage(lpbi, (HPALETTE) m_palette->GetHPALETTE(), WXIMA_COLORS ) != 0); 
 231 wxPNGReader::SetPalette(int n
, rgb_color_struct 
*rgb_struct
) 
 234   m_palette 
= new wxPalette(); 
 238   byte r
[256], g
[256], b
[256]; 
 240   for(int i
=0; i
<n
; i
++) 
 242    r
[i
] = rgb_struct
[i
].red
; 
 243    g
[i
] = rgb_struct
[i
].green
; 
 244    b
[i
] = rgb_struct
[i
].blue
; 
 246   // Added by JACS copying from Andrew Davison's additions 
 247   // to GIF-reading code 
 248   // Make transparency colour black... 
 250     r
[bgindex
] = g
[bgindex
] = b
[bgindex
] = 0; 
 252   m_palette
->Create(n
, r
, g
, b
); 
 253   ColorType 
|= (COLORTYPE_PALETTE 
| COLORTYPE_COLOR
); 
 255 //    return (DibSetUsage(lpbi, (HPALETTE) m_palette->GetHPALETTE(), WXIMA_COLORS ) != 0); 
 258 void wxPNGReader::NullData() 
 261         wxMacDestroyGWorld( lpbi 
) ; 
 268 wxBitmap
* wxPNGReader::GetBitmap(void) 
 270     wxBitmap 
*bitmap 
= new wxBitmap
; 
 271     if ( InstantiateBitmap(bitmap
) ) 
 280 bool wxPNGReader::InstantiateBitmap(wxBitmap 
*bitmap
) 
 284       bitmap
->SetHBITMAP((WXHBITMAP
) lpbi
); 
 285       bitmap
->SetWidth(GetWidth()); 
 286       bitmap
->SetHeight(GetHeight()); 
 287       bitmap
->SetDepth(GetDepth()); 
 288       if ( GetDepth() > 1 && m_palette 
) 
 289         bitmap
->SetPalette(*m_palette
); 
 293       // Make a mask if appropriate 
 297         wxMask *mask = CreateMask(); 
 298         bitmap->SetMask(mask); 
 301       lpbi 
= NULL 
; // bitmap has taken over ownership 
 309   HDC dc = ::CreateCompatibleDC(NULL); 
 313         // tmpBitmap is a dummy, to satisfy ::CreateCompatibleDC (it 
 314         // is a memory dc that must have a bitmap selected into it) 
 315         HDC dc2 = GetDC(NULL); 
 316         HBITMAP tmpBitmap = ::CreateCompatibleBitmap(dc2, GetWidth(), GetHeight()); 
 317         ReleaseDC(NULL, dc2); 
 318         HBITMAP oldBitmap = (HBITMAP) ::SelectObject(dc, tmpBitmap); 
 322             HPALETTE oldPal = ::SelectPalette(dc, (HPALETTE) m_palette->GetHPALETTE(), FALSE); 
 323         ::RealizePalette(dc); 
 326     HBITMAP hBitmap = ::CreateDIBitmap(dc, lpbi, 
 327         CBM_INIT, RawImage, (LPBITMAPINFO) lpbi, DIB_PAL_COLORS); 
 329         ::SelectPalette(dc, NULL, TRUE); 
 330         ::SelectObject(dc, oldBitmap); 
 331         ::DeleteObject(tmpBitmap); 
 336           bitmap->SetHBITMAP((WXHBITMAP) hBitmap); 
 337           bitmap->SetWidth(GetWidth()); 
 338           bitmap->SetHeight(GetHeight()); 
 339           bitmap->SetDepth(GetDepth()); 
 340           if ( GetDepth() > 1 && m_palette ) 
 341             bitmap->SetPalette(*m_palette); 
 345           // Make a mask if appropriate 
 348             wxMask *mask = CreateMask(); 
 349             bitmap->SetMask(mask); 
 366 wxPalette 
*wxCopyPalette(const wxPalette 
*cmap
) 
 368   wxPalette 
*newCmap 
= new wxPalette( *cmap 
) ; 
 372 wxMask 
*wxPNGReader::CreateMask(void) 
 375     HBITMAP hBitmap = ::CreateBitmap(GetWidth(), GetHeight(), 1, 1, NULL); 
 377   HDC dc = ::CreateCompatibleDC(NULL); 
 378     HBITMAP oldBitmap = (HBITMAP) ::SelectObject(dc, hBitmap); 
 380     int bgIndex = GetBGIndex(); 
 384     for (x=0; x<GetWidth(); x++) 
 386         for (y=0; y<GetHeight(); y++) 
 388             int index = GetIndex(x, y); 
 389             if ( index == bgIndex ) 
 390                 ::SetPixel(dc, x, GetHeight() - y - 1, RGB(0, 0, 0)); 
 392                 ::SetPixel(dc, x, GetHeight() - y - 1, RGB(255, 255, 255)); 
 396     ::SelectObject(dc, oldBitmap); 
 397     wxMask *mask = new wxMask; 
 398     mask->SetMaskBitmap((WXHBITMAP) hBitmap); 
 404 bool wxPNGReader::ReadFile(char * ImageFileName
) 
 409    strcpy(filename
, ImageFileName
); 
 414   wxPNGReaderIter 
iter(this); 
 417   fp 
= fopen( ImageFileName 
, "rb" ); 
 422   /* allocate the necessary structures */ 
 423   png_ptr 
= new (png_struct
); 
 430   info_ptr 
= new (png_info
); 
 437   /* set error handling */ 
 438   if (setjmp(png_ptr
->jmpbuf
)) 
 440     png_read_destroy(png_ptr
, info_ptr
, (png_info 
*)0); 
 445     /* If we get here, we had a problem reading the file */ 
 448         //png_set_error(ima_png_error, NULL); 
 450   /* initialize the structures, info first for error handling */ 
 451   png_info_init(info_ptr
); 
 452   png_read_init(png_ptr
); 
 454   /* set up the input control */ 
 455   png_init_io(png_ptr
, fp
); 
 457   /* read the file information */ 
 458   png_read_info(png_ptr
, info_ptr
); 
 460   /* allocate the memory to hold the image using the fields 
 462   png_color_16 my_background
={ 0, 31, 127, 255, 0 }; 
 464   if (info_ptr
->valid 
& PNG_INFO_bKGD
) 
 466     png_set_background(png_ptr
, &(info_ptr
->background
), 
 467       PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0); 
 468         if ( info_ptr
->num_palette 
> 0 ) 
 469             bgindex 
= info_ptr
->background
.index
; 
 472     png_set_background(png_ptr
, &my_background
, 
 473       PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0); 
 475         // Added by JACS: guesswork! 
 476         if ( info_ptr
->num_trans 
!= 0 ) 
 477             bgindex 
= info_ptr
->num_trans 
- 1 ; 
 480   /* tell libpng to strip 16 bit depth files down to 8 bits */ 
 481   if (info_ptr
->bit_depth 
== 16) 
 482     png_set_strip_16(png_ptr
); 
 484   int pixel_depth
=(info_ptr
->pixel_depth
<24) ? info_ptr
->pixel_depth
: 24; 
 485   Create(info_ptr
->width
, info_ptr
->height
, pixel_depth
, 
 486     info_ptr
->color_type
); 
 488   if (info_ptr
->num_palette
>0) 
 490       SetPalette((int)info_ptr
->num_palette
, (rgb_color_struct
*)info_ptr
->palette
); 
 493   int row_stride 
= info_ptr
->width 
* ((pixel_depth
+7)>>3); 
 494  //  printf("P = %d D = %d RS= %d ", info_ptr->num_palette, info_ptr->pixel_depth,row_stride); 
 495 //  printf("CT = %d TRS = %d BD= %d ", info_ptr->color_type, info_ptr->valid & PNG_INFO_tRNS,info_ptr->bit_depth); 
 497   byte 
*row_pointers 
= new byte
[row_stride
]; 
 499   /* turn on interlace handling */ 
 500   if (info_ptr
->interlace_type
) 
 501     number_passes 
= png_set_interlace_handling(png_ptr
); 
 504 //  printf("NP = %d ", number_passes); 
 506   for (int pass
=0; pass
< number_passes
; pass
++)  
 511                 GDHandle        origDevice 
; 
 513                 GetGWorld( &origPort 
, &origDevice 
) ; 
 515                 SetGWorld( lpbi 
, NULL 
) ; 
 518         //    (unsigned char *)iter.GetRow(); 
 519             if (info_ptr
->interlace_type
)   
 522               iter
.GetRow(row_pointers
, row_stride
); 
 523              png_read_row(png_ptr
, row_pointers
, NULL
); 
 526              png_read_row(png_ptr
, row_pointers
, NULL
); 
 528                         if ( info_ptr
->palette 
) 
 530                                 if ( pixel_depth 
== 8 ) 
 532                                         for ( int i 
= 0 ; i 
< info_ptr
->width 
; ++i 
) 
 534                                                 png_color_struct
* color 
;  
 537                                                 int index 
= row_pointers
[i
] ; 
 538                                                 color 
= &info_ptr
->palette
[index
] ; 
 539                                                 col
.red 
= (((int)color
->red
) << 8) | ((int)color
->red
) ; 
 540                                                 col
.green 
= (((int)color
->green
) << 8) | ((int)color
->green
) ; 
 541                                                 col
.blue 
= (((int)color
->blue
) << 8) | ((int)color
->blue
) ; 
 542                                                 SetCPixel( i
, y
, &col
); 
 545                                         png_color_struct* color ;  
 547                                         unsigned char* p = &row_pointers[0] ; 
 551                                         color = &info_ptr->palette[index] ; 
 552                                         col.red = (color->red << 8) | color->red ; 
 553                                         col.green = (color->green << 8) | color->green ; 
 554                                         col.blue = (color->blue << 8) | color->blue ; 
 555                                         RGBForeColor( &col ) ; 
 556                                         col.red = col.green = col.blue = 0xFFFF ; 
 557                                         RGBBackColor( &col ) ; 
 558                                         for ( int i = 0 ; i < info_ptr->width ; ++i , ++p) 
 564                                                         color = &info_ptr->palette[index] ; 
 565                                                         col.red = (((int)color->red) << 8) | ((int)color->red) ; 
 566                                                         col.green = (((int)color->green) << 8) | ((int)color->green) ; 
 567                                                         col.blue = (((int)color->blue) << 8) | ((int)color->blue) ; 
 568                                                         RGBForeColor( &col ) ; 
 571                                         LineTo( info_ptr->width  , y ) ; 
 576                                         for ( int i 
= 0 ; i 
< info_ptr
->width 
; ++i 
) 
 578                                                 png_color_struct
* color 
;  
 581                                                 int byte 
= ( i 
* pixel_depth 
) / 8 ; 
 582                                                 int offset 
= ( 8 - pixel_depth 
) - ( i 
* pixel_depth 
) % 8 ; 
 584                                                 int index 
= ( row_pointers
[byte
] >> offset 
) & ( 0xFF >> ( 8 - pixel_depth 
) ); 
 585                                                 color 
= &info_ptr
->palette
[index
] ; 
 586                                                 col
.red 
= (((int)color
->red
) << 8) | ((int)color
->red
) ; 
 587                                                 col
.green 
= (((int)color
->green
) << 8) | ((int)color
->green
) ; 
 588                                                 col
.blue 
= (((int)color
->blue
) << 8) | ((int)color
->blue
) ; 
 589                                                 SetCPixel( i
, y
, &col
); 
 595                                 for ( int i 
= 0 ; i 
< info_ptr
->width 
; ++i 
) 
 597                                         png_color_struct
* color 
;  
 599                                         color 
=(png_color_struct
*) (&row_pointers
[i
*3]) ; 
 600                                         col
.red 
= (((int)color
->red
) << 8) | ((int)color
->red
) ; 
 601                                         col
.green 
= (((int)color
->green
) << 8) | ((int)color
->green
) ; 
 602                                         col
.blue 
= (((int)color
->blue
) << 8) | ((int)color
->blue
) ; 
 603                                         SetCPixel( i
, y
, &col
); 
 607                                 iter
.SetRow(row_pointers
, row_stride
); 
 610           while(iter
.PrevRow()); 
 611           SetGWorld( origPort 
, origDevice 
) ; 
 613 //  printf("Y=%d ",y); 
 615   delete[] row_pointers
; 
 617   /* read the rest of the file, getting any additional chunks 
 619   png_read_end(png_ptr
, info_ptr
); 
 621   /* clean up after the read, and free any memory allocated */ 
 622   png_read_destroy(png_ptr
, info_ptr
, (png_info 
*)0); 
 624   /* free the structures */ 
 636 /* write a png file */ 
 638 bool wxPNGReader::SaveFile(char * ImageFileName
) 
 641    strcpy(filename
, ImageFileName
); 
 643   wxPNGReaderIter 
iter(this); 
 649   fp 
= fopen(filename
, "wb"); 
 653   /* allocate the necessary structures */ 
 654   png_ptr 
= new (png_struct
); 
 661   info_ptr 
= new (png_info
); 
 669   /* set error handling */ 
 670   if (setjmp(png_ptr
->jmpbuf
)) 
 672     png_write_destroy(png_ptr
); 
 677     /* If we get here, we had a problem reading the file */ 
 680         //png_set_error(ima_png_error, NULL); 
 682 //  printf("writig pg %s ", filename); 
 683    /* initialize the structures */ 
 684   png_info_init(info_ptr
); 
 685   png_write_init(png_ptr
); 
 687   int row_stride 
= GetWidth() * ((GetDepth()+7)>>3); 
 688   /* set up the output control */ 
 689    png_init_io(png_ptr
, fp
); 
 691   /* set the file information here */ 
 692   info_ptr
->width 
= GetWidth(); 
 693   info_ptr
->height 
= GetHeight(); 
 694   info_ptr
->pixel_depth 
= GetDepth(); 
 695   info_ptr
->channels 
= (GetDepth()>8) ? 3: 1; 
 696   info_ptr
->bit_depth 
= GetDepth()/info_ptr
->channels
; 
 697   info_ptr
->color_type 
= GetColorType(); 
 698   info_ptr
->compression_type 
= info_ptr
->filter_type 
= info_ptr
->interlace_type
=0; 
 700   info_ptr
->rowbytes 
= row_stride
; 
 703 // printf("P = %d D = %d RS= %d GD= %d CH= %d ", info_ptr->pixel_depth, info_ptr->bit_depth, row_stride, GetDepth(), info_ptr->channels); 
 704   /* set the palette if there is one */ 
 705   if ((GetColorType() & COLORTYPE_PALETTE
) && GetPalette()) 
 707 //    printf("writing paleta[%d %d %x]",GetColorType() ,COLORTYPE_PALETTE, GetPalette()); 
 708     info_ptr
->valid 
|= PNG_INFO_PLTE
; 
 709     info_ptr
->palette 
= new png_color
[256]; 
 710     info_ptr
->num_palette 
= 256; 
 711     for (int i
=0; i
<256; i
++) 
 712      GetPalette()->GetRGB(i
, &info_ptr
->palette
[i
].red
, &info_ptr
->palette
[i
].green
, &info_ptr
->palette
[i
].blue
); 
 714 //    printf("Paleta [%d %d %x]",GetColorType() ,COLORTYPE_PALETTE, GetPalette()); 
 717    /* optional significant bit chunk */ 
 718 //   info_ptr->valid |= PNG_INFO_sBIT; 
 719 //   info_ptr->sig_bit = true_bit_depth; 
 721   /* optional gamma chunk */ 
 722 //   info_ptr->valid |= PNG_INFO_gAMA; 
 723 //   info_ptr->gamma = gamma; 
 725   /* other optional chunks */ 
 727    /* write the file information */ 
 728    png_write_info(png_ptr
, info_ptr
); 
 730    /* set up the transformations you want.  Note that these are 
 731       all optional.  Only call them if you want them */ 
 733   /* shift the pixels up to a legal bit depth and fill in 
 734       as appropriate to correctly scale the image */ 
 735 //   png_set_shift(png_ptr, &(info_ptr->sig_bit)); 
 737   /* pack pixels into bytes */ 
 738 //   png_set_packing(png_ptr); 
 740   /* flip bgr pixels to rgb */ 
 741 //   png_set_bgr(png_ptr); 
 743    /* swap bytes of 16 bit files to most significant bit first */ 
 744 //   png_set_swap(png_ptr); 
 746    /* get rid of filler bytes, pack rgb into 3 bytes */ 
 747 //   png_set_rgbx(png_ptr); 
 749 /* If you are only writing one row at a time, this works */ 
 751   byte 
*row_pointers 
= new byte
[row_stride
]; 
 754 //    (unsigned char *)iter.GetRow(); 
 755     iter
.GetRow(row_pointers
, row_stride
); 
 756     png_write_row(png_ptr
, row_pointers
); 
 757   } while(iter
.PrevRow()); 
 759         delete[] row_pointers
; 
 761 /* write the rest of the file */ 
 762    png_write_end(png_ptr
, info_ptr
); 
 764   /* clean up after the write, and free any memory allocated */ 
 765    png_write_destroy(png_ptr
); 
 767    /* if you malloced the palette, free it here */ 
 768    if (info_ptr
->palette
) 
 769     delete[] (info_ptr
->palette
); 
 771   /* free the structures */ 
 782 static int Power(int x
, int y
) 
 786     for ( i 
= 0; i 
< y
; i
++) 
 793 static char hexArray
[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 
 794   'C', 'D', 'E', 'F' }; 
 796 static void DecToHex(int dec
, char *buf
) 
 798   int firstDigit 
= (int)(dec
/16.0); 
 799   int secondDigit 
= (int)(dec 
- (firstDigit
*16.0)); 
 800   buf
[0] = hexArray
[firstDigit
]; 
 801   buf
[1] = hexArray
[secondDigit
]; 
 806 bool wxPNGReader::SaveXPM(char *filename
, char *name
) 
 810         strcpy(nameStr
, name
); 
 813         strcpy(nameStr
, filename
); 
 814         wxStripExtension(nameStr
); 
 817     if ( GetDepth() > 4 ) 
 819         // Only a depth of 4 and below allowed 
 826     wxSTD ofstream 
str(filename
); 
 830     int noColours 
= Power(2, GetDepth()); 
 833     str 
<< "/* XPM */\n"; 
 834     str 
<< "static char * " << nameStr 
<< "_xpm[] = {\n"; 
 835     str 
<< "\"" << GetWidth() << " " << GetHeight() << " " << noColours 
<< " 1\",\n"; 
 838     int base 
= 97 ; // start from 'a' 
 840     unsigned char red
, green
, blue
; 
 843     for ( i 
= 0; i 
< noColours
; i 
++) 
 845         str 
<< "\"" << (char)(base 
+ i
) << "      c #"; 
 846         GetPalette()->GetRGB(i
, &red
, &green
, &blue
); 
 847         DecToHex(red
, hexBuf
); 
 849         DecToHex(green
, hexBuf
); 
 851         DecToHex(blue
, hexBuf
); 
 858     for ( y 
= 0; y 
< GetHeight(); y
++) 
 861         for ( x 
= 0; x 
< GetWidth(); x
++) 
 863             int index 
= GetIndex(x
, y
); 
 864             str 
<< (char)(base 
+ index
) ; 
 876 IMPLEMENT_DYNAMIC_CLASS(wxPNGFileHandler
, wxBitmapHandler
) 
 878 bool wxPNGFileHandler::LoadFile(wxBitmap 
*bitmap
, const wxString
& name
, long flags
, 
 879     int desiredWidth
, int desiredHeight
) 
 882     if (reader
.ReadFile((char*) (const char*) name
)) 
 884         return reader
.InstantiateBitmap(bitmap
); 
 890 bool wxPNGFileHandler::SaveFile(const wxBitmap 
*bitmap
, const wxString
& name
, int type
, const wxPalette 
*pal
)