source: svn/trunk/zas_dstar/build/bmpbin2src/yspng.cpp @ 2

Last change on this file since 2 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
File size: 36.8 KB
Line 
1#include <stdio.h>
2
3#include "yspng.h"
4
5
6
7unsigned int YsGenericPngDecoder::verboseMode=YSFALSE;
8
9
10
11// Updates
12//   2005/03/02
13//     Started
14//   2005/03/03
15//     Support:
16//       8bit Grayscale, True color, 4bit Indexed color, 8bit Indexed color
17//   2005/03/04
18//     Added support for true color with alpha and grayscale with alpha
19//   2005/03/14
20//     Support:
21//       Interlaced 8bit True color
22//   2005/03/15
23//     Support:
24//       Interlaced/Non-Interlaced 16bit True color
25//       Interlaced 8bit Grayscale
26//       Interlaced 8bit Indexed color
27//       Interlaced 8bit Grayscale with alpha
28//       Interlaced 8bit Truecolor with alpha
29//     Cleaned up a little bit.
30//   2005/04/08
31//     Support:
32//       Non-Interlace 1 bit Grayscale
33//   2010/09/18
34//     Fixed transparency check in interlaced 16-bit true-color mode.
35//     Based on a bug-report from a viewer.  Thanks for the good catch!
36//   2011/12/28
37//     Fixed transparent color reading based on the user-report.  Thanks for the good catch!
38
39
40/* Supported color and depth
41
42Non-Interlaced
43  1bit Grayscale
44  4bit Indexed Color
45  8bit Grayscale
46  8bit Grayscale with Alpha
47  8bit Indexed Color
48  8bit True Color (24bit per pixel)
49  8bit True Color with Alpha (32bit per pixel)
50  16bit True Color (48bit per pixel)
51
52Interlaced
53  8bit Grayscale
54  8bit Grayscale with Alpha
55  8bit Indexed Color
56  8bit True color (24bit per pixel)
57  8bit True Color with Alpha (32bit per pixel)
58  16bit True Color (48bit per pixel)
59
60*/
61
62
63
64// Memo
65//   PNG Data Format http://www.w3.org/TR/PNG
66
67
68#define MakeDword(a,b,c,d) ((a)*0x1000000+(b)*0x10000+(c)*0x100+(d))
69
70#define IHDR MakeDword('I','H','D','R')
71#define IDAT MakeDword('I','D','A','T')
72#define PLTE MakeDword('P','L','T','E')
73#define IEND MakeDword('I','E','N','D')
74#define pHYs MakeDword('p','H','y','s')
75#define tRNS MakeDword('t','R','N','S')
76#define gAMA MakeDword('g','A','M','A')
77
78static inline unsigned int PngGetUnsignedInt(const unsigned char dat[4])
79{
80        return (unsigned)dat[3]+(unsigned)dat[2]*0x100+(unsigned)dat[1]*0x10000+(unsigned)dat[0]*0x1000000;
81}
82
83////////////////////////////////////////////////////////////
84
85void YsPngHeader::Decode(unsigned char dat[])
86{
87        width=PngGetUnsignedInt(dat);
88        height=PngGetUnsignedInt(dat+4);
89        bitDepth=dat[8];
90        colorType=dat[9];
91        compressionMethod=dat[10];
92        filterMethod=dat[11];
93        interlaceMethod=dat[12];
94
95        if(YsGenericPngDecoder::verboseMode==YSTRUE)
96        {
97                printf("Width=%d Height=%d\n",width,height);
98                printf("bitDepth=%d\n",bitDepth);
99                printf("colorType=%d\n",colorType);
100                printf("compressionMethod=%d\n",compressionMethod);
101                printf("filterMethod=%d\n",filterMethod);
102                printf("interlaceMethod=%d\n",interlaceMethod);
103        }
104}
105
106YsPngPalette::YsPngPalette()
107{
108        nEntry=0;
109        entry=NULL;
110}
111
112YsPngPalette::~YsPngPalette()
113{
114        if(entry!=NULL)
115        {
116                delete [] entry;
117        }
118}
119
120int YsPngPalette::Decode(unsigned length,unsigned char dat[])
121{
122        if(length%3!=0)
123        {
124                return YSERR;
125        }
126
127        if(entry!=NULL)
128        {
129                delete [] entry;
130                nEntry=0;
131                entry=NULL;
132        }
133
134        if(length>0)
135        {
136                entry=new unsigned char [length];
137                if(entry!=NULL)
138                {
139                        unsigned int i;
140                        nEntry=length/3;
141
142                        if(YsGenericPngDecoder::verboseMode==YSTRUE)
143                        {
144                                printf("%d palette entries\n",nEntry);
145                        }
146
147                        for(i=0; i<length; i++)
148                        {
149                                entry[i]=dat[i];
150                        }
151                }
152        }
153
154        return YSOK;
155}
156
157////////////////////////////////////////////////////////////
158
159int YsPngTransparency::Decode(unsigned int length,unsigned char dat[],unsigned int colorType)
160{
161        unsigned int i;
162        switch(colorType)
163        {
164        case 0:
165                if(length>=2)
166                {
167                        col[0]=(unsigned int)dat[0]*256+(unsigned int)dat[1];
168                        return YSOK;
169                }
170                break;
171        case 2:
172                if(length>=6)
173                {
174                        col[0]=(unsigned int)dat[0]*256+(unsigned int)dat[1]; // 2011/12/28 Bug fix based on the user-report.  Thanks!
175                        col[1]=(unsigned int)dat[2]*256+(unsigned int)dat[3];
176                        col[2]=(unsigned int)dat[4]*256+(unsigned int)dat[5];
177                        return YSOK;
178                }
179                break;
180        case 3:
181                for(i=0; i<3 && i<length; i++)
182                {
183                        col[i]=dat[i];
184                }
185                return YSOK;
186        }
187        return YSERR;
188}
189
190////////////////////////////////////////////////////////////
191
192YsGenericPngDecoder::YsGenericPngDecoder()
193{
194        Initialize();
195}
196
197void YsGenericPngDecoder::Initialize(void)
198{
199        gamma=gamma_default;
200        trns.col[0]=0x7fffffff;
201        trns.col[1]=0x7fffffff;
202        trns.col[2]=0x7fffffff;
203}
204
205int YsGenericPngDecoder::CheckSignature(FILE *fp)
206{
207        unsigned char buf[8];
208        fread(buf,1,8,fp);
209        if(buf[0]==0x89 && buf[1]==0x50 && buf[2]==0x4e && buf[3]==0x47 && 
210           buf[4]==0x0d && buf[5]==0x0a && buf[6]==0x1a && buf[7]==0x0a)
211        {
212                return YSOK;
213        }
214        return YSERR;
215}
216
217int YsGenericPngDecoder::ReadChunk(unsigned &length,unsigned char *&buf,unsigned &chunkType,unsigned &crc,FILE *fp)
218{
219        unsigned char dwBuf[4];
220
221        if(fread(dwBuf,1,4,fp)<4)
222        {
223                return YSERR;
224        }
225        length=PngGetUnsignedInt(dwBuf);
226
227        if(fread(dwBuf,1,4,fp)<4)
228        {
229                return YSERR;
230        }
231        chunkType=PngGetUnsignedInt(dwBuf);
232
233        if(YsGenericPngDecoder::verboseMode==YSTRUE)
234        {
235                printf("Chunk name=%c%c%c%c\n",dwBuf[0],dwBuf[1],dwBuf[2],dwBuf[3]);
236        }
237
238        if(length>0)
239        {
240                buf=new unsigned char [length];
241                if(fread(buf,1,length,fp)<length)
242                {
243                        return YSERR;
244                }
245        }
246        else
247        {
248                buf=NULL;
249        }
250
251        if(fread(dwBuf,1,4,fp)<4)
252        {
253                return YSERR;
254        }
255        crc=PngGetUnsignedInt(dwBuf);
256
257        return YSOK;
258}
259
260////////////////////////////////////////////////////////////
261
262int YsPngHuffmanTree::leakTracker=0;
263
264YsPngHuffmanTree::YsPngHuffmanTree()
265{
266        zero=NULL;
267        one=NULL;
268        dat=0x7fffffff;
269        weight=0;
270        depth=1;
271        leakTracker++;
272}
273
274YsPngHuffmanTree::~YsPngHuffmanTree()
275{
276        leakTracker--;
277}
278
279void YsPngHuffmanTree::DeleteHuffmanTree(YsPngHuffmanTree *node)
280{
281        if(node!=NULL)
282        {
283                DeleteHuffmanTree(node->zero);
284                DeleteHuffmanTree(node->one);
285                delete node;
286        }
287}
288
289////////////////////////////////////////////////////////////
290
291void YsPngUncompressor::MakeFixedHuffmanCode(unsigned hLength[288],unsigned hCode[288])
292{
293        unsigned i;
294        for(i=0; i<=143; i++)
295        {
296                hLength[i]=8;
297                hCode[i]=0x30+i;
298        }
299        for(i=144; i<=255; i++)
300        {
301                hLength[i]=9;
302                hCode[i]=0x190+(i-144);
303        }
304        for(i=256; i<=279; i++)
305        {
306                hLength[i]=7;
307                hCode[i]=i-256;
308        }
309        for(i=280; i<=287; i++)
310        {
311                hLength[i]=8;
312                hCode[i]=0xc0+(i-280);
313        }
314}
315
316void YsPngUncompressor::MakeDynamicHuffmanCode(unsigned hLength[],unsigned hCode[],unsigned nLng,unsigned lng[])
317{
318        unsigned i,maxLng,code,*bl_count,*next_code,bits,n;
319
320        for(i=0; i<nLng; i++)
321        {
322                hLength[i]=lng[i];
323                hCode[i]=0;
324        }
325
326        maxLng=0;
327        for(i=0; i<nLng; i++)
328        {
329                if(maxLng<lng[i])
330                {
331                        maxLng=lng[i];
332                }
333        }
334
335        bl_count=new unsigned [maxLng+1];
336        next_code=new unsigned [maxLng+1];
337        for(i=0; i<maxLng+1; i++)
338        {
339                bl_count[i]=0;
340                next_code[i]=0;
341        }
342        for(i=0; i<nLng; i++)
343        {
344                bl_count[lng[i]]++;
345        }
346
347        // for(i=0; i<maxLng+1; i++)
348        // {
349        //      printf("bl_count[%d]=%d\n",i,bl_count[i]);
350        // }
351
352        // See RFC1951 Specification
353        code=0;
354        bl_count[0]=0;
355        for(bits=1; bits<=maxLng; bits++)
356        {
357                code=(code+bl_count[bits-1])<<1;
358                next_code[bits]=code;
359        }
360
361        for(n=0; n<nLng; n++)
362        {
363                unsigned len;
364                len=lng[n];
365                if(len>0)
366                {
367                        hCode[n]=next_code[len]++;
368                }
369        }
370
371        if(bl_count!=NULL)
372        {
373                delete [] bl_count;
374        }
375        if(next_code!=NULL)
376        {
377                delete [] next_code;
378        }
379}
380
381int YsPngUncompressor::DecodeDynamicHuffmanCode
382           (unsigned int &hLit,unsigned int &hDist,unsigned int &hCLen,
383            unsigned int *&hLengthLiteral,unsigned int *&hCodeLiteral,
384            unsigned int *&hLengthDist,unsigned int *&hCodeDist,
385            unsigned int hLengthBuf[322],unsigned int hCodeBuf[322],
386            const unsigned char dat[],unsigned int &bytePtr,unsigned int &bitPtr)
387{
388        unsigned int i;
389        hLit=0;
390        hDist=0;
391        hCLen=0;
392
393        hLit=GetNextMultiBit(dat,bytePtr,bitPtr,5);
394        hDist=GetNextMultiBit(dat,bytePtr,bitPtr,5);
395        hCLen=GetNextMultiBit(dat,bytePtr,bitPtr,4);
396
397        if(YsGenericPngDecoder::verboseMode==YSTRUE)
398        {
399                printf("hLit=%d hDist=%d hCLen=%d\n",hLit,hDist,hCLen);
400        }
401
402        const unsigned int codeLengthLen=19;
403        unsigned codeLengthOrder[codeLengthLen]=
404        {
405                16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
406        };
407        unsigned codeLengthCode[codeLengthLen];
408        for(i=0; i<codeLengthLen; i++)
409        {
410                codeLengthCode[i]=0;
411        }
412        for(i=0; i<hCLen+4; i++)
413        {
414                codeLengthCode[codeLengthOrder[i]]=GetNextMultiBit(dat,bytePtr,bitPtr,3);
415                // printf("Code length code[%d]=%d (for %d)\n",
416                //     codeLengthOrder[i],codeLengthCode[i],codeLengthOrder[i]);
417        }
418
419        unsigned hLengthCode[codeLengthLen],hCodeCode[codeLengthLen];
420        MakeDynamicHuffmanCode(hLengthCode,hCodeCode,codeLengthLen,codeLengthCode);
421
422        if(YSTRUE==YsGenericPngDecoder::verboseMode)
423        {
424                for(i=0; i<hCLen+4; i++)
425                {
426                        printf("CodeLengthLen[%3d]=%d  HuffmanCode=%08x\n",i,codeLengthCode[i],hCodeCode[i]);
427                }
428        }
429
430        // for(i=0; i<codeLengthLen; i++)
431        // {
432        //      printf("[%d] %08x %08xx\n",i,hLengthCode[i],hCodeCode[i]);
433        // }
434
435        hLengthLiteral=hLengthBuf;
436        hCodeLiteral=hCodeBuf;
437        hLengthDist=hLengthBuf+hLit+257;
438        hCodeDist=hCodeBuf+hLit+257;
439
440        YsPngHuffmanTree *lengthTree,*lengthTreePtr;
441        lengthTree=MakeHuffmanTree(codeLengthLen,hLengthCode,hCodeCode);
442
443        unsigned int nExtr;
444        nExtr=0;
445        lengthTreePtr=lengthTree;
446        while(nExtr<hLit+257+hDist+1)
447        {
448                if(GetNextBit(dat,bytePtr,bitPtr))
449                {
450                        lengthTreePtr=lengthTreePtr->one;
451                }
452                else
453                {
454                        lengthTreePtr=lengthTreePtr->zero;
455                }
456                if(lengthTreePtr->zero==NULL && lengthTreePtr->one==NULL)
457                {
458                        unsigned value,copyLength;
459                        value=lengthTreePtr->dat;
460
461                        // printf("Value=%d\n",value);
462
463                        if(value<=15)
464                        {
465                                hLengthBuf[nExtr++]=value;
466                        }
467                        else if(value==16)
468                        {
469                                copyLength=3+GetNextMultiBit(dat,bytePtr,bitPtr,2);
470                                // printf("copyLength=%d\n",copyLength);
471                                while(copyLength>0)
472                                {
473                                        hLengthBuf[nExtr]=hLengthBuf[nExtr-1];
474                                        nExtr++;
475                                        copyLength--;
476                                }
477                        }
478                        else if(value==17)
479                        {
480                                copyLength=3+GetNextMultiBit(dat,bytePtr,bitPtr,3);
481                                // printf("copyLength=%d\n",copyLength);
482                                while(copyLength>0)
483                                {
484                                        hLengthBuf[nExtr++]=0;
485                                        copyLength--;
486                                }
487                        }
488                        else if(value==18)
489                        {
490                                copyLength=11+GetNextMultiBit(dat,bytePtr,bitPtr,7);
491                                // printf("copyLength=%d\n",copyLength);
492                                while(copyLength>0)
493                                {
494                                        hLengthBuf[nExtr++]=0;
495                                        copyLength--;
496                                }
497                        }
498
499                        lengthTreePtr=lengthTree;
500
501                        // printf("nExtr=%d/%d\n",nExtr,hLit+257+hDist+1);
502                }
503        }
504
505        if(YSTRUE==YsGenericPngDecoder::verboseMode)
506        {
507                for(i=0; i<hLit+257; i++)
508                {
509                        printf("LiteralLength[%3d]=%d\n",i,hLengthLiteral[i]);
510                }
511                for(i=0; i<hDist+1; i++)
512                {
513                        printf("Dist [%d] Length %d\n",i,hLengthDist[i]);
514                }
515        }
516
517        if(YsGenericPngDecoder::verboseMode==YSTRUE)
518        {
519                printf("Making Huffman Code from Code Lengths\n");
520        }
521        MakeDynamicHuffmanCode(hLengthLiteral,hCodeLiteral,hLit+257,hLengthLiteral);
522        MakeDynamicHuffmanCode(hLengthDist,hCodeDist,hDist+1,hLengthDist);
523
524        DeleteHuffmanTree(lengthTree);
525
526        return YSOK;
527}
528
529YsPngHuffmanTree *YsPngUncompressor::MakeHuffmanTree(unsigned n,unsigned hLength[],unsigned hCode[])
530{
531        unsigned i,j,mask;
532        YsPngHuffmanTree *root,*ptr;
533        root=new YsPngHuffmanTree;
534
535        for(i=0; i<n; i++)
536        {
537                if(hLength[i]>0)
538                {
539                        ptr=root;
540                        mask=(1<<(hLength[i]-1));
541                        for(j=0; j<hLength[i]; j++)
542                        {
543                                if(hCode[i]&mask)
544                                {
545                                        if(ptr->one==NULL)
546                                        {
547                                                ptr->one=new YsPngHuffmanTree;
548                                        }
549                                        ptr=ptr->one;
550                                }
551                                else
552                                {
553                                        if(ptr->zero==NULL)
554                                        {
555
556                                                ptr->zero=new YsPngHuffmanTree;
557                                        }
558                                        ptr=ptr->zero;
559                                }
560                                mask>>=1;
561                        }
562                        ptr->dat=i;
563                }
564        }
565
566        return root;
567}
568
569void YsPngUncompressor::DeleteHuffmanTree(YsPngHuffmanTree *node)
570{
571        YsPngHuffmanTree::DeleteHuffmanTree(node);
572}
573
574unsigned YsPngUncompressor::GetCopyLength(unsigned value,unsigned char dat[],unsigned &bytePtr,unsigned &bitPtr)
575{
576        unsigned copyLength;
577
578        if(value<=264)
579        {
580                copyLength=3+(value-257);
581        }
582        else if(value>=285)
583        {
584                copyLength=258;
585        }
586        else
587        {
588                unsigned base,offset,extBits;
589                extBits=1+(value-265)/4;
590                base=(8<<((value-265)/4))+3;
591                offset=((value-265)&3)*(2<<((value-265)/4));
592
593                copyLength=GetNextMultiBit(dat,bytePtr,bitPtr,extBits);
594                copyLength+=base+offset;
595        }
596
597        return copyLength;
598}
599
600unsigned YsPngUncompressor::GetBackwardDistance
601   (unsigned distCode,unsigned char dat[],unsigned &bytePtr,unsigned &bitPtr)
602{
603        unsigned backDist;
604
605        if(distCode<=3)
606        {
607                backDist=distCode+1;
608        }
609        else
610        {
611                unsigned base,offset,extBits;
612
613                base=(4<<((distCode-4)/2))+1;
614                offset=(distCode&1)*(2<<((distCode-4)/2));
615                extBits=(distCode-2)/2;
616
617                backDist=GetNextMultiBit(dat,bytePtr,bitPtr,extBits);
618                backDist+=base+offset;
619        }
620
621        return backDist;
622}
623
624int YsPngUncompressor::Uncompress(unsigned length,unsigned char dat[])
625{
626        unsigned windowUsed;
627        unsigned char *windowBuf;
628        unsigned nByteExtracted;
629
630        windowBuf=NULL;
631
632        unsigned bytePtr,bitPtr;
633        bytePtr=0;
634        bitPtr=1;
635        nByteExtracted=0;
636
637
638        if(YsGenericPngDecoder::verboseMode==YSTRUE)
639        {
640                printf("Begin zLib block length=%d bytePtr=%d bitPtr=0x%02x\n",length,bytePtr,bitPtr);
641        }
642
643        unsigned char cmf,flg;
644        cmf=dat[bytePtr++];
645        flg=dat[bytePtr++];
646
647        unsigned cm,cInfo,windowSize;
648        cm=cmf&0x0f;
649        if(cm!=8)
650        {
651                printf("Unsupported compression method! (%d)\n",cm);
652                goto ERREND;
653        }
654
655        cInfo=(cmf&0xf0)>>4;
656        windowSize=1<<(cInfo+8);
657
658        if(YsGenericPngDecoder::verboseMode==YSTRUE)
659        {
660                printf("cInfo=%d, Window Size=%d\n",cInfo,windowSize);
661        }
662
663        windowBuf=new unsigned char [windowSize];
664        windowUsed=0;
665
666
667
668        unsigned fCheck,fDict,fLevel;
669        fCheck=(flg&15);
670        fDict=(flg&32)>>5;
671        fLevel=(flg&192)>>6;
672
673        if(YsGenericPngDecoder::verboseMode==YSTRUE)
674        {
675                printf("fCheck=%d fDict=%d fLevel=%d\n",fCheck,fDict,fLevel);
676        }
677
678
679        if(fDict!=0)
680        {
681                printf("PNG is not supposed to have a preset dictionary.\n");
682                goto ERREND;
683        }
684
685
686        YsPngHuffmanTree *codeTree,*codeTreePtr;
687        YsPngHuffmanTree *distTree,*distTreePtr;
688        codeTree=NULL;
689        distTree=NULL;
690
691        while(1)
692        {
693                unsigned bFinal,bType;
694
695                bFinal=GetNextBit(dat,bytePtr,bitPtr);
696                bType=GetNextMultiBit(dat,bytePtr,bitPtr,2);
697
698                if(bytePtr>=length)
699                {
700                        printf("Buffer overflow\n");
701                        goto ERREND;
702                }
703
704                if(YsGenericPngDecoder::verboseMode==YSTRUE)
705                {
706                        printf("bFinal=%d bType=%d\n",bFinal,bType);
707                }
708
709                if(bType==0) // No Compression
710                {
711                        unsigned len;
712                        if(bitPtr!=1)
713                        {
714                                bitPtr=1;
715                                bytePtr++;
716                        }
717                        if(bytePtr>=length)
718                        {
719                                printf("Buffer overflow\n");
720                                goto ERREND;
721                        }
722
723                        len=dat[bytePtr]+dat[bytePtr+1]*256;
724                        bytePtr+=4;
725
726                        // Feed len bytes
727                        int i;
728                        for(i=0; i<len; i++)  // 2010/02/08
729                        {
730                                output->Output(dat[bytePtr+i]);
731                        }
732
733                        bytePtr+=len;
734                }
735                else if(bType==1 || bType==2)
736                {
737                        codeTree=NULL;
738
739                        if(bType==1)
740                        {
741                                unsigned hLength[288],hCode[288];
742                                MakeFixedHuffmanCode(hLength,hCode);
743                                codeTree=MakeHuffmanTree(288,hLength,hCode);
744                                distTree=NULL;
745                        }
746                        else
747                        {
748                                unsigned hLit,hDist,hCLen;
749                                unsigned *hLengthLiteral,*hCodeLiteral;
750                                unsigned *hLengthDist,*hCodeDist;
751                                unsigned hLengthBuf[322],hCodeBuf[322];
752
753                                DecodeDynamicHuffmanCode
754                                   (hLit,hDist,hCLen,
755                                    hLengthLiteral,hCodeLiteral,hLengthDist,hCodeDist,hLengthBuf,hCodeBuf,
756                                    dat,bytePtr,bitPtr);
757
758                                if(YsGenericPngDecoder::verboseMode==YSTRUE)
759                                {
760                                        printf("Making Huffman Tree\n");
761                                }
762                                codeTree=MakeHuffmanTree(hLit+257,hLengthLiteral,hCodeLiteral);
763                                distTree=MakeHuffmanTree(hDist+1,hLengthDist,hCodeDist);
764                        }
765
766
767                        if(YsGenericPngDecoder::verboseMode==YSTRUE)
768                        {
769                                printf("Huffman table paprared\n");
770                        }
771
772
773                        codeTreePtr=codeTree;
774                        if(codeTree!=NULL)
775                        {
776                                while(1)
777                                {
778                                        if(GetNextBit(dat,bytePtr,bitPtr))
779                                        {
780                                                codeTreePtr=codeTreePtr->one;
781                                        }
782                                        else
783                                        {
784                                                codeTreePtr=codeTreePtr->zero;
785                                        }
786
787                                        if(codeTreePtr==NULL)
788                                        {
789                                                printf("Huffman Decompression: Reached NULL node.\n");
790                                                goto ERREND;
791                                        }
792
793                                        if(codeTreePtr->zero==NULL && codeTreePtr->one==NULL)
794                                        {
795                                                // printf("[%d]\n",codeTreePtr->dat);
796
797                                                unsigned value;
798                                                value=codeTreePtr->dat;
799                                                if(value<256)
800                                                {
801                                                        windowBuf[windowUsed++]=value;
802                                                        windowUsed&=(windowSize-1);
803                                                        if(output->Output(value)!=YSOK)
804                                                        {
805                                                                goto ERREND;
806                                                        }
807                                                        nByteExtracted++;
808                                                }
809                                                else if(value==256)
810                                                {
811                                                        break;
812                                                }
813                                                else if(value<=285)
814                                                {
815                                                        unsigned copyLength,distCode,backDist;
816                                                        copyLength=GetCopyLength(value,dat,bytePtr,bitPtr);
817                                                        // printf("CopyLength %d\n",copyLength);
818
819                                                        if(bType==1)
820                                                        {
821                                                                distCode=16*GetNextBit(dat,bytePtr,bitPtr);  // 5 bits fixed
822                                                                distCode+=8*GetNextBit(dat,bytePtr,bitPtr);  // Reversed order
823                                                                distCode+=4*GetNextBit(dat,bytePtr,bitPtr);
824                                                                distCode+=2*GetNextBit(dat,bytePtr,bitPtr);
825                                                                distCode+=  GetNextBit(dat,bytePtr,bitPtr);
826                                                        }
827                                                        else
828                                                        {
829                                                                distTreePtr=distTree;
830                                                                while(distTreePtr->zero!=NULL || distTreePtr->one!=NULL)
831                                                                {
832                                                                        if(GetNextBit(dat,bytePtr,bitPtr))
833                                                                        {
834                                                                                distTreePtr=distTreePtr->one;
835                                                                        }
836                                                                        else
837                                                                        {
838                                                                                distTreePtr=distTreePtr->zero;
839                                                                        }
840                                                                }
841                                                                distCode=distTreePtr->dat;
842                                                        }
843                                                        backDist=GetBackwardDistance(distCode,dat,bytePtr,bitPtr);
844                                                        // printf("DistCode %d BackDist %d\n",distCode,backDist);
845
846
847                                                        unsigned i;
848                                                        for(i=0; i<copyLength; i++)
849                                                        {
850                                                                unsigned char dat;
851                                                                dat=windowBuf[(windowUsed-backDist)&(windowSize-1)];
852                                                                if(output->Output(dat)!=YSOK)
853                                                                {
854                                                                        goto ERREND;
855                                                                }
856                                                                nByteExtracted++;
857                                                                windowBuf[windowUsed++]=dat;
858                                                                windowUsed&=(windowSize-1);
859                                                        }
860                                                }
861
862                                                codeTreePtr=codeTree;
863                                        }
864
865                                        if(length<=bytePtr)
866                                        {
867                                                goto ERREND;
868                                        }
869                                }
870                        }
871
872
873                        DeleteHuffmanTree(codeTree);
874                        DeleteHuffmanTree(distTree);
875                        codeTree=NULL;
876                        distTree=NULL;
877                }
878                else
879                {
880                        printf("Unknown compression type (bType=3)\n");
881                        goto ERREND;
882                }
883
884
885                if(bFinal!=0)
886                {
887                        break;
888                }
889        }
890
891        delete [] windowBuf;
892        windowBuf=NULL;
893
894
895
896        if(YsGenericPngDecoder::verboseMode==YSTRUE)
897        {
898                printf("End zLib block length=%d bytePtr=%d bitPtr=0x%02x\n",length,bytePtr,bitPtr);
899                printf("Huffman Tree Leak Tracker = %d\n",YsPngHuffmanTree::leakTracker);
900                printf("Output %d bytes.\n",nByteExtracted);
901        }
902
903        return YSOK;
904
905ERREND:
906        if(windowBuf!=NULL)
907        {
908                delete [] windowBuf;
909        }
910        if(codeTree!=NULL)
911        {
912                DeleteHuffmanTree(codeTree);
913        }
914        if(distTree!=NULL)
915        {
916                DeleteHuffmanTree(distTree);
917        }
918        return YSERR;
919}
920
921////////////////////////////////////////////////////////////
922
923int YsGenericPngDecoder::Decode(const char fn[])
924{
925        FILE *fp;
926        unsigned fileSize;
927
928        fp=fopen(fn,"rb");
929        if(fp!=NULL)
930        {
931            fseek(fp,0,2 /* SEEK_END */);
932            fileSize=ftell(fp);
933            fseek(fp,0,0 /* SEEK_SET */);
934
935                if(CheckSignature(fp)!=YSOK)
936                {
937                        printf("The file does not have PNG signature.\n");
938                        goto ERREND;
939                }
940
941                unsigned datBufUsed;
942                unsigned char *datBuf;
943
944
945                datBufUsed=0;
946                datBuf=new unsigned char [fileSize];
947
948
949                unsigned char *buf;
950                unsigned length,chunkType,crc;
951                while(ReadChunk(length,buf,chunkType,crc,fp)==YSOK && chunkType!=IEND)
952                {
953                        switch(chunkType)
954                        {
955                        default:
956                                if(buf!=NULL)
957                                {
958                                        delete [] buf;
959                                }
960                                break;
961                        case IHDR:
962                                if(buf!=NULL)
963                                {
964                                        if(length>=13)
965                                        {
966                                                hdr.Decode(buf);
967                                        }
968                                        delete [] buf;
969                                }
970                                break;
971                        case PLTE:
972                                if(buf!=NULL)
973                                {
974                                        if(plt.Decode(length,buf)!=YSOK)
975                                        {
976                                                delete [] buf;
977                                                goto ERREND;
978                                        }
979                                        delete [] buf;
980                                }
981                                break;
982                        case tRNS:
983                                if(buf!=NULL)
984                                {
985                                        trns.Decode(length,buf,hdr.colorType);
986                                        delete [] buf;
987                                }
988                                break;
989                        case gAMA:
990                                if(buf!=NULL && length>=4)
991                                {
992                                        gamma=PngGetUnsignedInt(buf);
993                                        if(YsGenericPngDecoder::verboseMode==YSTRUE)
994                                        {
995                                                printf("Gamma %d (default=%d)\n",gamma,gamma_default);
996                                        }
997                                        delete [] buf;
998                                }
999                                break;
1000                        case IDAT:
1001                                if(buf!=NULL)
1002                                {
1003                                        unsigned i;
1004                                        for(i=0; i<length; i++)
1005                                        {
1006                                                datBuf[datBufUsed+i]=buf[i];
1007                                        }
1008                                        datBufUsed+=length;
1009                                        delete [] buf;
1010                                }
1011                        }
1012                }
1013
1014
1015
1016                if(PrepareOutput()==YSOK)
1017                {
1018                        YsPngUncompressor uncompressor;
1019                        uncompressor.output=this;
1020                        uncompressor.Uncompress(datBufUsed,datBuf);
1021
1022                        EndOutput();
1023                }
1024
1025
1026                delete [] datBuf;
1027                fclose(fp);
1028                return YSOK;
1029        }
1030
1031ERREND:
1032        if(fp!=NULL)
1033        {
1034                fclose(fp);
1035        }
1036        return -1;
1037}
1038
1039int YsGenericPngDecoder::PrepareOutput(void)
1040{
1041        return YSOK;
1042}
1043
1044int YsGenericPngDecoder::Output(unsigned char dat)
1045{
1046        return YSOK;
1047}
1048
1049int YsGenericPngDecoder::EndOutput(void)
1050{
1051        return YSOK;
1052}
1053
1054
1055
1056////////////////////////////////////////////////////////////
1057
1058static inline unsigned char Paeth(unsigned int ua,unsigned int ub,unsigned int uc)
1059{
1060        int a,b,c,p,pa,pb,pc;
1061
1062        a=(int)ua;
1063        b=(int)ub;
1064        c=(int)uc;
1065
1066        p=a+b-c;
1067        pa=(p>a ? p-a : a-p);
1068        pb=(p>b ? p-b : b-p);
1069        pc=(p>c ? p-c : c-p);
1070
1071        if(pa<=pb && pa<=pc)
1072        {
1073                return a;
1074        }
1075        else if(pb<=pc)
1076        {
1077                return b;
1078        }
1079        else
1080        {
1081                return c;
1082        }
1083}
1084
1085static inline void Filter8(unsigned char curLine[],unsigned char prvLine[],int x,int y,int unitLng,int filter)
1086{
1087        int i;
1088        switch(filter)
1089        {
1090        case 1:
1091                if(x>0)
1092                {
1093                        for(i=0; i<unitLng; i++)
1094                        {
1095                                curLine[x*unitLng+i]+=curLine[x*unitLng+i-unitLng];
1096                        }
1097                }
1098                break;
1099        case 2:
1100                if(y>0)
1101                {
1102                        for(i=0; i<unitLng; i++)
1103                        {
1104                                curLine[x*unitLng+i]+=prvLine[x*unitLng+i];
1105                        }
1106                }
1107                break;
1108        case 3:
1109                for(i=0; i<unitLng; i++)
1110                {
1111                        unsigned int a;
1112                        a=(x>0 ? curLine[x*unitLng+i-unitLng] : 0);
1113                        a+=(y>0 ? prvLine[x*unitLng+i] : 0);
1114                        curLine[x*unitLng+i]+=a/2;
1115                }
1116                break;
1117        case 4:
1118                for(i=0; i<unitLng; i++)
1119                {
1120                        unsigned int a,b,c;
1121                        a=(x>0 ? curLine[x*unitLng+i-unitLng] : 0);
1122                        b=(y>0 ? prvLine[x*unitLng+i] : 0);
1123                        c=((x>0 && y>0) ? prvLine[x*unitLng-unitLng+i] : 0);
1124                        curLine[x*unitLng+i]+=Paeth(a,b,c);
1125                }
1126                break;
1127        }
1128}
1129
1130YsRawPngDecoder::YsRawPngDecoder()
1131{
1132        wid=0;
1133        hei=0;
1134        rgba=NULL;
1135        twoLineBuf8=NULL;
1136
1137        curLine8=NULL;
1138        prvLine8=NULL;
1139
1140        autoDeleteRgbaBuffer=1;
1141}
1142
1143YsRawPngDecoder::~YsRawPngDecoder()
1144{
1145        if(autoDeleteRgbaBuffer==1 && rgba!=NULL)
1146        {
1147                delete [] rgba;
1148        }
1149        if(twoLineBuf8!=NULL)
1150        {
1151                delete [] twoLineBuf8;
1152        }
1153}
1154
1155void YsRawPngDecoder::ShiftTwoLineBuf(void)
1156{
1157        if(twoLineBuf8!=NULL)
1158        {
1159                unsigned char *swap;
1160                swap=curLine8;
1161                curLine8=prvLine8;
1162                prvLine8=swap;
1163        }
1164}
1165
1166int YsRawPngDecoder::PrepareOutput(void)
1167{
1168        int supported;
1169
1170        supported=0;
1171        switch(hdr.colorType)
1172        {
1173        case 0:   // Greyscale
1174                switch(hdr.bitDepth)
1175                {
1176                case 8:
1177                case 1:
1178                        supported=1;
1179                        break;
1180                case 2:
1181                case 4:
1182                case 16:
1183                        break;
1184                }
1185                break;
1186        case 2:   // Truecolor
1187                switch(hdr.bitDepth)
1188                {
1189                case 8:
1190                case 16:
1191                        supported=1;
1192                        break;
1193                }
1194                break;
1195        case 3:   // Indexed-color
1196                switch(hdr.bitDepth)
1197                {
1198                case 4:
1199                case 8:
1200                        supported=1;
1201                        break;
1202                case 1:
1203                case 2:
1204                        break;
1205                }
1206                break;
1207        case 4:   // Greyscale with alpha
1208                switch(hdr.bitDepth)
1209                {
1210                case 8:
1211                        supported=1;
1212                        break;
1213                case 16:
1214                        break;
1215                }
1216                break;
1217        case 6:   // Truecolor with alpha
1218                switch(hdr.bitDepth)
1219                {
1220                case 8:
1221                        supported=1;
1222                        break;
1223                case 16:
1224                        break;
1225                }
1226                break;
1227        }
1228
1229        if(supported==0)
1230        {
1231                printf("Unsupported colorType-bitDepth combination.\n");
1232                return YSERR;
1233        }
1234
1235
1236
1237        wid=hdr.width;
1238        hei=hdr.height;
1239        if(autoDeleteRgbaBuffer==1 && rgba!=NULL)
1240        {
1241                delete [] rgba;
1242                rgba=NULL;
1243        }
1244        rgba=new unsigned char [wid*hei*4];
1245        x=-1;
1246        y=0;
1247        filter=0;
1248        inLineCount=0;
1249        inPixelCount=0;
1250        firstByte=1;
1251        index=0;
1252        interlacePass=1;
1253
1254        if(twoLineBuf8!=NULL)
1255        {
1256                delete [] twoLineBuf8;
1257                twoLineBuf8=NULL;
1258        }
1259
1260
1261        // See PNG Specification 11.2 for Allowed combinations of color type and bit depth
1262        unsigned int twoLineBufLngPerLine;
1263        switch(hdr.colorType)
1264        {
1265        case 0:   // Greyscale
1266                switch(hdr.bitDepth)
1267                {
1268                case 1:
1269                        twoLineBufLngPerLine=(hdr.width+7)/8;
1270                        break;
1271                case 2:
1272                        twoLineBufLngPerLine=(hdr.width+3)/4;
1273                        break;
1274                case 4:
1275                        twoLineBufLngPerLine=(hdr.width+1)/2;
1276                        break;
1277                case 8:
1278                        twoLineBufLngPerLine=hdr.width;
1279                        break;
1280                case 16:
1281                        twoLineBufLngPerLine=hdr.width*2;
1282                        break;
1283                }
1284                break;
1285        case 2:   // Truecolor
1286                switch(hdr.bitDepth)
1287                {
1288                case 8:
1289                        twoLineBufLngPerLine=hdr.width*3;
1290                        break;
1291                case 16:
1292                        twoLineBufLngPerLine=hdr.width*6;
1293                        break;
1294                }
1295                break;
1296        case 3:   // Indexed-color
1297                switch(hdr.bitDepth)
1298                {
1299                case 1:
1300                        twoLineBufLngPerLine=(hdr.width+7)/8;
1301                        break;
1302                case 2:
1303                        twoLineBufLngPerLine=(hdr.width+3)/4;
1304                        break;
1305                case 4:
1306                        twoLineBufLngPerLine=(hdr.width+1)/2;
1307                        break;
1308                case 8:
1309                        twoLineBufLngPerLine=hdr.width;
1310                        break;
1311                }
1312                break;
1313        case 4:   // Greyscale with alpha
1314                switch(hdr.bitDepth)
1315                {
1316                case 8:
1317                        twoLineBufLngPerLine=hdr.width*2;
1318                        break;
1319                case 16:
1320                        twoLineBufLngPerLine=hdr.width*4;
1321                        break;
1322                }
1323                break;
1324        case 6:   // Truecolor with alpha
1325                switch(hdr.bitDepth)
1326                {
1327                case 8:
1328                        twoLineBufLngPerLine=hdr.width*4;
1329                        break;
1330                case 16:
1331                        twoLineBufLngPerLine=hdr.width*8;
1332                        break;
1333                }
1334                break;
1335        }
1336
1337        twoLineBuf8=new unsigned char [twoLineBufLngPerLine*2];
1338        curLine8=twoLineBuf8;
1339        prvLine8=twoLineBuf8+twoLineBufLngPerLine;
1340
1341        return YSOK;
1342}
1343
1344int YsRawPngDecoder::Output(unsigned char dat)
1345{
1346        unsigned int i;
1347        unsigned int colIdx;
1348        unsigned int interlaceWid,interlaceHei,interlaceX,interlaceY;
1349
1350        if(y>=hei)
1351        {
1352                return YSERR;
1353        }
1354
1355        if(x==-1)  // First byte is filter type for the line. 
1356        {
1357                filter=dat;   // See PNG Specification 4.5.4 Filtering, 9 Filtering
1358                inLineCount=0;
1359                inPixelCount=0;
1360                x++;
1361                // printf("y=%d filter=%d\n",y,filter);
1362                return YSOK;
1363        }
1364        else 
1365        {
1366                switch(hdr.interlaceMethod)
1367                {
1368                // Non-Interlace
1369                case 0:
1370                        switch(hdr.colorType)  // See PNG Specification 6.1 Colour types and values
1371                        {
1372                        // Grayscale
1373                        case 0:
1374                                switch(hdr.bitDepth)
1375                                {
1376                                case 1:
1377                                        curLine8[x/8]=dat;
1378                                        Filter8(curLine8,prvLine8,x/8,y,1,filter);
1379
1380                                        for(i=0; i<8 && x<wid; i++)
1381                                        {
1382                                                colIdx=(curLine8[x/8]>>(7-i))&1;
1383                                                colIdx=(colIdx<<1)+colIdx;
1384                                                colIdx=(colIdx<<2)+colIdx;
1385                                                colIdx=(colIdx<<4)+colIdx;
1386
1387                                                rgba[index  ]=colIdx;
1388                                                rgba[index+1]=colIdx;
1389                                                rgba[index+2]=colIdx;
1390                                                rgba[index+3]=0;
1391                                                x++;
1392                                                index+=4;
1393                                        }
1394                                        break;
1395
1396                                case 8:
1397                                        curLine8[x]=dat;
1398                                        Filter8(curLine8,prvLine8,x,y,1,filter);
1399                                        colIdx=curLine8[x];
1400
1401                                        rgba[index  ]=curLine8[x];
1402                                        rgba[index+1]=curLine8[x];
1403                                        rgba[index+2]=curLine8[x];
1404                                        if(curLine8[x]==trns.col[0] || curLine8[x]==trns.col[1] || curLine8[x]==trns.col[2])
1405                                        {
1406                                                rgba[index+3]=0;
1407                                        }
1408                                        else
1409                                        {
1410                                                rgba[index+3]=255;
1411                                        }
1412
1413                                        x++;
1414                                        index+=4;
1415                                        break;
1416                                }
1417                                break;
1418
1419
1420
1421                        // True color
1422                        case 2:
1423                                switch(hdr.bitDepth)
1424                                {
1425                                case 8:
1426                                        curLine8[inLineCount+inPixelCount]=dat;
1427                                        inPixelCount++;
1428                                        if(inPixelCount==3)
1429                                        {
1430                                                Filter8(curLine8,prvLine8,x,y,3,filter);
1431                                                rgba[index  ]=curLine8[inLineCount];
1432                                                rgba[index+1]=curLine8[inLineCount+1];
1433                                                rgba[index+2]=curLine8[inLineCount+2];
1434
1435                                                if(curLine8[inLineCount  ]==trns.col[0] && 
1436                                                   curLine8[inLineCount+1]==trns.col[1] && 
1437                                                   curLine8[inLineCount+2]==trns.col[2])
1438                                                {
1439                                                        rgba[index+3]=0;
1440                                                }
1441                                                else
1442                                                {
1443                                                        rgba[index+3]=255;
1444                                                }
1445
1446                                                x++;
1447                                                index+=4;
1448                                                inLineCount+=3;
1449                                                inPixelCount=0;
1450                                        }
1451                                        break;
1452                                case 16:
1453                                        curLine8[inLineCount+inPixelCount]=dat;
1454                                        inPixelCount++;
1455                                        if(inPixelCount==6)
1456                                        {
1457                                                Filter8(curLine8,prvLine8,x,y,6,filter);
1458                                                rgba[index  ]=curLine8[inLineCount  ];
1459                                                rgba[index+1]=curLine8[inLineCount+2];
1460                                                rgba[index+2]=curLine8[inLineCount+4];
1461
1462                                                r=curLine8[inLineCount  ]*256+curLine8[inLineCount+1];
1463                                                g=curLine8[inLineCount+2]*256+curLine8[inLineCount+3];
1464                                                b=curLine8[inLineCount+4]*256+curLine8[inLineCount+5];
1465                                                if(r==trns.col[0] && g==trns.col[1] && b==trns.col[2])
1466                                                {
1467                                                        rgba[index+3]=0;
1468                                                }
1469                                                else
1470                                                {
1471                                                        rgba[index+3]=255;
1472                                                }
1473                                                x++;
1474                                                index+=4;
1475                                                inLineCount+=6;
1476                                                inPixelCount=0;
1477                                        }
1478                                        break;
1479                                }
1480                                break;
1481
1482
1483
1484                        // Indexed color
1485                        case 3:
1486                                switch(hdr.bitDepth)
1487                                {
1488                                case 4:
1489                                        curLine8[x/2]=dat;
1490                                        Filter8(curLine8,prvLine8,x/2,y,1,filter);
1491
1492                                        for(i=0; i<2 && x<wid; i++)
1493                                        {
1494                                                colIdx=(curLine8[x/2]>>((1-i)*4))&0x0f;
1495
1496                                                if(colIdx<plt.nEntry)
1497                                                {
1498                                                        rgba[index  ]=plt.entry[colIdx*3  ];
1499                                                        rgba[index+1]=plt.entry[colIdx*3+1];
1500                                                        rgba[index+2]=plt.entry[colIdx*3+2];
1501                                                        if(colIdx==trns.col[0] || colIdx==trns.col[1] || colIdx==trns.col[2])
1502                                                        {
1503                                                                rgba[index+3]=0;
1504                                                        }
1505                                                        else
1506                                                        {
1507                                                                rgba[index+3]=255;
1508                                                        }
1509                                                }
1510                                                x++;
1511                                                index+=4;
1512                                        }
1513                                        break;
1514
1515                                case 8:
1516                                        curLine8[x]=dat;
1517                                        Filter8(curLine8,prvLine8,x,y,1,filter);
1518                                        colIdx=curLine8[x];
1519
1520                                        if(colIdx<plt.nEntry)
1521                                        {
1522                                                rgba[index  ]=plt.entry[colIdx*3  ];
1523                                                rgba[index+1]=plt.entry[colIdx*3+1];
1524                                                rgba[index+2]=plt.entry[colIdx*3+2];
1525                                                if(colIdx==trns.col[0] || colIdx==trns.col[1] || colIdx==trns.col[2])
1526                                                {
1527                                                        rgba[index+3]=0;
1528                                                }
1529                                                else
1530                                                {
1531                                                        rgba[index+3]=255;
1532                                                }
1533                                        }
1534                                        x++;
1535                                        index+=4;
1536                                        break;
1537                                }
1538                                break;
1539
1540
1541
1542                        // Greyscale with alpha
1543                        case 4:
1544                                switch(hdr.bitDepth)
1545                                {
1546                                case 8:
1547                                        curLine8[inLineCount+inPixelCount]=dat;
1548                                        inPixelCount++;
1549                                        if(inPixelCount==2)
1550                                        {
1551                                                Filter8(curLine8,prvLine8,x,y,2,filter);
1552                                                rgba[index  ]=curLine8[inLineCount  ];
1553                                                rgba[index+1]=curLine8[inLineCount  ];
1554                                                rgba[index+2]=curLine8[inLineCount  ];
1555                                                rgba[index+3]=curLine8[inLineCount+1];
1556                                                index+=4;
1557                                                x++;
1558                                                inLineCount+=2;
1559                                                inPixelCount=0;
1560                                        }
1561                                        break;
1562                                }
1563                                break;
1564
1565
1566
1567                        // Truecolor with alpha
1568                        case 6:
1569                                switch(hdr.bitDepth)
1570                                {
1571                                case 8:
1572                                        curLine8[inLineCount+inPixelCount]=dat;
1573                                        inPixelCount++;
1574                                        if(inPixelCount==4)
1575                                        {
1576                                                Filter8(curLine8,prvLine8,x,y,4,filter);
1577                                                rgba[index  ]=curLine8[inLineCount  ];
1578                                                rgba[index+1]=curLine8[inLineCount+1];
1579                                                rgba[index+2]=curLine8[inLineCount+2];
1580                                                rgba[index+3]=curLine8[inLineCount+3];
1581                                                index+=4;
1582                                                x++;
1583                                                inLineCount+=4;
1584                                                inPixelCount=0;
1585                                        }
1586                                        break;
1587                                }
1588                                break;
1589                        }  // switch(hdr.colorType)
1590
1591                        if(x>=wid)
1592                        {
1593                                y++;
1594                                x=-1;
1595                                ShiftTwoLineBuf();
1596                        }
1597
1598                        return YSOK;
1599
1600
1601                // Interlace
1602                case 1:
1603                        //   1 6 4 6 2 6 4 6
1604                        //   7 7 7 7 7 7 7 7
1605                        //   5 6 5 6 5 6 5 6
1606                        //   7 7 7 7 7 7 7 7
1607                        //   3 6 4 6 3 6 4 6
1608                        //   7 7 7 7 7 7 7 7
1609                        //   5 6 5 6 5 6 5 6
1610                        //   7 7 7 7 7 7 7 7
1611                        switch(interlacePass)
1612                        {
1613                        case 1:
1614                                interlaceWid=(wid+7)/8;
1615                                interlaceHei=(hei+7)/8;
1616                                interlaceX=x*8;
1617                                interlaceY=y*8;
1618                                break;
1619                        case 2:
1620                                interlaceWid=(wid+3)/8;
1621                                interlaceHei=(hei+7)/8;
1622                                interlaceX=4+x*8;
1623                                interlaceY=y*8;
1624                                break;
1625                        case 3:
1626                                interlaceWid=(wid+3)/4;
1627                                interlaceHei=(hei+3)/8;
1628                                interlaceX=x*4;
1629                                interlaceY=4+y*8;
1630                                break;
1631                        case 4:
1632                                interlaceWid=(wid+1)/4;
1633                                interlaceHei=(hei+3)/4;
1634                                interlaceX=2+x*4;
1635                                interlaceY=y*4;
1636                                break;
1637                        case 5:
1638                                interlaceWid=(wid+1)/2;
1639                                interlaceHei=(hei+1)/4;
1640                                interlaceX=x*2;
1641                                interlaceY=2+y*4;
1642                                break;
1643                        case 6:
1644                                interlaceWid=(wid  )/2;
1645                                interlaceHei=(hei+1)/2;
1646                                interlaceX=1+x*2;
1647                                interlaceY=y*2;
1648                                break;
1649                        case 7:
1650                                interlaceWid=wid;
1651                                interlaceHei=hei/2;
1652                                interlaceX=x;
1653                                interlaceY=1+y*2;
1654                                break;
1655                        default:
1656                                return YSERR;
1657                        } // switch(interlacePass)
1658
1659                        switch(hdr.colorType)  // See PNG Specification 6.1 Colour types and values
1660                        {
1661                        // Grayscale
1662                        case 0:
1663                                switch(hdr.bitDepth)
1664                                {
1665                                case 8:
1666                                        curLine8[inLineCount]=dat;
1667                                        Filter8(curLine8,prvLine8,x,y,1,filter);
1668
1669                                        index=interlaceX*4+interlaceY*wid*4;
1670                                        rgba[index  ]=curLine8[inLineCount];
1671                                        rgba[index+1]=curLine8[inLineCount];
1672                                        rgba[index+2]=curLine8[inLineCount];
1673
1674                                        if(curLine8[inLineCount]==trns.col[0] || 
1675                                           curLine8[inLineCount]==trns.col[1] || 
1676                                           curLine8[inLineCount]==trns.col[2])
1677                                        {
1678                                                rgba[index+3]=0;
1679                                        }
1680                                        else
1681                                        {
1682                                                rgba[index+3]=255;
1683                                        }
1684
1685                                        x++;
1686                                        inLineCount++;
1687                                        break;
1688                                }
1689                                break;
1690
1691
1692                        // True color
1693                        case 2:
1694                                switch(hdr.bitDepth)
1695                                {
1696                                case 8:
1697                                        curLine8[inLineCount+inPixelCount]=dat;
1698                                        inPixelCount++;
1699                                        if(inPixelCount==3)
1700                                        {
1701                                                Filter8(curLine8,prvLine8,x,y,3,filter);
1702
1703                                                index=interlaceX*4+interlaceY*wid*4;
1704                                                rgba[index  ]=curLine8[inLineCount  ];
1705                                                rgba[index+1]=curLine8[inLineCount+1];
1706                                                rgba[index+2]=curLine8[inLineCount+2];
1707
1708                                                if(curLine8[inLineCount  ]==trns.col[0] && 
1709                                                   curLine8[inLineCount+1]==trns.col[1] && 
1710                                                   curLine8[inLineCount+2]==trns.col[2])
1711                                                {
1712                                                        rgba[index+3]=0;
1713                                                }
1714                                                else
1715                                                {
1716                                                        rgba[index+3]=255;
1717                                                }
1718
1719                                                x++;
1720                                                inLineCount+=3;
1721                                                inPixelCount=0;
1722                                        }
1723                                        break;
1724
1725                                case 16:
1726                                        curLine8[inLineCount+inPixelCount]=dat;
1727                                        inPixelCount++;
1728                                        if(inPixelCount==6)
1729                                        {
1730                                                Filter8(curLine8,prvLine8,x,y,6,filter);
1731                                                index=interlaceX*4+interlaceY*wid*4;
1732                                                rgba[index  ]=curLine8[inLineCount  ];
1733                                                rgba[index+1]=curLine8[inLineCount+2];
1734                                                rgba[index+2]=curLine8[inLineCount+4];
1735
1736                                                r=curLine8[inLineCount  ]*256+curLine8[inLineCount+1];
1737                                                g=curLine8[inLineCount+2]*256+curLine8[inLineCount+3];
1738                                                b=curLine8[inLineCount+4]*256+curLine8[inLineCount+5];
1739
1740                                                if(r==trns.col[0] && g==trns.col[1] && b==trns.col[2])
1741                                                // Fixed based on a bug report from a viewer.  Thanks for the good catch!
1742                                                //   Report received 09/10/2010
1743                                                //   Fixed           09/18/2010
1744                                                {
1745                                                        rgba[index+3]=0;
1746                                                }
1747                                                else
1748                                                {
1749                                                        rgba[index+3]=255;
1750                                                }
1751
1752                                                x++;
1753                                                inLineCount+=6;
1754                                                inPixelCount=0;
1755                                        }
1756                                        break;
1757                                }
1758                                break;
1759
1760
1761
1762                        // Indexed color
1763                        case 3:
1764                                switch(hdr.bitDepth)
1765                                {
1766                                case 8:
1767                                        curLine8[inLineCount]=dat;
1768                                        Filter8(curLine8,prvLine8,x,y,1,filter);
1769
1770                                        index=interlaceX*4+interlaceY*wid*4;
1771                                        colIdx=curLine8[inLineCount  ];
1772                                        if(colIdx<plt.nEntry)
1773                                        {
1774                                                rgba[index  ]=plt.entry[colIdx*3  ];
1775                                                rgba[index+1]=plt.entry[colIdx*3+1];
1776                                                rgba[index+2]=plt.entry[colIdx*3+2];
1777                                                if(colIdx==trns.col[0] || colIdx==trns.col[1] || colIdx==trns.col[2])
1778                                                {
1779                                                        rgba[index+3]=0;
1780                                                }
1781                                                else
1782                                                {
1783                                                        rgba[index+3]=255;
1784                                                }
1785                                        }
1786
1787                                        x++;
1788                                        inLineCount++;
1789                                        break;
1790                                }
1791                                break;
1792
1793
1794
1795                        // Greyscale with alpha
1796                        case 4:
1797                                switch(hdr.bitDepth)
1798                                {
1799                                case 8:
1800                                        curLine8[inLineCount+inPixelCount]=dat;
1801                                        inPixelCount++;
1802                                        if(inPixelCount==2)
1803                                        {
1804                                                Filter8(curLine8,prvLine8,x,y,2,filter);
1805
1806                                                index=interlaceX*4+interlaceY*wid*4;
1807                                                rgba[index  ]=curLine8[inLineCount  ];
1808                                                rgba[index+1]=curLine8[inLineCount  ];
1809                                                rgba[index+2]=curLine8[inLineCount  ];
1810                                                rgba[index+3]=curLine8[inLineCount+1];
1811
1812                                                x++;
1813                                                inLineCount+=2;
1814                                                inPixelCount=0;
1815                                        }
1816                                        break;
1817                                }
1818                                break;
1819
1820
1821
1822                        // Truecolor with alpha
1823                        case 6:
1824                                switch(hdr.bitDepth)
1825                                {
1826                                case 8:
1827                                        curLine8[inLineCount+inPixelCount]=dat;
1828                                        inPixelCount++;
1829                                        if(inPixelCount==4)
1830                                        {
1831                                                Filter8(curLine8,prvLine8,x,y,4,filter);
1832
1833                                                index=interlaceX*4+interlaceY*wid*4;
1834                                                rgba[index  ]=curLine8[inLineCount  ];
1835                                                rgba[index+1]=curLine8[inLineCount+1];
1836                                                rgba[index+2]=curLine8[inLineCount+2];
1837                                                rgba[index+3]=curLine8[inLineCount+3];
1838
1839                                                x++;
1840                                                inLineCount+=4;
1841                                                inPixelCount=0;
1842                                        }
1843                                        break;
1844                                }
1845                        break;
1846                        } // switch(hdr.colorType)
1847
1848                        if(x>=interlaceWid)
1849                        {
1850                                y++;
1851                                x=-1;
1852                                ShiftTwoLineBuf();
1853                                if(y>=interlaceHei)
1854                                {
1855                                        y=0;
1856                                        interlacePass++;
1857
1858                                        if(YsGenericPngDecoder::verboseMode==YSTRUE)
1859                                        {
1860                                                printf("Interlace Pass %d\n",interlacePass);
1861                                        }
1862                                }
1863                        }
1864
1865                        return YSOK;
1866                default:
1867                        printf("Unsupported interlace method.\n");
1868                        return YSERR;
1869                }
1870        }
1871        return YSERR;
1872}
1873
1874int YsRawPngDecoder::EndOutput(void)
1875{
1876        if(YsGenericPngDecoder::verboseMode==YSTRUE)
1877        {
1878                printf("Final Position (%d,%d)\n",x,y);
1879        }
1880        return YSOK;
1881}
1882
1883void YsRawPngDecoder::Flip(void)  // For drawing in OpenGL
1884{
1885        int x,y,bytePerLine;
1886        unsigned int swp;
1887        bytePerLine=wid*4;
1888        for(y=0; y<hei/2; y++)
1889        {
1890                for(x=0; x<bytePerLine; x++)
1891                {
1892                        swp=rgba[y*bytePerLine+x];
1893                        rgba[y*bytePerLine+x]=rgba[(hei-1-y)*bytePerLine+x];
1894                        rgba[(hei-1-y)*bytePerLine+x]=swp;
1895                }
1896        }
1897}
Note: See TracBrowser for help on using the repository browser.