1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Implements a PNG reader class + handler 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  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" 
  42 #include "wx/mac/private.h" 
  48 extern "C" void png_read_init 
PNGARG((png_structp png_ptr
)); 
  49 extern "C" void png_write_init 
PNGARG((png_structp png_ptr
)); 
  51 extern CTabHandle 
wxMacCreateColorTable( int numColors 
) ; 
  52 extern void wxMacDestroyColorTable( CTabHandle colors 
)  ; 
  53 extern void wxMacSetColorTableEntry( CTabHandle newColors 
, int index 
, int red 
, int green 
,  int blue 
) ; 
  54 extern GWorldPtr 
wxMacCreateGWorld( int width 
, int height 
, int depth 
) ; 
  55 extern void wxMacDestroyGWorld( GWorldPtr gw 
) ; 
  58 ima_png_error(png_struct 
*png_ptr
, char *message
) 
  60     wxMessageBox(wxString::FromAscii(message
), wxT("PNG error")); 
  61     longjmp(png_ptr
->jmpbuf
, 1); 
  65 // static wxGifReaderIter* iter; 
  66 wxPalette 
*wxCopyPalette(const wxPalette 
*cmap
); 
  68 wxPNGReader::wxPNGReader(void) 
  71     RawImage 
= NULL
;      //  Image data 
  73     Width 
= 0; Height 
= 0;       //  Dimensions 
  74     Depth 
= 0;           // (bits x pixel) 
  75     ColorType 
= 0;        // Bit 1 = Palette used 
  79     EfeWidth 
= 0;         // Efective Width 
  87 wxPNGReader::wxPNGReader ( char* ImageFileName 
) 
  91     RawImage 
= NULL
;      //  Image data 
  93     Width 
= 0; Height 
= 0;       //  Dimensions 
  94     Depth 
= 0;           // (bits x pixel) 
  95     ColorType 
= 0;        // Bit 1 = m_palette used 
  99     EfeWidth 
= 0;         // Efective Width 
 105     imageOK 
= ReadFile (ImageFileName
); 
 109 wxPNGReader::Create(int width
, int height
, int depth
, int colortype
) 
 111     Width 
= width
; Height 
= height
; Depth 
= depth
; 
 112     ColorType 
