]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/pnghand.cpp
fixed bug introduced in prior check-ins; minor reformatting
[wxWidgets.git] / src / mac / carbon / pnghand.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: pnghand.cpp
3 // Purpose: Implements a PNG reader class + handler
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 # pragma hdrstop
17 #endif
18
19 #if 0 // wxUSE_LIBPNG
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24
25 #if defined(__DARWIN__)
26 /* MW's math routines do certain things if __FP__ (the include guard around
27 CarbonCore's fp.h) is defined. CarbonCore's fp.h does certain things if
28 __cmath__ is defined so it seems the easy thing to do is to make sure
29 __cmath__ is effectively not defined which counteracts the MWERKS check
30 then when the real cmath is included everything will be okay.
31 */
32 #include <CoreServices/CoreServices.h>
33 //#include <cmath>
34 #endif //defined(__DARWIN__)
35
36 #if wxUSE_IOSTREAMH
37 # include <fstream.h>
38 #else
39 # include <fstream>
40 #endif
41
42 #ifndef __DARWIN__
43 # include <windows.h>
44 #endif
45 #include "wx/msgdlg.h"
46 #include "wx/palette.h"
47 #include "wx/bitmap.h"
48 #include "wx/mac/pnghand.h"
49 #include "wx/mac/pngread.h"
50 #include "wx/mac/private.h"
51
52 extern "C" {
53 #include "png.h"
54 }
55
56 extern "C" void png_read_init PNGARG((png_structp png_ptr));
57 extern "C" void png_write_init PNGARG((png_structp png_ptr));
58
59 extern CTabHandle wxMacCreateColorTable( int numColors ) ;
60 extern void wxMacDestroyColorTable( CTabHandle colors ) ;
61 extern void wxMacSetColorTableEntry( CTabHandle newColors , int index , int red , int green , int blue ) ;
62 extern GWorldPtr wxMacCreateGWorld( int width , int height , int depth ) ;
63 extern void wxMacDestroyGWorld( GWorldPtr gw ) ;
64
65 void
66 ima_png_error(png_struct *png_ptr, char *message)
67 {
68 wxMessageBox(wxString::FromAscii(message), wxT("PNG error"));
69 longjmp(png_ptr->jmpbuf, 1);
70 }
71
72
73 // static wxGifReaderIter* iter;
74 wxPalette *wxCopyPalette(const wxPalette *cmap);
75
76 wxPNGReader::wxPNGReader(void)
77 {
78 filetype = 0;
79 RawImage = NULL; // Image data
80
81 Width = 0; Height = 0; // Dimensions
82 Depth = 0; // (bits x pixel)
83 ColorType = 0; // Bit 1 = Palette used
84 // Bit 2 = Color used
85 // Bit 3 = Alpha used
86
87 EfeWidth = 0; // Efective Width
88
89 lpbi = NULL;
90 bgindex = -1;
91 m_palette = 0;
92 imageOK = FALSE;
93 }
94
95 wxPNGReader::wxPNGReader ( char* ImageFileName )
96 {
97 imageOK = FALSE;
98 filetype = 0;
99 RawImage = NULL; // Image data
100
101 Width = 0; Height = 0; // Dimensions
102 Depth = 0; // (bits x pixel)
103 ColorType = 0; // Bit 1 = m_palette used
104 // Bit 2 = Color used
105 // Bit 3 = Alpha used
106
107 EfeWidth = 0; // Efective Width
108
109 lpbi = NULL;
110 bgindex = -1;
111 m_palette = 0;
112
113 imageOK = ReadFile (ImageFileName);
114 }
115
116 void
117 wxPNGReader::Create(int width, int height, int depth, int colortype)
118 {
119 Width = width; Height = height; Depth = depth;
120 ColorType = (colortype>=0) ? colortype: ((Depth>8) ? COLORTYPE_COLOR: 0);
121 delete m_palette;
122 m_palette = NULL;
123 delete[] RawImage;
124 RawImage = NULL;
125
126 if (lpbi) {
127 wxMacDestroyGWorld( (GWorldPtr) lpbi ) ;
128 }
129 lpbi = wxMacCreateGWorld( Width , Height , Depth);
130 if (lpbi)
131 {
132 EfeWidth = (long)(((long)Width*Depth + 31) / 32) * 4;
133 int bitwidth = width ;
134 if ( EfeWidth > bitwidth )
135 bitwidth = EfeWidth ;
136
137 RawImage = (byte*) new char[ ( bitwidth * Height * ((Depth+7)>>3) ) ];
138 imageOK = TRUE;
139 }
140 }
141
142 wxPNGReader::~wxPNGReader ( )
143 {
144 if (RawImage != NULL) {
145 delete[] RawImage ;
146 RawImage = NULL;
147 }
148 if (lpbi) {
149 wxMacDestroyGWorld( (GWorldPtr) lpbi ) ;
150 lpbi = NULL;
151 }
152 if (m_palette != NULL) {
153 delete m_palette;
154 m_palette = NULL;
155 }
156 }
157
158
159 int wxPNGReader::GetIndex(int x, int y)
160 {
161 if (!Inside(x, y) || (Depth>8)) return -1;
162
163 ImagePointerType ImagePointer = RawImage + EfeWidth*y + (x*Depth >> 3);
164 int index = (int)(*ImagePointer);
165 return index;
166 }
167
168 bool wxPNGReader::GetRGB(int x, int y, byte* r, byte* g, byte* b)
169 {
170 if (!Inside(x, y)) return FALSE;
171
172 if (m_palette) {
173 return m_palette->GetRGB(GetIndex(x, y), r, g, b);
174 /* PALETTEENTRY entry;
175 ::GetPaletteEntries((HPALETTE) m_palette->GetHPALETTE(), GetIndex(x, y), 1, &entry);
176 *r = entry.peRed;
177 *g = entry.peGreen;
178 *b = entry.peBlue; */
179 } else {
180 ImagePointerType ImagePointer = RawImage + EfeWidth*y + (x*Depth >> 3);
181 *b = ImagePointer[0];
182 *g = ImagePointer[1];
183 *r = ImagePointer[2];
184 }
185 return TRUE;
186 }
187
188
189 bool wxPNGReader::SetIndex(int x, int y, int index)
190 {
191 if (!Inside(x, y) || (Depth>8)) return FALSE;
192
193 ImagePointerType ImagePointer = RawImage + EfeWidth*y + (x*Depth >> 3);
194 *ImagePointer = index;
195
196 return TRUE;
197 }
198
199 bool wxPNGReader::SetRGB(int x, int y, byte r, byte g, byte b)
200 {
201 if (!Inside(x, y)) return FALSE;
202
203 if (ColorType & COLORTYPE_PALETTE)
204 {
205 if (!m_palette) return FALSE;
206 SetIndex(x, y, m_palette->GetPixel(r, g, b));
207
208 } else {
209 ImagePointerType ImagePointer = RawImage + EfeWidth*y + (x*Depth >> 3);
210 ImagePointer[0] = b;
211 ImagePointer[1] = g;
212 ImagePointer[2] = r;
213 }
214
215 return TRUE;
216 }
217
218 bool wxPNGReader::SetPalette(wxPalette* colourmap)
219 {
220 delete m_palette ;
221 if (!colourmap)
222 return FALSE;
223 ColorType |= (COLORTYPE_PALETTE | COLORTYPE_COLOR);
224 m_palette = new wxPalette( *colourmap );
225 return true ;
226 // return (DibSetUsage(lpbi, (HPALETTE) m_palette->GetHPALETTE(), WXIMA_COLORS ) != 0);
227 }
228
229 bool
230 wxPNGReader::SetPalette(int n, byte *r, byte *g, byte *b)
231 {
232 delete m_palette ;
233 m_palette = new wxPalette();
234 if (!m_palette)
235 return FALSE;
236
237 if (!g) g = r;
238 if (!b) b = g;
239 m_palette->Create(n, r, g, b);
240 ColorType |= (COLORTYPE_PALETTE | COLORTYPE_COLOR);
241 return true ;
242 // return (DibSetUsage(lpbi, (HPALETTE) m_palette->GetHPALETTE(), WXIMA_COLORS ) != 0);
243 }
244
245 bool
246 wxPNGReader::SetPalette(int n, rgb_color_struct *rgb_struct)
247 {
248 delete m_palette ;
249 m_palette = new wxPalette();
250 if (!m_palette)
251 return FALSE;
252
253 byte r[256], g[256], b[256];
254
255 for(int i=0; i<n; i++)
256 {
257 r[i] = rgb_struct[i].red;
258 g[i] = rgb_struct[i].green;
259 b[i] = rgb_struct[i].blue;
260 }
261 // Added by JACS copying from Andrew Davison's additions
262 // to GIF-reading code
263 // Make transparency colour black...
264 if (bgindex != -1)
265 r[bgindex] = g[bgindex] = b[bgindex] = 0;
266
267 m_palette->Create(n, r, g, b);
268 ColorType |= (COLORTYPE_PALETTE | COLORTYPE_COLOR);
269 return true ;
270 // return (DibSetUsage(lpbi, (HPALETTE) m_palette->GetHPALETTE(), WXIMA_COLORS ) != 0);
271 }
272
273 void wxPNGReader::NullData()
274 {
275 if (lpbi) {
276 wxMacDestroyGWorld( (GWorldPtr) lpbi ) ;
277 lpbi = NULL;
278 }
279 if (m_palette != NULL) {
280 delete m_palette;
281 m_palette = NULL;
282 }
283 }
284
285 wxBitmap* wxPNGReader::GetBitmap(void)
286 {
287 wxBitmap *bitmap = new wxBitmap;
288 if ( InstantiateBitmap(bitmap) )
289 return bitmap;
290 else
291 {
292 delete bitmap;
293 return NULL;
294 }
295 }
296
297 bool wxPNGReader::InstantiateBitmap(wxBitmap *bitmap)
298 {
299 if ( lpbi )
300 {
301 bitmap->SetHBITMAP((WXHBITMAP) lpbi);
302 bitmap->SetWidth(GetWidth());
303 bitmap->SetHeight(GetHeight());
304 bitmap->SetDepth(GetDepth());
305 if ( GetDepth() > 1 && m_palette )
306 bitmap->SetPalette(*m_palette);
307 bitmap->SetOk(TRUE);
308
309
310 // Make a mask if appropriate
311 /*
312 if ( bgindex > -1 )
313 {
314 wxMask *mask = CreateMask();
315 bitmap->SetMask(mask);
316 }
317 */
318 lpbi = NULL ; // bitmap has taken over ownership
319 return TRUE;
320 }
321 else
322 {
323 return FALSE;
324 }
325 /*
326 HDC dc = ::CreateCompatibleDC(NULL);
327
328 if (dc)
329 {
330 // tmpBitmap is a dummy, to satisfy ::CreateCompatibleDC (it
331 // is a memory dc that must have a bitmap selected into it)
332 HDC dc2 = GetDC(NULL);
333 HBITMAP tmpBitmap = ::CreateCompatibleBitmap(dc2, GetWidth(), GetHeight());
334 ReleaseDC(NULL, dc2);
335 HBITMAP oldBitmap = (HBITMAP) ::SelectObject(dc, tmpBitmap);
336
337 if ( m_palette )
338 {
339 HPALETTE oldPal = ::SelectPalette(dc, (HPALETTE) m_palette->GetHPALETTE(), FALSE);
340 ::RealizePalette(dc);
341 }
342
343 HBITMAP hBitmap = ::CreateDIBitmap(dc, lpbi,
344 CBM_INIT, RawImage, (LPBITMAPINFO) lpbi, DIB_PAL_COLORS);
345
346 ::SelectPalette(dc, NULL, TRUE);
347 ::SelectObject(dc, oldBitmap);
348 ::DeleteObject(tmpBitmap);
349 ::DeleteDC(dc);
350
351 if ( hBitmap )
352 {
353 bitmap->SetHBITMAP((WXHBITMAP) hBitmap);
354 bitmap->SetWidth(GetWidth());
355 bitmap->SetHeight(GetHeight());
356 bitmap->SetDepth(GetDepth());
357 if ( GetDepth() > 1 && m_palette )
358 bitmap->SetPalette(*m_palette);
359 bitmap->SetOk(TRUE);
360
361
362 // Make a mask if appropriate
363 if ( bgindex > -1 )
364 {
365 wxMask *mask = CreateMask();
366 bitmap->SetMask(mask);
367 }
368 return TRUE;
369 }
370 else
371 {
372 return FALSE;
373 }
374 }
375 else
376 {
377 return FALSE;
378 }
379 */
380 return false ;
381 }
382
383 wxPalette *wxCopyPalette(const wxPalette *cmap)
384 {
385 wxPalette *newCmap = new wxPalette( *cmap ) ;
386 return newCmap;
387 }
388
389 wxMask *wxPNGReader::CreateMask(void)
390 {
391 /*
392 HBITMAP hBitmap = ::CreateBitmap(GetWidth(), GetHeight(), 1, 1, NULL);
393
394 HDC dc = ::CreateCompatibleDC(NULL);
395 HBITMAP oldBitmap = (HBITMAP) ::SelectObject(dc, hBitmap);
396
397 int bgIndex = GetBGIndex();
398
399 int x,y;
400
401 for (x=0; x<GetWidth(); x++)
402 {
403 for (y=0; y<GetHeight(); y++)
404 {
405 int index = GetIndex(x, y);
406 if ( index == bgIndex )
407 ::SetPixel(dc, x, GetHeight() - y - 1, RGB(0, 0, 0));
408 else
409 ::SetPixel(dc, x, GetHeight() - y - 1, RGB(255, 255, 255));
410
411 }
412 }
413 ::SelectObject(dc, oldBitmap);
414 wxMask *mask = new wxMask;
415 mask->SetMaskBitmap((WXHBITMAP) hBitmap);
416 return mask;
417 */
418 return NULL ;
419 }
420
421 bool wxPNGReader::ReadFile(char * ImageFileName)
422 {
423 int number_passes;
424
425 if (ImageFileName)
426 strcpy(filename, ImageFileName);
427
428 FILE *fp;
429 png_struct *png_ptr;
430 png_info *info_ptr;
431 wxPNGReaderIter iter(this);
432
433 /* open the file */
434 fp = fopen( ImageFileName , "rb" );
435
436 if (!fp)
437 return FALSE;
438
439 /* allocate the necessary structures */
440 png_ptr = new (png_struct);
441 if (!png_ptr)
442 {
443 fclose(fp);
444 return FALSE;
445 }
446
447 info_ptr = new (png_info);
448 if (!info_ptr)
449 {
450 fclose(fp);
451 delete png_ptr;
452 return FALSE;
453 }
454 /* set error handling */
455 if (setjmp(png_ptr->jmpbuf))
456 {
457 png_read_destroy(png_ptr, info_ptr, (png_info *)0);
458 fclose(fp);
459 delete png_ptr;
460 delete info_ptr;
461
462 /* If we get here, we had a problem reading the file */
463 return FALSE;
464 }
465 //png_set_error(ima_png_error, NULL);
466
467 /* initialize the structures, info first for error handling */
468 png_info_init(info_ptr);
469 png_read_init(png_ptr);
470
471 /* set up the input control */
472 png_init_io(png_ptr, fp);
473
474 /* read the file information */
475 png_read_info(png_ptr, info_ptr);
476
477 /* allocate the memory to hold the image using the fields
478 of png_info. */
479 png_color_16 my_background={ 0, 31, 127, 255, 0 };
480
481 if (info_ptr->valid & PNG_INFO_bKGD)
482 {
483 png_set_background(png_ptr, &(info_ptr->background),
484 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
485 if ( info_ptr->num_palette > 0 )
486 bgindex = info_ptr->background.index;
487 }
488 else {
489 png_set_background(png_ptr, &my_background,
490 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
491
492 // Added by JACS: guesswork!
493 if ( info_ptr->num_trans != 0 )
494 bgindex = info_ptr->num_trans - 1 ;
495 }
496
497 /* tell libpng to strip 16 bit depth files down to 8 bits */
498 if (info_ptr->bit_depth == 16)
499 png_set_strip_16(png_ptr);
500
501 int pixel_depth=(info_ptr->pixel_depth<24) ? info_ptr->pixel_depth: 24;
502 Create(info_ptr->width, info_ptr->height, pixel_depth,
503 info_ptr->color_type);
504
505 if (info_ptr->num_palette>0)
506 {
507 SetPalette((int)info_ptr->num_palette, (rgb_color_struct*)info_ptr->palette);
508 }
509
510 int row_stride = info_ptr->width * ((pixel_depth+7)>>3);
511 // printf("P = %d D = %d RS= %d ", info_ptr->num_palette, info_ptr->pixel_depth,row_stride);
512 // printf("CT = %d TRS = %d BD= %d ", info_ptr->color_type, info_ptr->valid & PNG_INFO_tRNS,info_ptr->bit_depth);
513
514 byte *row_pointers = new byte[row_stride];
515
516 /* turn on interlace handling */
517 if (info_ptr->interlace_type)
518 number_passes = png_set_interlace_handling(png_ptr);
519 else
520 number_passes = 1;
521 // printf("NP = %d ", number_passes);
522
523 for (int pass=0; pass< number_passes; pass++)
524 {
525 iter.upset();
526 int y=0;
527 CGrafPtr origPort ;
528 GDHandle origDevice ;
529
530 GetGWorld( &origPort , &origDevice ) ;
531 // ignore shapedc
532 SetGWorld( (GWorldPtr) lpbi , NULL ) ;
533 do
534 {
535 // (unsigned char *)iter.GetRow();
536 if (info_ptr->interlace_type)
537 {
538 if (pass>0)
539 iter.GetRow(row_pointers, row_stride);
540 png_read_row(png_ptr, row_pointers, NULL);
541 }
542 else
543 png_read_row(png_ptr, row_pointers, NULL);
544
545 if ( info_ptr->palette )
546 {
547 if ( pixel_depth == 8 )
548 {
549 for ( size_t i = 0 ; i < info_ptr->width ; ++i )
550 {
551 png_color_struct* color ;
552 RGBColor col ;
553
554 int index = row_pointers[i] ;
555 color = &info_ptr->palette[index] ;
556 col.red = (((int)color->red) << 8) | ((int)color->red) ;
557 col.green = (((int)color->green) << 8) | ((int)color->green) ;
558 col.blue = (((int)color->blue) << 8) | ((int)color->blue) ;
559 SetCPixel( i, y, &col);
560 }
561 /*
562 png_color_struct* color ;
563 RGBColor col ;
564 unsigned char* p = &row_pointers[0] ;
565 PenNormal() ;
566 MoveTo( 0 , y ) ;
567 int index = *p ;
568 color = &info_ptr->palette[index] ;
569 col.red = (color->red << 8) | color->red ;
570 col.green = (color->green << 8) | color->green ;
571 col.blue = (color->blue << 8) | color->blue ;
572 RGBForeColor( &col ) ;
573 col.red = col.green = col.blue = 0xFFFF ;
574 RGBBackColor( &col ) ;
575 for ( int i = 0 ; i < info_ptr->width ; ++i , ++p)
576 {
577 if ( *p != index )
578 {
579 LineTo( i , y ) ;
580 index = *p ;
581 color = &info_ptr->palette[index] ;
582 col.red = (((int)color->red) << 8) | ((int)color->red) ;
583 col.green = (((int)color->green) << 8) | ((int)color->green) ;
584 col.blue = (((int)color->blue) << 8) | ((int)color->blue) ;
585 RGBForeColor( &col ) ;
586 }
587 }
588 LineTo( info_ptr->width , y ) ;
589 */
590 }
591 else
592 {
593 for ( size_t i = 0 ; i < info_ptr->width ; ++i )
594 {
595 png_color_struct* color ;
596 RGBColor col ;
597
598 int byte = ( i * pixel_depth ) / 8 ;
599 int offset = ( 8 - pixel_depth ) - ( i * pixel_depth ) % 8 ;
600
601 int index = ( row_pointers[byte] >> offset ) & ( 0xFF >> ( 8 - pixel_depth ) );
602 color = &info_ptr->palette[index] ;
603 col.red = (((int)color->red) << 8) | ((int)color->red) ;
604 col.green = (((int)color->green) << 8) | ((int)color->green) ;
605 col.blue = (((int)color->blue) << 8) | ((int)color->blue) ;
606 SetCPixel( i, y, &col);
607 }
608 }
609 }
610 else
611 {
612 for ( size_t i = 0 ; i < info_ptr->width ; ++i )
613 {
614 png_color_struct* color ;
615 RGBColor col ;
616 color =(png_color_struct*) (&row_pointers[i*3]) ;
617 col.red = (((int)color->red) << 8) | ((int)color->red) ;
618 col.green = (((int)color->green) << 8) | ((int)color->green) ;
619 col.blue = (((int)color->blue) << 8) | ((int)color->blue) ;
620 SetCPixel( i, y, &col);
621 }
622 }
623 if (number_passes)
624 iter.SetRow(row_pointers, row_stride);
625 y++;
626 }
627 while(iter.PrevRow());
628 SetGWorld( origPort , origDevice ) ;
629
630 // printf("Y=%d ",y);
631 }
632 delete[] row_pointers;
633
634 /* read the rest of the file, getting any additional chunks
635 in info_ptr */
636 png_read_end(png_ptr, info_ptr);
637
638 /* clean up after the read, and free any memory allocated */
639 png_read_destroy(png_ptr, info_ptr, (png_info *)0);
640
641 /* free the structures */
642 delete png_ptr;
643 delete info_ptr;
644
645 /* close the file */
646 fclose(fp);
647
648 /* that's it */
649 return TRUE;
650 }
651
652
653 /* write a png file */
654
655 bool wxPNGReader::SaveFile(char * ImageFileName)
656 {
657 if (ImageFileName)
658 strcpy(filename, ImageFileName);
659
660 wxPNGReaderIter iter(this);
661 FILE *fp;
662 png_struct *png_ptr;
663 png_info *info_ptr;
664
665 /* open the file */
666 fp = fopen(filename, "wb");
667 if (!fp)
668 return FALSE;
669
670 /* allocate the necessary structures */
671 png_ptr = new (png_struct);
672 if (!png_ptr)
673 {
674 fclose(fp);
675 return FALSE;
676 }
677
678 info_ptr = new (png_info);
679 if (!info_ptr)
680 {
681 fclose(fp);
682 delete png_ptr;
683 return FALSE;
684 }
685
686 /* set error handling */
687 if (setjmp(png_ptr->jmpbuf))
688 {
689 png_write_destroy(png_ptr);
690 fclose(fp);
691 delete png_ptr;
692 delete info_ptr;
693
694 /* If we get here, we had a problem reading the file */
695 return FALSE;
696 }
697 //png_set_error(ima_png_error, NULL);
698
699 // printf("writig pg %s ", filename);
700 /* initialize the structures */
701 png_info_init(info_ptr);
702 png_write_init(png_ptr);
703
704 int row_stride = GetWidth() * ((GetDepth()+7)>>3);
705 /* set up the output control */
706 png_init_io(png_ptr, fp);
707
708 /* set the file information here */
709 info_ptr->width = GetWidth();
710 info_ptr->height = GetHeight();
711 info_ptr->pixel_depth = GetDepth();
712 info_ptr->channels = (GetDepth()>8) ? 3: 1;
713 info_ptr->bit_depth = GetDepth()/info_ptr->channels;
714 info_ptr->color_type = GetColorType();
715 info_ptr->compression_type = info_ptr->filter_type = info_ptr->interlace_type=0;
716 info_ptr->valid = 0;
717 info_ptr->rowbytes = row_stride;
718
719
720 // 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);
721 /* set the palette if there is one */
722 if ((GetColorType() & COLORTYPE_PALETTE) && GetPalette())
723 {
724 // printf("writing paleta[%d %d %x]",GetColorType() ,COLORTYPE_PALETTE, GetPalette());
725 info_ptr->valid |= PNG_INFO_PLTE;
726 info_ptr->palette = new png_color[256];
727 info_ptr->num_palette = 256;
728 for (int i=0; i<256; i++)
729 GetPalette()->GetRGB(i, &info_ptr->palette[i].red, &info_ptr->palette[i].green, &info_ptr->palette[i].blue);
730 }
731 // printf("Paleta [%d %d %x]",GetColorType() ,COLORTYPE_PALETTE, GetPalette());
732
733
734 /* optional significant bit chunk */
735 // info_ptr->valid |= PNG_INFO_sBIT;
736 // info_ptr->sig_bit = true_bit_depth;
737
738 /* optional gamma chunk */
739 // info_ptr->valid |= PNG_INFO_gAMA;
740 // info_ptr->gamma = gamma;
741
742 /* other optional chunks */
743
744 /* write the file information */
745 png_write_info(png_ptr, info_ptr);
746
747 /* set up the transformations you want. Note that these are
748 all optional. Only call them if you want them */
749
750 /* shift the pixels up to a legal bit depth and fill in
751 as appropriate to correctly scale the image */
752 // png_set_shift(png_ptr, &(info_ptr->sig_bit));
753
754 /* pack pixels into bytes */
755 // png_set_packing(png_ptr);
756
757 /* flip bgr pixels to rgb */
758 // png_set_bgr(png_ptr);
759
760 /* swap bytes of 16 bit files to most significant bit first */
761 // png_set_swap(png_ptr);
762
763 /* get rid of filler bytes, pack rgb into 3 bytes */
764 // png_set_rgbx(png_ptr);
765
766 /* If you are only writing one row at a time, this works */
767
768 byte *row_pointers = new byte[row_stride];
769 iter.upset();
770 do {
771 // (unsigned char *)iter.GetRow();
772 iter.GetRow(row_pointers, row_stride);
773 png_write_row(png_ptr, row_pointers);
774 } while(iter.PrevRow());
775
776 delete[] row_pointers;
777
778 /* write the rest of the file */
779 png_write_end(png_ptr, info_ptr);
780
781 /* clean up after the write, and free any memory allocated */
782 png_write_destroy(png_ptr);
783
784 /* if you malloced the palette, free it here */
785 if (info_ptr->palette)
786 delete[] (info_ptr->palette);
787
788 /* free the structures */
789 delete png_ptr;
790 delete info_ptr;
791
792 /* close the file */
793 fclose(fp);
794
795 /* that's it */
796 return TRUE;
797 }
798
799 static int Power(int x, int y)
800 {
801 int z = 1;
802 int i;
803 for ( i = 0; i < y; i++)
804 {
805 z *= x;
806 }
807 return z;
808 }
809
810 static char hexArray[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
811 'C', 'D', 'E', 'F' };
812
813 static void DecToHex(int dec, char *buf)
814 {
815 int firstDigit = (int)(dec/16.0);
816 int secondDigit = (int)(dec - (firstDigit*16.0));
817 buf[0] = hexArray[firstDigit];
818 buf[1] = hexArray[secondDigit];
819 buf[2] = 0;
820 }
821
822
823 bool wxPNGReader::SaveXPM(char *filename, char *name)
824 {
825 char nameStr[256];
826 if ( name )
827 strcpy(nameStr, name);
828 else
829 {
830 wxString str = wxString::FromAscii(filename) ;
831 wxStripExtension( str ) ;
832 strcpy(nameStr, str.ToAscii() );
833 }
834
835 if ( GetDepth() > 4 )
836 {
837 // Only a depth of 4 and below allowed
838 return FALSE;
839 }
840
841 if ( !GetPalette() )
842 return FALSE;
843
844 wxSTD ofstream str(filename);
845 if ( str.bad() )
846 return FALSE;
847
848 int noColours = Power(2, GetDepth());
849
850 // Output header
851 str << "/* XPM */\n";
852 str << "static char * " << nameStr << "_xpm[] = {\n";
853 str << "\"" << GetWidth() << " " << GetHeight() << " " << noColours << " 1\",\n";
854
855 // Output colourmap
856 int base = 97 ; // start from 'a'
857
858 unsigned char red, green, blue;
859 char hexBuf[4];
860 int i;
861 for ( i = 0; i < noColours; i ++)
862 {
863 str << "\"" << (char)(base + i) << " c #";
864 GetPalette()->GetRGB(i, &red, &green, &blue);
865 DecToHex(red, hexBuf);
866 str << hexBuf;
867 DecToHex(green, hexBuf);
868 str << hexBuf;
869 DecToHex(blue, hexBuf);
870 str << hexBuf;
871 str << "\",\n";
872 }
873
874 // Output the data
875 int x, y;
876 for ( y = 0; y < GetHeight(); y++)
877 {
878 str << "\"";
879 for ( x = 0; x < GetWidth(); x++)
880 {
881 int index = GetIndex(x, y);
882 str << (char)(base + index) ;
883 }
884 str << "\",\n";
885 }
886
887 str << "};\n";
888 str.flush();
889
890 return TRUE;
891 }
892
893
894 IMPLEMENT_DYNAMIC_CLASS(wxPNGFileHandler, wxBitmapHandler)
895
896 bool wxPNGFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
897 int desiredWidth, int desiredHeight)
898 {
899 wxPNGReader reader;
900 if (reader.ReadFile( (char*)(const char*) name.ToAscii() ) )
901 {
902 return reader.InstantiateBitmap(bitmap);
903 }
904 else
905 return FALSE;
906 }
907
908 bool wxPNGFileHandler::SaveFile(const wxBitmap *bitmap, const wxString& name, int type, const wxPalette *pal)
909 {
910 return FALSE;
911 }
912
913 #endif //wxUSE_LIBPNG