1 
2 #include "studiox_includes.h"
3 #include "image_reader.h"
4 #include "png.h"
5 
6 png_structp png_instance;
7 png_infop   png_info_ptr;
8 
9 ///////////////////////////////////////////////////////////////////////////////
input_stream(unsigned char * data,int data_size)10 input_stream::input_stream(unsigned char* data, int data_size)
11 {
12     mpData = data;
13     mDataSize = data_size;
14     mReadSize = 0;
15 }
16 
17 ///////////////////////////////////////////////////////////////////////////////
Read(void * pv,ULONG cb,ULONG * pcbRead)18 IFACEMETHODIMP input_stream::Read(void *pv, ULONG cb, ULONG *pcbRead)
19 {
20     if (mReadSize < mDataSize)
21     {
22         ULONG remain_size = mDataSize - mReadSize;
23 
24         if (cb <= remain_size)
25         {
26             memcpy((void *)pv, (void *)(mpData + mReadSize), cb); /* Use case of memcpy is verified. */
27             mReadSize += cb;
28 
29             if (pcbRead)
30             {
31                 *pcbRead = cb;
32             }
33         }
34         else
35         {
36             memcpy((void *)pv, (void *)(mpData + mReadSize), remain_size); /* Use case of memcpy is verified. */
37             mReadSize += remain_size;
38 
39             if (pcbRead)
40             {
41                 *pcbRead = remain_size;
42             }
43         }
44     }
45 
46     return 0;
47 }
48 
png_reader()49 png_reader::png_reader() : image_reader()
50 {
51     mpRowPointers = NULL;
52 }
53 
~png_reader()54 png_reader::~png_reader()
55 {
56 }
57 
CheckImageHasAlphaChannel(CString & path)58 BOOL png_reader::CheckImageHasAlphaChannel(CString &path)
59 {
60     BOOL has_alpha = FALSE;
61     UCHAR signature[8];
62 
63     FILE *file = _tfopen(path.GetBuffer(), _T("rb"));
64 
65     if (!file)
66     {
67         return FALSE;
68     }
69 
70     fread(signature, 1, 8, file);
71     if (png_sig_cmp(signature, 0, 8))
72     {
73         fclose(file);
74         return FALSE;
75     }
76 
77     png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
78         NULL, NULL, NULL);
79 
80     if (!png_ptr)
81     {
82         fclose(file);
83         return FALSE;
84     }
85 
86     png_infop info = png_create_info_struct(png_ptr);
87 
88     if (!info)
89     {
90         fclose(file);
91         png_destroy_read_struct(&png_ptr, NULL, NULL);
92         return FALSE;
93     }
94 
95     png_init_io(png_ptr, file);
96     png_set_sig_bytes(png_ptr, 8);
97     png_read_info(png_ptr, info);
98 
99     int color_type, num_trans;
100 
101     //get information from the info
102     if (png_get_IHDR(png_ptr, info, NULL, NULL, NULL, &color_type, NULL, NULL, NULL) == 0)
103     {
104         color_type = -1;
105     }
106 
107     if (png_get_tRNS(png_ptr, info, NULL, &num_trans, NULL) == 0)
108     {
109         num_trans = 0;
110     }
111 
112     switch (color_type)
113     {
114     case PNG_COLOR_TYPE_RGB_ALPHA:
115     case PNG_COLOR_TYPE_GRAY_ALPHA:
116         has_alpha = TRUE;
117         break;
118 
119     case PNG_COLOR_TYPE_PALETTE:
120     case PNG_COLOR_TYPE_GRAY:
121     case PNG_COLOR_TYPE_RGB:
122 
123         if (num_trans > 0)
124         {
125             has_alpha = TRUE;
126         }
127         break;
128     default:
129         break;
130     }
131 
132     png_destroy_read_struct(&png_ptr, &info, NULL);
133     fclose(file);
134     return has_alpha;
135 }
136 
137 ///////////////////////////////////////////////////////////////////////////////
ReadImage(CString & path,int frame_id)138 BOOL png_reader::ReadImage(CString &path, int frame_id)
139 {
140     UCHAR signature[8];
141 
142     FILE *file = _tfopen(path.GetBuffer(), _T("rb"));
143 
144     if (!file)
145     {
146         return FALSE;
147     }
148 
149     fread(signature, 1, 8, file);
150     if (png_sig_cmp(signature, 0, 8))
151     {
152         fclose(file);
153         return FALSE;
154     }
155 
156     m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
157         NULL, NULL, NULL);
158 
159     if (!m_png)
160     {
161         fclose(file);
162         return FALSE;
163     }
164     png_instance = m_png;
165 
166     m_info = png_create_info_struct(m_png);
167     if (!m_info)
168     {
169         fclose(file);
170         png_destroy_read_struct(&m_png, NULL, NULL);
171         return FALSE;
172     }
173 
174     png_init_io(m_png, file);
175     png_set_sig_bytes(m_png, 8);
176     png_read_png(m_png, m_info, PNG_TRANSFORM_IDENTITY, NULL);
177     png_info_ptr = m_info;
178 
179     png_uint_32 width, height;
180 
181     // get information from the m_info
182     if (png_get_IHDR(m_png, m_info, &width, &height, NULL, NULL, NULL, NULL, NULL) != 0)
183     {
184         mpRowPointers = png_get_rows(m_png, m_info);
185 
186         if (mpRowPointers)
187         {
188             ConfigureInternalFormat();
189             DoCompress(FALSE);
190             if (!FinalizeImage(width, height))
191             {
192                 png_destroy_read_struct(&m_png, &m_info, NULL);
193                 fclose(file);
194                 return FALSE;
195             }
196         }
197     }
198 
199     png_destroy_read_struct(&m_png, &m_info, NULL);
200     fclose(file);
201     return TRUE;
202 }
203 
204 ///////////////////////////////////////////////////////////////////////////////
ReadImage(IStream * input_stream)205 BOOL png_reader::ReadImage(IStream *input_stream)
206 {
207     UCHAR signature[8];
208 
209     input_stream->Read(signature, 8, NULL);
210 
211     if (png_sig_cmp(signature, 0, 8))
212     {
213         return FALSE;
214     }
215 
216     m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
217         NULL, NULL, NULL);
218 
219     if (!m_png)
220     {
221         return FALSE;
222     }
223     png_instance = m_png;
224 
225     m_info = png_create_info_struct(m_png);
226     if (!m_info)
227     {
228         png_destroy_read_struct(&m_png, NULL, NULL);
229         return FALSE;
230     }
231 
232     // Set user-defined function for reading a PNG stream.
233     png_set_read_fn(m_png, input_stream, ReadDataFromIStream);
234 
235     png_set_sig_bytes(m_png, 8);
236     png_read_png(m_png, m_info, PNG_TRANSFORM_IDENTITY, NULL);
237     png_info_ptr = m_info;
238 
239     png_uint_32 width, height;
240 
241     // get information from the m_info
242     if (png_get_IHDR(m_png, m_info, &width, &height, NULL, NULL, NULL, NULL, NULL) != 0)
243     {
244         mpRowPointers = png_get_rows(m_png, m_info);
245 
246         if (mpRowPointers)
247         {
248             ConfigureInternalFormat();
249             DoCompress(FALSE);
250             if (!FinalizeImage(width, height))
251             {
252                 png_destroy_read_struct(&m_png, &m_info, NULL);
253                 return FALSE;
254             }
255         }
256     }
257 
258     png_destroy_read_struct(&m_png, &m_info, NULL);
259     return TRUE;
260 }
261 
262 ///////////////////////////////////////////////////////////////////////////////
ReadImage(unsigned char * data,int data_size)263 BOOL png_reader::ReadImage(unsigned char* data, int data_size)
264 {
265     input_stream inputstream(data, data_size);
266 
267     return ReadImage((IStream *)&inputstream);
268 }
269 
270 ///////////////////////////////////////////////////////////////////////////////
GetInputDataPtr(int row)271 UCHAR *png_reader::GetInputDataPtr(int row)
272 {
273     if (mpRowPointers)
274     {
275         return mpRowPointers[row];
276     }
277     return NULL;
278 }
279 
280 
281 // the data formats supported by the PNG decoder are not always
282 // formats that our image_reader understands, so we have to convert
283 // the odd formats to something we do understand
284 
285 ///////////////////////////////////////////////////////////////////////////////
ReadPixel48(image_reader * reader,int Index,Pixel * Pixel)286 void png_reader::ReadPixel48(image_reader *reader, int Index, Pixel *Pixel)
287 {
288     const USHORT *pGet = (USHORT *)reader->mpGetData;
289     pGet += Index * 3;
290     Pixel->Red = *pGet++;
291     Pixel->Green = *pGet++;
292     Pixel->Blue = *pGet;
293 
294     int num_trans;
295     png_color_16p trans_color;
296     if (png_get_tRNS(png_instance, png_info_ptr, NULL, &num_trans, &trans_color) == 0)
297     {
298         num_trans = 0;
299         trans_color = NULL;
300     }
301 
302     if ((num_trans > 0) &&
303         (trans_color->red == Pixel->Red) &&
304         (trans_color->green == Pixel->Green) &&
305         (trans_color->blue == Pixel->Blue))
306     {
307         //Transparent
308         Pixel->Alpha = 0;
309     }
310     else
311     {
312         Pixel->Red &= 0xff;
313         Pixel->Green &= 0xff;
314         Pixel->Blue &= 0xff;
315         Pixel->Alpha = 0xff;
316     }
317 }
318 
319 ///////////////////////////////////////////////////////////////////////////////
ReadPixel1(image_reader * reader,int Index,Pixel * put)320 void png_reader::ReadPixel1(image_reader *reader, int Index, Pixel *put)
321 {
322     UCHAR pal_index;
323     const GX_UBYTE *pGet = reader->mpGetData;
324 
325     put->Red = put->Green = put->Blue = put->Alpha = 0;
326 
327     pGet += (Index >> 3);
328     pal_index = *pGet;
329     pal_index >>= (7 - (Index & 0x07));
330     pal_index &= 0x01;
331 
332     png_colorp palette;
333     int num_palette, num_trans;
334     png_bytep trans_alpha;
335     png_color_16p trans_color;
336 
337     //get information from the png_ingo
338 
339     if (png_get_PLTE(png_instance, png_info_ptr, &palette, &num_palette) == 0)
340     {
341         palette = NULL;
342         num_palette = 0;
343     }
344 
345     if (png_get_tRNS(png_instance, png_info_ptr, &trans_alpha, &num_trans, &trans_color) == 0)
346     {
347         trans_alpha = NULL;
348         num_trans = 0;
349         trans_color = NULL;
350     }
351 
352 
353     if (palette)
354     {
355         //Palette
356         if ((num_trans > 0) && (trans_alpha[0] == pal_index))
357         {
358             put->Alpha = 0;
359         }
360         else
361         {
362             if (pal_index < num_palette)
363             {
364                 put->Red = palette[pal_index].red;
365                 put->Green = palette[pal_index].green;
366                 put->Blue = palette[pal_index].blue;
367             }
368             put->Alpha = 0xff;
369         }
370     }
371     else
372     {
373         //Gray
374         if ((num_trans > 0) &&  (trans_color->gray == pal_index))
375         {
376             put->Alpha = 0;
377         }
378         else
379         {
380             pal_index *= 255;
381             put->Red = pal_index;
382             put->Green = pal_index;
383             put->Blue = pal_index;
384             put->Alpha = 0xff;
385         }
386     }
387 
388 }
389 ///////////////////////////////////////////////////////////////////////////////
ReadPixel2(image_reader * reader,int Index,Pixel * put)390 void png_reader::ReadPixel2(image_reader *reader, int Index, Pixel *put)
391 {
392     UCHAR pal_index;
393     const GX_UBYTE *pGet = reader->mpGetData;
394 
395     put->Red = put->Green = put->Blue = put->Alpha = 0;
396 
397     pGet += (Index >> 2);
398     pal_index = *pGet;
399     pal_index >>= (3 - (Index & 0x03)) * 2;
400     pal_index &= 0x03;
401 
402     png_colorp palette;
403     int num_palette, num_trans;
404     png_bytep trans_alpha;
405     png_color_16p trans_color;
406 
407     //get information from the png_info
408     if (png_get_PLTE(png_instance, png_info_ptr, &palette, &num_palette) == 0)
409     {
410         palette = NULL;
411         num_palette = 0;
412     }
413 
414     if (png_get_tRNS(png_instance, png_info_ptr, &trans_alpha, &num_trans, &trans_color) == 0)
415     {
416         trans_alpha = NULL;
417         num_trans = 0;
418         trans_color = NULL;
419     }
420 
421     if (palette)
422     {
423         //Palette
424         if ((num_trans > 0) && (trans_alpha[0] == pal_index))
425         {
426             put->Alpha = 0;
427         }
428         else
429         {
430             if (pal_index < num_palette)
431             {
432                 put->Red = palette[pal_index].red;
433                 put->Green = palette[pal_index].green;
434                 put->Blue = palette[pal_index].blue;
435             }
436             put->Alpha = 0xff;
437         }
438     }
439     else
440     {
441         //Gray
442         if ((num_trans > 0) && (trans_color->gray == pal_index))
443         {
444             put->Alpha = 0;
445         }
446         else
447         {
448             pal_index = pal_index * 255 / 3;
449             put->Red = pal_index;
450             put->Green = pal_index;
451             put->Blue = pal_index;
452             put->Alpha = 0xff;
453         }
454     }
455 }
456 ///////////////////////////////////////////////////////////////////////////////
ReadPixel4(image_reader * reader,int Index,Pixel * put)457 void png_reader::ReadPixel4(image_reader *reader, int Index, Pixel *put)
458 {
459     UCHAR pal_index;
460     const GX_UBYTE *pGet = reader->mpGetData;
461 
462     put->Red = put->Green = put->Blue = put->Alpha = 0;
463 
464     pGet += (Index >> 1);
465     pal_index = *pGet;
466     pal_index >>= (1 - (Index & 0x01)) * 4;
467     pal_index &= 0x0f;
468 
469     png_colorp palette;
470     int num_palette, num_trans;
471     png_bytep trans_alpha;
472     png_color_16p trans_color;
473 
474     // get information from the png_info
475     if (png_get_PLTE(png_instance, png_info_ptr, &palette, &num_palette) == 0)
476     {
477         palette = NULL;
478         num_palette = 0;
479     }
480 
481     if (png_get_tRNS(png_instance, png_info_ptr, &trans_alpha, &num_trans, &trans_color) == 0)
482     {
483         trans_alpha = NULL;
484         num_trans = 0;
485         trans_color = NULL;
486     }
487 
488     if (palette)
489     {
490         //Palette
491         if ((num_trans > 0) && (trans_alpha[0] == pal_index))
492         {
493             put->Alpha = 0;
494         }
495         else
496         {
497             if (pal_index < num_palette)
498             {
499                 put->Red = palette[pal_index].red;
500                 put->Green = palette[pal_index].green;
501                 put->Blue = palette[pal_index].blue;
502             }
503             put->Alpha = 0xff;
504         }
505     }
506     else
507     {
508         //Gray
509 
510         if ((num_trans > 0) && (trans_color->gray == pal_index))
511         {
512             put->Alpha = 0;
513         }
514         else
515         {
516             pal_index = pal_index * 255 / 15;
517             put->Red = pal_index;
518             put->Green = pal_index;
519             put->Blue = pal_index;
520             put->Alpha = 0xff;
521         }
522     }
523 }
524 
525 ///////////////////////////////////////////////////////////////////////////////
ReadPixel8(image_reader * reader,int Index,Pixel * put)526 void png_reader::ReadPixel8(image_reader *reader, int Index, Pixel *put)
527 {
528     UCHAR pal_index;
529     const GX_UBYTE *pGet = reader->mpGetData;
530 
531     put->Red = put->Green = put->Blue = put->Alpha = 0;
532 
533     pGet += Index;
534     pal_index = *pGet;
535 
536     int color_type, num_palette, num_trans;
537     png_colorp palette;
538     png_bytep trans_alpha;
539     png_color_16p trans_color;
540 
541     //get information from the info
542     if (png_get_IHDR(png_instance, png_info_ptr, NULL, NULL, NULL, &color_type, NULL, NULL, NULL) == 0)
543     {
544         color_type = -1;
545     }
546 
547 
548     if (png_get_PLTE(png_instance, png_info_ptr, &palette, &num_palette) == 0)
549     {
550         palette = NULL;
551         num_palette = 0;
552     }
553 
554     if (png_get_tRNS(png_instance, png_info_ptr, &trans_alpha, &num_trans, &trans_color) == 0)
555     {
556         trans_alpha = NULL;
557         num_trans = 0;
558         trans_color = NULL;
559     }
560 
561     switch(color_type)
562     {
563     case 3:   // indexed color
564         if (pal_index < num_palette)
565         {
566             put->Red = palette[pal_index].red;
567             put->Green = palette[pal_index].green;
568             put->Blue = palette[pal_index].blue;
569         }
570         if (pal_index < num_trans)
571         {
572             put->Alpha = trans_alpha[pal_index];
573         }
574         else
575         {
576             put->Alpha = 0xff;
577         }
578         break;
579 
580     case 2: // TrueColor image data
581         if (pal_index < num_palette)
582         {
583             put->Red = palette[pal_index].red;
584             put->Green = palette[pal_index].green;
585             put->Blue = palette[pal_index].blue;
586         }
587         if ((num_trans > 0) && (trans_alpha[0] == pal_index))
588         {
589             put->Alpha = 0;
590         }
591         else
592         {
593             put->Alpha = 0xff;
594         }
595         break;
596 
597     case 0: // grayscale
598         //Gray
599         if ((num_trans > 0) && (trans_color->gray == pal_index))
600         {
601             put->Alpha = 0;
602         }
603         else
604         {
605             put->Red = pal_index;
606             put->Green = pal_index;
607             put->Blue = pal_index;
608             put->Alpha = 0xff;
609         }
610         break;
611 
612     default:
613         break;
614     }
615 }
616 
617 ///////////////////////////////////////////////////////////////////////////////
ReadPixel24(image_reader * reader,int Index,Pixel * put)618 void png_reader::ReadPixel24(image_reader *reader, int Index, Pixel *put)
619 {
620     const GX_UBYTE *pGet = reader->mpGetData;
621 
622     pGet += Index * 3;
623 
624     put->Red = *pGet++;
625     put->Green = *pGet++;
626     put->Blue = *pGet++;
627 
628     int num_trans;
629     png_color_16p trans_color;
630 
631     if (png_get_tRNS(png_instance, png_info_ptr, NULL, &num_trans, &trans_color) == 0)
632     {
633         trans_color = NULL;
634         num_trans = 0;
635     }
636 
637     if ((num_trans > 0) &&
638         (trans_color->red == put->Red) &&
639         (trans_color->green == put->Green) &&
640         (trans_color->blue == put->Blue))
641     {
642         //Transparent
643         put->Alpha = 0;
644     }
645     else
646     {
647         put->Alpha = 0xff;
648     }
649 }
650 
651 ///////////////////////////////////////////////////////////////////////////////
ReadPixel64(image_reader * reader,int Index,Pixel * put)652 void png_reader::ReadPixel64(image_reader *reader, int Index, Pixel *put)
653 {
654     const GX_UBYTE *pGet = reader->mpGetData;
655 
656     pGet += Index * 8;
657     put->Red = *pGet;
658     pGet += 2;
659     put->Green = *pGet;
660     pGet += 2;
661     put->Blue =  *pGet;
662     pGet += 2;
663     put->Alpha = *pGet;
664 }
665 
666 ///////////////////////////////////////////////////////////////////////////////
ReadPixel24Alpha(image_reader * reader,int Index,Pixel * put)667 void png_reader::ReadPixel24Alpha(image_reader *reader, int Index, Pixel *put)
668 {
669     const GX_UBYTE *pGet = reader->mpGetData;
670 
671     pGet += Index * 4;
672     put->Red =   *pGet++;
673     put->Green = *pGet++;
674     put->Blue =  *pGet++;
675     put->Alpha = *pGet;
676 }
677 
678 
679 ///////////////////////////////////////////////////////////////////////////////
ReadPixel8Alpha(image_reader * reader,int Index,Pixel * put)680 void png_reader::ReadPixel8Alpha(image_reader *reader, int Index, Pixel *put)
681 {
682     const GX_UBYTE *pGet = reader->mpGetData;
683 
684     pGet += Index * 2;
685     put->Red = put->Green = put->Blue = *pGet++;
686     put->Alpha = *pGet;
687 }
688 
689 ///////////////////////////////////////////////////////////////////////////////
ReadPixel16To8(image_reader * reader,int Index,Pixel * put)690 void png_reader::ReadPixel16To8(image_reader *reader, int Index, Pixel *put)
691 {
692     const USHORT *pGet = (USHORT *)reader->mpGetData;
693     int gray;
694 
695     pGet += Index;
696     gray = *pGet;
697 
698     int num_trans;
699     png_color_16p trans_color;
700 
701     if (png_get_tRNS(png_instance, png_info_ptr, NULL, &num_trans, &trans_color) == 0)
702     {
703         num_trans = 0;
704         trans_color = NULL;
705     }
706 
707     if ((num_trans > 0) && (trans_color->gray == gray))
708     {
709         //Transparent
710         put->Alpha = 0;
711     }
712     else
713     {
714         put->Red = put->Green = put->Blue = (GX_UBYTE)gray;
715         put->Alpha = 0xff;
716     }
717 }
718 
719 ///////////////////////////////////////////////////////////////////////////////
ReadPixel16Alpha(image_reader * reader,int Index,Pixel * put)720 void png_reader::ReadPixel16Alpha(image_reader *reader, int Index, Pixel *put)
721 {
722     const GX_UBYTE *pGet = reader->mpGetData;
723 
724     pGet += (Index * 4);
725     put->Red = put->Green = put->Blue = *pGet;
726     pGet += 2;
727     put->Alpha = *pGet;
728 }
729 
730 ///////////////////////////////////////////////////////////////////////////////
ReadDataFromIStream(png_structp png_ptr,png_bytep outBytes,png_size_t byteCountToRead)731 void png_reader::ReadDataFromIStream(png_structp png_ptr, png_bytep outBytes, png_size_t byteCountToRead)
732 {
733     IStream *inputstream = (IStream *)png_get_io_ptr(png_ptr);
734 
735     if (inputstream)
736     {
737         inputstream->Read(outBytes, byteCountToRead, GX_NULL);
738     }
739 }
740 
741 ///////////////////////////////////////////////////////////////////////////////
ConfigureInternalFormat()742 void png_reader::ConfigureInternalFormat()
743 {
744     mInputHasAlpha = FALSE;
745 
746     int bit_depth, color_type, num_trans;
747 
748     //get information from the info
749     if (png_get_IHDR(m_png, m_info, NULL, NULL, &bit_depth, &color_type, NULL, NULL, NULL) == 0)
750     {
751         bit_depth = 0;
752         color_type = -1;
753     }
754 
755     if (png_get_tRNS(m_png, m_info, NULL, &num_trans, NULL) == 0)
756     {
757         num_trans = 0;
758     }
759 
760     switch(color_type)
761     {
762     case PNG_COLOR_TYPE_RGB:
763         if (num_trans > 0)
764         {
765             mInputHasAlpha = TRUE;
766         }
767 
768         if (bit_depth == 8)
769         {
770             // use standard raw reader provided by base class
771             //SetDefaultPixelReader(24);
772             mpReadInputPixel = &png_reader::ReadPixel24;
773         }
774         else
775         {
776             // the input file has 16-bit channels. Use
777             // my own reader
778             mpReadInputPixel = &png_reader::ReadPixel48;
779         }
780         break;
781 
782     case PNG_COLOR_TYPE_RGB_ALPHA:
783         mInputHasAlpha = TRUE;
784         if (bit_depth == 8)
785         {
786             mpReadInputPixel = &png_reader::ReadPixel24Alpha;
787         }
788         else
789         {
790             // the input file has 16-bit color channels
791             mpReadInputPixel = &png_reader::ReadPixel64;
792         }
793         break;
794 
795     case PNG_COLOR_TYPE_PALETTE:
796     case PNG_COLOR_TYPE_GRAY:
797 
798         if (num_trans > 0)
799         {
800             mInputHasAlpha = TRUE;
801         }
802 
803         switch(bit_depth)
804         {
805         case 1:
806             mpReadInputPixel = &png_reader::ReadPixel1;
807             break;
808 
809         case 2:
810             mpReadInputPixel = &png_reader::ReadPixel2;
811             break;
812 
813         case 4:
814             mpReadInputPixel = &png_reader::ReadPixel4;
815             break;
816 
817         case 8:
818             mpReadInputPixel = &png_reader::ReadPixel8;
819             break;
820 
821         case 16:
822             mpReadInputPixel = &png_reader::ReadPixel16To8;
823             break;
824         }
825         break;
826 
827     case  PNG_COLOR_TYPE_GRAY_ALPHA:
828         mInputHasAlpha = TRUE;
829 
830         if (bit_depth == 8)
831         {
832             mpReadInputPixel = &png_reader::ReadPixel8Alpha;
833         }
834         else
835         {
836             mpReadInputPixel = &png_reader::ReadPixel16Alpha;
837         }
838         break;
839     }
840 }
841