= (colortype
>=0) ? colortype
: ((Depth
>8) ? COLORTYPE_COLOR
: 0); 
 119         wxMacDestroyGWorld( (GWorldPtr
) 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 ( ) 
 136     if (RawImage 
!= NULL
) { 
 141         wxMacDestroyGWorld( (GWorldPtr
) lpbi 
) ; 
 144     if (m_palette 
!= NULL
) { 
 151 int wxPNGReader::GetIndex(int x
, int y
) 
 153     if (!Inside(x
, y
) || (Depth
>8)) return -1; 
 155     ImagePointerType ImagePointer 
= RawImage 
+ EfeWidth
*y 
+ (x
*Depth 
>> 3); 
 156     int index 
= (int)(*ImagePointer
); 
 160 bool wxPNGReader::GetRGB(int x
, int y
, byte
* r
, byte
* g
, byte
* b
) 
 162     if (!Inside(x
, y
)) return FALSE
; 
 165         return m_palette
->GetRGB(GetIndex(x
, y
), r
, g
, b
); 
 166         /*   PALETTEENTRY entry; 
 167         ::GetPaletteEntries((HPALETTE) m_palette->GetHPALETTE(), GetIndex(x, y), 1, &entry); 
 170         *b = entry.peBlue;  */ 
 172         ImagePointerType ImagePointer 
= RawImage 
+ EfeWidth
*y 
+ (x
*Depth 
>> 3); 
 173         *b 
= ImagePointer
[0]; 
 174         *g 
= ImagePointer
[1]; 
 175         *r 
= ImagePointer
[2]; 
 181 bool wxPNGReader::SetIndex(int x
, int y
, int index
) 
 183     if (!Inside(x
, y
) || (Depth
>8)) return FALSE
; 
 185     ImagePointerType ImagePointer 
= RawImage 
+ EfeWidth
*y 
+ (x
*Depth 
>> 3); 
 186     *ImagePointer 
= index
; 
 191 bool wxPNGReader::SetRGB(int x
, int y
, byte r
, byte g
, byte b
) 
 193     if (!Inside(x
, y
)) return FALSE
; 
 195     if (ColorType 
& COLORTYPE_PALETTE
) 
 197         if (!m_palette
) return FALSE
; 
 198         SetIndex(x
, y
, m_palette
->GetPixel(r
, g
, b
)); 
 201         ImagePointerType ImagePointer 
= RawImage 
+ EfeWidth
*y 
+ (x
*Depth 
>> 3); 
 210 bool wxPNGReader::SetPalette(wxPalette
* colourmap
) 
 215     ColorType 
|= (COLORTYPE_PALETTE 
| COLORTYPE_COLOR
); 
 216     m_palette 
= new wxPalette( *colourmap 
); 
 218     //  return (DibSetUsage(lpbi, (HPALETTE) m_palette->GetHPALETTE(), WXIMA_COLORS ) != 0); 
 222 wxPNGReader::SetPalette(int n
, byte 
*r
, byte 
*g
, byte 
*b
) 
 225     m_palette 
= new wxPalette(); 
 231     m_palette
->Create(n
, r
, g
, b
); 
 232     ColorType 
|= (COLORTYPE_PALETTE 
| COLORTYPE_COLOR
); 
 234     //    return (DibSetUsage(lpbi, (HPALETTE) m_palette->GetHPALETTE(), WXIMA_COLORS ) != 0); 
 238 wxPNGReader::SetPalette(int n
, rgb_color_struct 
*rgb_struct
) 
 241     m_palette 
= new wxPalette(); 
 245     byte r
[256], g
[256], b
[256]; 
 247     for(int i
=0; i
<n
; i
++) 
 249         r
[i
] = rgb_struct
[i
].red
; 
 250         g
[i
] = rgb_struct
[i
].green
; 
 251         b
[i
] = rgb_struct
[i
].blue
; 
 253     // Added by JACS copying from Andrew Davison's additions 
 254     // to GIF-reading code 
 255     // Make transparency colour black... 
 257         r
[bgindex
] = g
[bgindex
] = b
[bgindex
] = 0; 
 259     m_palette
->Create(n
, r
, g
, b
); 
 260     ColorType 
|= (COLORTYPE_PALETTE 
| COLORTYPE_COLOR
); 
 262     //    return (DibSetUsage(lpbi, (HPALETTE) m_palette->GetHPALETTE(), WXIMA_COLORS ) != 0); 
 265 void wxPNGReader::NullData() 
 268         wxMacDestroyGWorld( (GWorldPtr
) lpbi 
) ; 
 271     if (m_palette 
!= NULL
) { 
 277 wxBitmap
* wxPNGReader::GetBitmap(void) 
 279     wxBitmap 
*bitmap 
= new wxBitmap
; 
 280     if ( InstantiateBitmap(bitmap
) ) 
 289 bool wxPNGReader::InstantiateBitmap(wxBitmap 
*bitmap
) 
 293         bitmap
->SetHBITMAP((WXHBITMAP
) lpbi
); 
 294         bitmap
->SetWidth(GetWidth()); 
 295         bitmap
->SetHeight(GetHeight()); 
 296         bitmap
->SetDepth(GetDepth()); 
 297         if ( GetDepth() > 1 && m_palette 
) 
 298             bitmap
->SetPalette(*m_palette
); 
 302         // Make a mask if appropriate 
 306         wxMask *mask = CreateMask(); 
 307         bitmap->SetMask(mask); 
 310         lpbi 
= NULL 
; // bitmap has taken over ownership 
 318     HDC dc = ::CreateCompatibleDC(NULL); 
 322       // tmpBitmap is a dummy, to satisfy ::CreateCompatibleDC (it 
 323       // is a memory dc that must have a bitmap selected into it) 
 324       HDC dc2 = GetDC(NULL); 
 325       HBITMAP tmpBitmap = ::CreateCompatibleBitmap(dc2, GetWidth(), GetHeight()); 
 326       ReleaseDC(NULL, dc2); 
 327       HBITMAP oldBitmap = (HBITMAP) ::SelectObject(dc, tmpBitmap); 
 331         HPALETTE oldPal = ::SelectPalette(dc, (HPALETTE) m_palette->GetHPALETTE(), FALSE); 
 332         ::RealizePalette(dc); 
 335           HBITMAP hBitmap = ::CreateDIBitmap(dc, lpbi, 
 336           CBM_INIT, RawImage, (LPBITMAPINFO) lpbi, DIB_PAL_COLORS); 
 338             ::SelectPalette(dc, NULL, TRUE); 
 339             ::SelectObject(dc, oldBitmap); 
 340             ::DeleteObject(tmpBitmap); 
 345               bitmap->SetHBITMAP((WXHBITMAP) hBitmap); 
 346               bitmap->SetWidth(GetWidth()); 
 347               bitmap->SetHeight(GetHeight()); 
 348               bitmap->SetDepth(GetDepth()); 
 349               if ( GetDepth() > 1 && m_palette ) 
 350               bitmap->SetPalette(*m_palette); 
 354                   // Make a mask if appropriate 
 357                   wxMask *mask = CreateMask(); 
 358                   bitmap->SetMask(mask); 
 375 wxPalette 
*wxCopyPalette(const wxPalette 
*cmap
) 
 377     wxPalette 
*newCmap 
= new wxPalette( *cmap 
) ; 
 381 wxMask 
*wxPNGReader::CreateMask(void) 
 384 HBITMAP hBitmap = ::CreateBitmap(GetWidth(), GetHeight(), 1, 1, NULL); 
 386   HDC dc = ::CreateCompatibleDC(NULL); 
 387   HBITMAP oldBitmap = (HBITMAP) ::SelectObject(dc, hBitmap); 
 389     int bgIndex = GetBGIndex(); 
 393         for (x=0; x<GetWidth(); x++) 
 395         for (y=0; y<GetHeight(); y++) 
 397         int index = GetIndex(x, y); 
 398         if ( index == bgIndex ) 
 399         ::SetPixel(dc, x, GetHeight() - y - 1, RGB(0, 0, 0)); 
 401         ::SetPixel(dc, x, GetHeight() - y - 1, RGB(255, 255, 255)); 
 405           ::SelectObject(dc, oldBitmap); 
 406           wxMask *mask = new wxMask; 
 407           mask->SetMaskBitmap((WXHBITMAP) hBitmap); 
 413 bool wxPNGReader::ReadFile(char * ImageFileName
) 
 418         strcpy(filename
, ImageFileName
); 
 423     wxPNGReaderIter 
iter(this); 
 426     fp 
= fopen( ImageFileName 
, "rb" ); 
 431     /* allocate the necessary structures */ 
 432     png_ptr 
= new (png_struct
); 
 439     info_ptr 
= new (png_info
); 
 446     /* set error handling */ 
 447     if (setjmp(png_ptr
->jmpbuf
)) 
 449         png_read_destroy(png_ptr
, info_ptr
, (png_info 
*)0); 
 454         /* If we get here, we had a problem reading the file */ 
 457     //png_set_error(ima_png_error, NULL); 
 459     /* initialize the structures, info first for error handling */ 
 460     png_info_init(info_ptr
); 
 461     png_read_init(png_ptr
); 
 463     /* set up the input control */ 
 464     png_init_io(png_ptr
, fp
); 
 466     /* read the file information */ 
 467     png_read_info(png_ptr
, info_ptr
); 
 469     /* allocate the memory to hold the image using the fields 
 471     png_color_16 my_background
={ 0, 31, 127, 255, 0 }; 
 473     if (info_ptr
->valid 
& PNG_INFO_bKGD
) 
 475         png_set_background(png_ptr
, &(info_ptr
->background
), 
 476             PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0); 
 477         if ( info_ptr
->num_palette 
> 0 ) 
 478             bgindex 
= info_ptr
->background
.index
; 
 481         png_set_background(png_ptr
, &my_background
, 
 482             PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0); 
 484         // Added by JACS: guesswork! 
 485         if ( info_ptr
->num_trans 
!= 0 ) 
 486             bgindex 
= info_ptr
->num_trans 
- 1 ; 
 489     /* tell libpng to strip 16 bit depth files down to 8 bits */ 
 490     if (info_ptr
->bit_depth 
== 16) 
 491         png_set_strip_16(png_ptr
); 
 493     int pixel_depth
=(info_ptr
->pixel_depth
<24) ? info_ptr
->pixel_depth
: 24; 
 494     Create(info_ptr
->width
, info_ptr
->height
, pixel_depth
, 
 495         info_ptr
->color_type
); 
 497     if (info_ptr
->num_palette
>0) 
 499         SetPalette((int)info_ptr
->num_palette
, (rgb_color_struct
*)info_ptr
->palette
); 
 502     int row_stride 
= info_ptr
->width 
* ((pixel_depth
+7)>>3); 
 503     //  printf("P = %d D = %d RS= %d ", info_ptr->num_palette, info_ptr->pixel_depth,row_stride); 
 504     //  printf("CT = %d TRS = %d BD= %d ", info_ptr->color_type, info_ptr->valid & PNG_INFO_tRNS,info_ptr->bit_depth); 
 506     byte 
*row_pointers 
= new byte
[row_stride
]; 
 508     /* turn on interlace handling */ 
 509     if (info_ptr
->interlace_type
) 
 510         number_passes 
= png_set_interlace_handling(png_ptr
); 
 513     //  printf("NP = %d ", number_passes); 
 515     for (int pass
=0; pass
< number_passes
; pass
++)  
 520         GDHandle    origDevice 
; 
 522         GetGWorld( &origPort 
, &origDevice 
) ; 
 524         SetGWorld( (GWorldPtr
) lpbi 
, NULL 
) ; 
 527             //    (unsigned char *)iter.GetRow(); 
 528             if (info_ptr
->interlace_type
)   
 531                     iter
.GetRow(row_pointers
, row_stride
); 
 532                 png_read_row(png_ptr
, row_pointers
, NULL
); 
 535                 png_read_row(png_ptr
, row_pointers
, NULL
); 
 537             if ( info_ptr
->palette 
) 
 539                 if ( pixel_depth 
== 8 ) 
 541                     for ( size_t i 
= 0 ; i 
< info_ptr
->width 
; ++i 
) 
 543                         png_color_struct
* color 
;  
 546                         int index 
= row_pointers
[i
] ; 
 547                         color 
= &info_ptr
->palette
[index
] ; 
 548                         col
.red 
= (((int)color
->red
) << 8) | ((int)color
->red
) ; 
 549                         col
.green 
= (((int)color
->green
) << 8) | ((int)color
->green
) ; 
 550                         col
.blue 
= (((int)color
->blue
) << 8) | ((int)color
->blue
) ; 
 551                         SetCPixel( i
, y
, &col
); 
 554                     png_color_struct* color ;  
 556                     unsigned char* p = &row_pointers[0] ; 
 560                     color = &info_ptr->palette[index] ; 
 561                     col.red = (color->red << 8) | color->red ; 
 562                     col.green = (color->green << 8) | color->green ; 
 563                     col.blue = (color->blue << 8) | color->blue ; 
 564                     RGBForeColor( &col ) ; 
 565                     col.red = col.green = col.blue = 0xFFFF ; 
 566                     RGBBackColor( &col ) ; 
 567                     for ( int i = 0 ; i < info_ptr->width ; ++i , ++p) 
 573                     color = &info_ptr->palette[index] ; 
 574                     col.red = (((int)color->red) << 8) | ((int)color->red) ; 
 575                     col.green = (((int)color->green) << 8) | ((int)color->green) ; 
 576                     col.blue = (((int)color->blue) << 8) | ((int)color->blue) ; 
 577                     RGBForeColor( &col ) ; 
 580                     LineTo( info_ptr->width  , y ) ; 
 585                     for ( size_t i 
= 0 ; i 
< info_ptr
->width 
; ++i 
) 
 587                         png_color_struct
* color 
;  
 590                         int byte 
= ( i 
* pixel_depth 
) / 8 ; 
 591                         int offset 
= ( 8 - pixel_depth 
) - ( i 
* pixel_depth 
) % 8 ; 
 593                         int index 
= ( row_pointers
[byte
] >> offset 
) & ( 0xFF >> ( 8 - pixel_depth 
) ); 
 594                         color 
= &info_ptr
->palette
[index
] ; 
 595                         col
.red 
= (((int)color
->red
) << 8) | ((int)color
->red
) ; 
 596                         col
.green 
= (((int)color
->green
) << 8) | ((int)color
->green
) ; 
 597                         col
.blue 
= (((int)color
->blue
) << 8) | ((int)color
->blue
) ; 
 598                         SetCPixel( i
, y
, &col
); 
 604                 for ( size_t i 
= 0 ; i 
< info_ptr
->width 
; ++i 
) 
 606                     png_color_struct
* color 
;  
 608                     color 
=(png_color_struct
*) (&row_pointers
[i
*3]) ; 
 609                     col
.red 
= (((int)color
->red
) << 8) | ((int)color
->red
) ; 
 610                     col
.green 
= (((int)color
->green
) << 8) | ((int)color
->green
) ; 
 611                     col
.blue 
= (((int)color
->blue
) << 8) | ((int)color
->blue
) ; 
 612                     SetCPixel( i
, y
, &col
); 
 616                 iter
.SetRow(row_pointers
, row_stride
); 
 619         while(iter
.PrevRow()); 
 620         SetGWorld( origPort 
, origDevice 
) ; 
 622         //  printf("Y=%d ",y); 
 624   delete[] row_pointers
; 
 626   /* read the rest of the file, getting any additional chunks 
 628   png_read_end(png_ptr
, info_ptr
); 
 630   /* clean up after the read, and free any memory allocated */ 
 631   png_read_destroy(png_ptr
, info_ptr
, (png_info 
*)0); 
 633   /* free the structures */ 
 645 /* write a png file */ 
 647 bool wxPNGReader::SaveFile(char * ImageFileName
) 
 650         strcpy(filename
, ImageFileName
); 
 652     wxPNGReaderIter 
iter(this); 
 658     fp 
= fopen(filename
, "wb"); 
 662     /* allocate the necessary structures */ 
 663     png_ptr 
= new (png_struct
); 
 670     info_ptr 
= new (png_info
); 
 678     /* set error handling */ 
 679     if (setjmp(png_ptr
->jmpbuf
)) 
 681         png_write_destroy(png_ptr
); 
 686         /* If we get here, we had a problem reading the file */ 
 689     //png_set_error(ima_png_error, NULL); 
 691     //  printf("writig pg %s ", filename); 
 692     /* initialize the structures */ 
 693     png_info_init(info_ptr
); 
 694     png_write_init(png_ptr
); 
 696     int row_stride 
= GetWidth() * ((GetDepth()+7)>>3); 
 697     /* set up the output control */ 
 698     png_init_io(png_ptr
, fp
); 
 700     /* set the file information here */ 
 701     info_ptr
->width 
= GetWidth(); 
 702     info_ptr
->height 
= GetHeight(); 
 703     info_ptr
->pixel_depth 
= GetDepth(); 
 704     info_ptr
->channels 
= (GetDepth()>8) ? 3: 1; 
 705     info_ptr
->bit_depth 
= GetDepth()/info_ptr
->channels
; 
 706     info_ptr
->color_type 
= GetColorType(); 
 707     info_ptr
->compression_type 
= info_ptr
->filter_type 
= info_ptr
->interlace_type
=0; 
 709     info_ptr
->rowbytes 
= row_stride
; 
 712     // 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); 
 713     /* set the palette if there is one */ 
 714     if ((GetColorType() & COLORTYPE_PALETTE
) && GetPalette()) 
 716         //    printf("writing paleta[%d %d %x]",GetColorType() ,COLORTYPE_PALETTE, GetPalette()); 
 717         info_ptr
->valid 
|= PNG_INFO_PLTE
; 
 718         info_ptr
->palette 
= new png_color
[256]; 
 719         info_ptr
->num_palette 
= 256; 
 720         for (int i
=0; i
<256; i
++) 
 721             GetPalette()->GetRGB(i
, &info_ptr
->palette
[i
].red
, &info_ptr
->palette
[i
].green
, &info_ptr
->palette
[i
].blue
); 
 723     //    printf("Paleta [%d %d %x]",GetColorType() ,COLORTYPE_PALETTE, GetPalette()); 
 726     /* optional significant bit chunk */ 
 727     //   info_ptr->valid |= PNG_INFO_sBIT; 
 728     //   info_ptr->sig_bit = true_bit_depth; 
 730     /* optional gamma chunk */ 
 731     //   info_ptr->valid |= PNG_INFO_gAMA; 
 732     //   info_ptr->gamma = gamma; 
 734     /* other optional chunks */ 
 736     /* write the file information */ 
 737     png_write_info(png_ptr
, info_ptr
); 
 739     /* set up the transformations you want.  Note that these are 
 740     all optional.  Only call them if you want them */ 
 742     /* shift the pixels up to a legal bit depth and fill in 
 743     as appropriate to correctly scale the image */ 
 744     //   png_set_shift(png_ptr, &(info_ptr->sig_bit)); 
 746     /* pack pixels into bytes */ 
 747     //   png_set_packing(png_ptr); 
 749     /* flip bgr pixels to rgb */ 
 750     //   png_set_bgr(png_ptr); 
 752     /* swap bytes of 16 bit files to most significant bit first */ 
 753     //   png_set_swap(png_ptr); 
 755     /* get rid of filler bytes, pack rgb into 3 bytes */ 
 756     //   png_set_rgbx(png_ptr); 
 758     /* If you are only writing one row at a time, this works */ 
 760     byte 
*row_pointers 
= new byte
[row_stride
]; 
 763         //    (unsigned char *)iter.GetRow(); 
 764         iter
.GetRow(row_pointers
, row_stride
); 
 765         png_write_row(png_ptr
, row_pointers
); 
 766     } while(iter
.PrevRow()); 
 768     delete[] row_pointers
; 
 770     /* write the rest of the file */ 
 771     png_write_end(png_ptr
, info_ptr
); 
 773     /* clean up after the write, and free any memory allocated */ 
 774     png_write_destroy(png_ptr
); 
 776     /* if you malloced the palette, free it here */ 
 777     if (info_ptr
->palette
) 
 778         delete[] (info_ptr
->palette
); 
 780     /* free the structures */ 
 791 static int Power(int x
, int y
) 
 795     for ( i 
= 0; i 
< y
; i
++) 
 802 static char hexArray
[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 
 803 'C', 'D', 'E', 'F' }; 
 805 static void DecToHex(int dec
, char *buf
) 
 807     int firstDigit 
= (int)(dec
/16.0); 
 808     int secondDigit 
= (int)(dec 
- (firstDigit
*16.0)); 
 809     buf
[0] = hexArray
[firstDigit
]; 
 810     buf
[1] = hexArray
[secondDigit
]; 
 815 bool wxPNGReader::SaveXPM(char *filename
, char *name
) 
 819         strcpy(nameStr
, name
); 
 822         wxString str 
= wxString::FromAscii(filename
) ; 
 823         wxStripExtension( str 
) ; 
 824         strcpy(nameStr
, str
.ToAscii() ); 
 827     if ( GetDepth() > 4 ) 
 829         // Only a depth of 4 and below allowed 
 836     wxSTD ofstream 
str(filename
); 
 840     int noColours 
= Power(2, GetDepth()); 
 843     str 
<< "/* XPM */\n"; 
 844     str 
<< "static char * " << nameStr 
<< "_xpm[] = {\n"; 
 845     str 
<< "\"" << GetWidth() << " " << GetHeight() << " " << noColours 
<< " 1\",\n"; 
 848     int base 
= 97 ; // start from 'a' 
 850     unsigned char red
, green
, blue
; 
 853     for ( i 
= 0; i 
< noColours
; i 
++) 
 855         str 
<< "\"" << (char)(base 
+ i
) << "      c #"; 
 856         GetPalette()->GetRGB(i
, &red
, &green
, &blue
); 
 857         DecToHex(red
, hexBuf
); 
 859         DecToHex(green
, hexBuf
); 
 861         DecToHex(blue
, hexBuf
); 
 868     for ( y 
= 0; y 
< GetHeight(); y
++) 
 871         for ( x 
= 0; x 
< GetWidth(); x
++) 
 873             int index 
= GetIndex(x
, y
); 
 874             str 
<< (char)(base 
+ index
) ; 
 886 IMPLEMENT_DYNAMIC_CLASS(wxPNGFileHandler
, wxBitmapHandler
) 
 888 bool wxPNGFileHandler::LoadFile(wxBitmap 
*bitmap
, const wxString
& name
, long flags
, 
 889                                 int desiredWidth
, int desiredHeight
) 
 892     if (reader
.ReadFile( (char*)(const char*) name
.ToAscii() ) ) 
 894         return reader
.InstantiateBitmap(bitmap
); 
 900 bool wxPNGFileHandler::SaveFile(const wxBitmap 
*bitmap
, const wxString
& name
, int type
, const wxPalette 
*pal
)