1 
2 #include "studiox_includes.h"
3 #include "image_reader.h"
4 
5 #ifdef _DEBUG
6 #define new DEBUG_NEW
7 #endif
8 
9 #define TRANSPARENT_COLOR 0xff
10 
11 
12 /* How to use the image_reader class:
13 
14    image_reader *pReader = image_reader::CreateProperReader(path);
15 
16     if (pReader)
17     {
18         // this need to be set based on display properties
19         pReader->SetOutputColorFormat(GX_COLOR_FORMAT_24BIT_XRGB);
20         pReader->SetSaveAlphaVal(TRUE);     // optional
21         pReader->SetCompression(TRUE);      // optional
22 
23         if (pReader->ReadImage(path))
24         {
25             pmap = pReader->GetPixelmap();  // get back pixelmap
26         }
27         delete pReader;                     // cleanup
28     }
29 */
30 
31 /* The Pixel class is a very simple class we use to pass color data around
32    between the data readers and data writers.
33 */
34 ///////////////////////////////////////////////////////////////////////////////
Pixel(int red,int green,int blue)35 Pixel::Pixel(int red, int green, int blue)
36 {
37     Red = red;
38     Green = green;
39     Blue = blue;
40     Alpha = 0xff;
41 }
42 
43 ///////////////////////////////////////////////////////////////////////////////
Pixel(GX_COLOR color)44 Pixel::Pixel(GX_COLOR color)
45 {
46     Red = (color >> 16) & 0xff;
47     Green = (color >> 8) & 0xff;
48     Blue = color & 0xff;
49 }
50 ///////////////////////////////////////////////////////////////////////////////
operator !=(const Pixel & other) const51 BOOL Pixel::operator != (const Pixel &other) const
52 {
53     if (Red == other.Red && Green == other.Green &&
54         Blue == other.Blue && Alpha == other.Alpha)
55     {
56         return FALSE;
57     }
58     return TRUE;
59 }
60 
61 ///////////////////////////////////////////////////////////////////////////////
operator ==(const Pixel & other) const62 BOOL Pixel::operator == (const Pixel &other) const
63 {
64     if (Red == other.Red && Green == other.Green &&
65         Blue == other.Blue && Alpha == other.Alpha)
66     {
67         return TRUE;
68     }
69     return FALSE;
70 }
71 
72 /*
73     Image reader base class. This class defines functionality of storing pixels to
74     memory in each of the supported formats. The base class also takes care of
75     initializing the GX_PIXELMAP structure, color space remapping,
76     RLE encoding, and Dithering.
77 
78     The individual PNG, JPG, etc decoders should be derived from this base. They
79     have to provide these functions:
80     1) ReadImage: The main function to decode whatever type of image it is an place
81         the data in RAM.
82 
83     2) GetInputDataPtr: Function that returns address of a specified scanline in the
84         source data.
85 
86     3) mpReadInputPixel: This is a function pointer that must be initialized by the
87         sub-class, once the sub-class has identified the input data format.
88        Default pixel readers are provided by the base class for 16 bpp 565, 24 bpp packed,
89        and 32 bpp argb formats.
90 
91     4) The sub-class should call the function FinalizeImage after it has decoded the source
92        data into RAM. FinalizeImage will do the color space conversion and/or RLE
93        compression.
94 */
95 
96 ///////////////////////////////////////////////////////////////////////////////
image_reader()97 image_reader::image_reader()
98 {
99     mFile = NULL;
100 
101     mMode = 0;
102 
103     mDithering = FALSE;
104     mWantAlpha = FALSE;
105     mInputHasAlpha = FALSE;
106     mSaveAlpha = FALSE;
107     mDoCompress = FALSE;
108     mTargaFormat = FALSE;
109 
110     mpReadInputPixel = NULL;
111     mpReadOutputPixel = NULL;
112     mpWritePixel = NULL;
113     mpWriteTransparentPix = NULL;
114 
115     mpPalette = NULL;
116     mPalSize = 0;
117     mPalFixed = 0;
118     mDisplayFormat = 0;
119 }
120 
121 ///////////////////////////////////////////////////////////////////////////////
~image_reader()122 image_reader::~image_reader()
123 {
124 }
125 
126 // CreateProperReader: This function is called by external code to
127 // create an image_reader sub-class that is correct for the image type.
128 // i.e. the caller doesn't have to figure what type of image it is,
129 // just call this function and it will do it for you and return
130 // an image_reader instance.
131 ///////////////////////////////////////////////////////////////////////////////
CreateProperReader(CString & path)132 image_reader *image_reader::CreateProperReader(CString &path)
133 {
134     return CreateProperReader(GetImageType(path));
135 }
136 
137 ///////////////////////////////////////////////////////////////////////////////
CreateProperReader(unsigned char * data,int data_size)138 image_reader *image_reader ::CreateProperReader(unsigned char* data, int data_size)
139 {
140     return CreateProperReader(GetImageType(data, data_size));
141 }
142 
143 ///////////////////////////////////////////////////////////////////////////////
CreateProperReader(int image_type)144 image_reader* image_reader::CreateProperReader(int image_type)
145 {
146     image_reader* pReader = NULL;
147 
148     switch (image_type)
149     {
150     case IMAGE_TYPE_PNG:
151         pReader = new png_reader();
152         break;
153 
154     case IMAGE_TYPE_JPG:
155         pReader = new jpg_reader();
156         break;
157 
158     case IMAGE_TYPE_GIF:
159         pReader = new gif_reader();
160         break;
161 
162     default:
163         break;
164     }
165     return pReader;
166 }
167 
168 // can be called by app code if image is not needed. Cleans
169 // up image storage.
170 ///////////////////////////////////////////////////////////////////////////////
DestroyImage(void)171 void image_reader::DestroyImage(void)
172 {
173     GX_PIXELMAP *map;
174 
175     for(int index = 0; index < mPixelmapList.GetCount(); index++)
176     {
177         map = mPixelmapList.GetAt(index);
178 
179         if (map->gx_pixelmap_data)
180         {
181             delete [] map->gx_pixelmap_data;
182         }
183 
184         if (map->gx_pixelmap_aux_data)
185         {
186             delete [] map->gx_pixelmap_aux_data;
187         }
188 
189         delete map;
190     }
191 }
192 
193 ///////////////////////////////////////////////////////////////////////////////
ResizeImage(GX_PIXELMAP * src,int dest_width,int dest_height)194 GX_PIXELMAP *image_reader::ResizeImage(GX_PIXELMAP *src, int dest_width, int dest_height)
195 {
196     if (!mPixelmapList.GetCount() || dest_width <= 0 || dest_height <= 0)
197     {
198         return NULL;
199     }
200     if (src->gx_pixelmap_flags & GX_PIXELMAP_COMPRESSED)
201     {
202         // can't resize a compressed image. just return:
203         return NULL;
204     }
205 
206     SetOutputColorFormat(src->gx_pixelmap_format, mDisplayFormat);
207     int output_stride = CalculateOutputStride(dest_width);
208 
209     // Initialize Pixelmap structure and
210     // create a buffer to hold the correctly formatted data:
211 
212     int new_data_size = output_stride * dest_height;
213     UCHAR *pData = new UCHAR[new_data_size];
214     memset(pData, 0, (output_stride * dest_height));
215     GX_PIXELMAP *newmap = new GX_PIXELMAP;
216     memset(newmap, 0, sizeof(GX_PIXELMAP));
217 
218     newmap->gx_pixelmap_data = pData;
219     newmap->gx_pixelmap_height = dest_height;
220     newmap->gx_pixelmap_width = dest_width;
221     newmap->gx_pixelmap_flags = src->gx_pixelmap_flags;
222     newmap->gx_pixelmap_format = src->gx_pixelmap_format;
223     newmap->gx_pixelmap_data_size = new_data_size;
224     newmap->gx_pixelmap_aux_data_size = 0;
225     newmap->gx_pixelmap_aux_data = NULL;
226     newmap->gx_pixelmap_transparent_color = src->gx_pixelmap_transparent_color;
227 
228     // check to see if we need an aux-data
229     switch(mOutputFormat)
230     {
231     case GX_COLOR_FORMAT_MONOCHROME:
232     case GX_COLOR_FORMAT_MONOCHROME_INVERTED:
233     case GX_COLOR_FORMAT_2BIT_GRAY:
234     case GX_COLOR_FORMAT_2BIT_GRAY_INVERTED:
235     case GX_COLOR_FORMAT_4BIT_GRAY_INVERTED:
236     case GX_COLOR_FORMAT_4BIT_VGA:
237     case GX_COLOR_FORMAT_8BIT_GRAY:
238     case GX_COLOR_FORMAT_8BIT_GRAY_INVERTED:
239         break;
240 
241 
242     case GX_COLOR_FORMAT_4BIT_GRAY:
243         if (src->gx_pixelmap_aux_data &&
244             src->gx_pixelmap_aux_data_size)
245         {
246             // need a seperate transparent mask value channel:
247             int aux_data_size = ((dest_width  + 7) >> 3)* dest_height;
248             newmap->gx_pixelmap_aux_data = new UCHAR[aux_data_size];
249             newmap->gx_pixelmap_aux_data_size = aux_data_size;
250         }
251         break;
252 
253     case GX_COLOR_FORMAT_8BIT_PALETTE:
254         if (src->gx_pixelmap_aux_data &&
255             src->gx_pixelmap_aux_data_size)
256         {
257             // create a copy of the palette:
258             newmap->gx_pixelmap_aux_data = new GX_UBYTE[src->gx_pixelmap_aux_data_size];
259             memcpy_s((void *) (newmap->gx_pixelmap_aux_data), src->gx_pixelmap_aux_data_size, src->gx_pixelmap_aux_data, src->gx_pixelmap_aux_data_size);
260             newmap->gx_pixelmap_aux_data_size = src->gx_pixelmap_aux_data_size;
261         }
262         break;
263 
264     case GX_COLOR_FORMAT_8BIT_PACKED_PIXEL:
265     case GX_COLOR_FORMAT_5551BGRX:
266     case GX_COLOR_FORMAT_1555XRGB:
267     case GX_COLOR_FORMAT_565RGB:
268     case GX_COLOR_FORMAT_565BGR:
269     case GX_COLOR_FORMAT_4444ARGB:
270     case GX_COLOR_FORMAT_4444BGRA:
271         if (mSaveAlpha)
272         {
273             // need a seperate alpha value channel:
274             int aux_data_size = dest_width * dest_height;
275             newmap->gx_pixelmap_aux_data = new UCHAR[aux_data_size];
276             newmap->gx_pixelmap_aux_data_size = aux_data_size;
277         }
278         break;
279 
280     case GX_COLOR_FORMAT_24RGB:
281     case GX_COLOR_FORMAT_24BGR:
282     case GX_COLOR_FORMAT_24XRGB:
283     case GX_COLOR_FORMAT_24BGRX:
284     case GX_COLOR_FORMAT_32ARGB:
285     case GX_COLOR_FORMAT_32RGBA:
286     case GX_COLOR_FORMAT_32ABGR:
287     case GX_COLOR_FORMAT_32BGRA:
288         break;
289     }
290 
291     BitmapStretch(src->gx_pixelmap_width, src->gx_pixelmap_height,
292         dest_width, dest_height, src, newmap);
293 
294     return newmap;
295 }
296 
297 ///////////////////////////////////////////////////////////////////////////////
BitmapStretch(int src_width,int src_height,int dest_width,int dest_height,GX_PIXELMAP * src,GX_PIXELMAP * dest)298 void image_reader::BitmapStretch(int src_width, int src_height,
299     int dest_width, int dest_height, GX_PIXELMAP *src, GX_PIXELMAP *dest)
300 {
301     //
302     // This algorithm is an implementation of Fast Bitmap Stretching
303     // published by Tomas Moller in Graphics Gems III, p 4-7, code
304     // listing on page 411-413 and also found here:
305     //
306     // http://tog.acm.org/resources/GraphicsGems/gemsiii/fastBitmap.c
307     //
308 
309     int dx, dy, e, d, dx2;
310     int yIn = 0;
311     int yOut = 0;
312     dx = dest_height;
313     dy = src_height;
314     e = (dy << 1) - dx;
315     dx2 = dx << 1;
316     dy <<= 1;
317 
318     for (d = 0; d < dx; d++)
319     {
320         BitmapStretchStep(dest_width, src_width, yIn, yOut, src, dest);
321 
322         while(e >= 0 && dx2)
323         {
324             yIn++;
325             e -= dx2;
326         }
327 
328         yOut++;
329         e += dy;
330     }
331 }
332 
333 ///////////////////////////////////////////////////////////////////////////////
BitmapStretchStep(int dest_width,int source_width,int yIn,int yOut,GX_PIXELMAP * src,GX_PIXELMAP * dest)334 void image_reader::BitmapStretchStep(int dest_width,
335     int source_width, int yIn, int yOut,
336     GX_PIXELMAP *src, GX_PIXELMAP *dest)
337 {
338     // Note:
339     //
340     // This function is an implementation of Fast Bitmap Stretching
341     // published by Tomas Moller in Graphics Gems III, p 4-7, code
342     // listing on page 411-413 and also found here:
343     //
344     // http://tog.acm.org/resources/GraphicsGems/gemsiii/fastBitmap.c
345     //
346 
347     int dx, dy, e, d, dx2;
348     int xIn = 0;
349     int xOut = 0;
350     Pixel val;
351     dx = dest_width;
352     dy = source_width;
353     e = (dy << 1) - dx;
354     dx2 = dx << 1;
355     dy <<= 1;
356     mpGetData = src->gx_pixelmap_data;
357     int stride = CalculateOutputStride(source_width);
358     mpGetData += (yIn * stride);
359 
360     stride = CalculateOutputStride(dest_width);
361     mpPutData = (GX_UBYTE *) dest->gx_pixelmap_data;
362     mpPutData += (yOut * stride);
363 
364     if (src->gx_pixelmap_aux_data != GX_NULL)
365     {
366         int SrcAuxStride = source_width;
367         if (src->gx_pixelmap_format == GX_COLOR_FORMAT_4BIT_GRAY)
368         {
369             /* 4bpp use 1bit to mask transparent. */
370             SrcAuxStride = (source_width + 7) >> 3;
371         }
372         mpGetAux = src->gx_pixelmap_aux_data;
373         mpGetAux += yIn * SrcAuxStride;
374 
375         int DestAuxStride = dest_width;
376         if (dest->gx_pixelmap_format == GX_COLOR_FORMAT_4BIT_GRAY)
377         {
378             /* 4bpp use 1bit to mask transparent. */
379             DestAuxStride = (dest_width + 7) >> 3;
380             this->mNibbleMask = 0xf0;
381             this->mMonoMask = 0x80;
382         }
383         mpPutAux = (UCHAR *)dest->gx_pixelmap_aux_data;
384         mpPutAux += yOut * DestAuxStride;
385     }
386 
387     if (dest->gx_pixelmap_format == GX_COLOR_FORMAT_MONOCHROME ||
388         dest->gx_pixelmap_format == GX_COLOR_FORMAT_MONOCHROME_INVERTED)
389     {
390         this->mMonoMask = 0x80;
391     }
392 
393     for (d = 0; d < dx; d++)
394     {
395         val = mpReadOutputPixel(this, xIn);
396         mpWritePixel(this, val);
397 
398         while(e >= 0 && dx2)
399         {
400             xIn++;
401             e -= dx2;
402         }
403 
404         xOut++;
405         e += dy;
406     }
407 
408     /* Make data byte-aligned one row for 4bpp fprmat.*/
409     if (dest->gx_pixelmap_format == GX_COLOR_FORMAT_4BIT_GRAY)
410     {
411         if (this->mNibbleMask != 0xf0)
412         {
413             this->mNibbleMask = 0xf0;
414             mpPutData++;
415         }
416         if (this->mMonoMask != 0x80)
417         {
418             this->mpPutAux++;
419             this->mMonoMask = 0x80;
420         }
421     }
422 }
423 
424 ///////////////////////////////////////////////////////////////////////////////
425 // called by app code to retrieve pixelmap pointer
426 ///////////////////////////////////////////////////////////////////////////////
GetPixelmap(int frame_id)427 GX_PIXELMAP *image_reader::GetPixelmap(int frame_id)
428 {
429     if (frame_id < mPixelmapList.GetCount())
430     {
431         return mPixelmapList.GetAt(frame_id);
432     }
433     else
434     {
435         return NULL;
436     }
437 }
438 
439 ///////////////////////////////////////////////////////////////////////////////
GetFrameCount(CString & path)440 int image_reader::GetFrameCount(CString& path)
441 {
442     int frame_count = 1;
443 
444     switch (GetImageType(path))
445     {
446     case IMAGE_TYPE_GIF:
447         frame_count = gif_reader::GetFrameCount(path);
448         break;
449 
450     default:
451         break;
452     }
453 
454     return frame_count;
455 }
456 ///////////////////////////////////////////////////////////////////////////////
457 // called by app code or by CreateProperReader to determine
458 // image type. Note that this used the image data header, not
459 // the filename extension, to determine image type.
460 ///////////////////////////////////////////////////////////////////////////////
GetImageType(CString & path)461 int image_reader::GetImageType(CString &path)
462 {
463     UCHAR ImageType = IMAGE_TYPE_UNKNOWN;
464     UCHAR Buffer[8];
465 
466     // examine the first few bytes of data to determine the image type:
467     FILE *file = _tfopen(path.GetBuffer(), _T("rb"));
468 
469     if (file)
470     {
471         fread(Buffer, 1, 8, file);
472         ImageType = GetImageType(Buffer, 8);
473         fclose(file);
474     }
475     return ImageType;
476 }
477 
478 ///////////////////////////////////////////////////////////////////////////////
GetImageType(unsigned char * data,int data_size)479 int image_reader::GetImageType(unsigned char *data, int data_size)
480 {
481     UCHAR ImageType = IMAGE_TYPE_UNKNOWN;
482     UCHAR Buffer[8];
483 
484     if (data_size < sizeof(Buffer))
485     {
486         return ImageType;
487     }
488 
489     // examine the first few bytes of data to determine the image type:
490     memcpy((void *)Buffer, (void *)data, sizeof(Buffer)); /* Use case of memcpy is verified. */
491 
492     if (Buffer[0] == 'B')
493     {
494         ImageType = IMAGE_TYPE_BMP;
495     }
496     else
497     {
498         if (Buffer[0] == 'G')
499         {
500             ImageType = IMAGE_TYPE_GIF;
501         }
502         else
503         {
504             if (Buffer[1] == 'P')
505             {
506                 ImageType = IMAGE_TYPE_PNG;
507             }
508             else
509             {
510                 if (Buffer[6] == 'J')
511                 {
512                     ImageType = IMAGE_TYPE_JPG;
513                 }
514                 else
515                 {
516                     if (Buffer[1] == 0xd8 && Buffer[0] == 0xff && (Buffer[2] == 0xff))
517                     {
518                         ImageType = IMAGE_TYPE_JPG;
519                     }
520                 }
521             }
522         }
523     }
524 
525     return ImageType;
526 }
527 
528 ///////////////////////////////////////////////////////////////////////////////
529 // called by app if it wants to keep alpha values
SetSaveAlphaVal(BOOL save)530 void image_reader::SetSaveAlphaVal(BOOL save)
531 {
532     mWantAlpha = save;
533 
534     if (save && mInputHasAlpha)
535     {
536         mSaveAlpha = TRUE;
537     }
538 }
539 
540 ///////////////////////////////////////////////////////////////////////////////
DoCompress(BOOL docompress)541 void image_reader::DoCompress(BOOL docompress)
542 {
543     if (docompress)
544     {
545         mDoCompress = TRUE;
546     }
547 }
548 
549 
550 ///////////////////////////////////////////////////////////////////////////////
SetPalette(GX_COLOR * pal,int size,int fixed)551 void image_reader::SetPalette(GX_COLOR *pal, int size, int fixed)
552 {
553     mpPalette = pal;
554     mPalSize = size;
555     mPalFixed = fixed;
556 }
557 
558 
559 ///////////////////////////////////////////////////////////////////////////////
560 // Called by sub-class when raw input data is ready to go. This
561 // function does color space mapping and compression.
562 ///////////////////////////////////////////////////////////////////////////////
FinalizeImage(int width,int height)563 BOOL image_reader::FinalizeImage(int width, int height)
564 {
565     // initialize output color format and pixel writer function
566     // this has to be done now, after the image has been
567     // read, so that we know if we are saving alpha values
568     // or not.
569 
570     if (!SetOutputColorFormat(mOutputFormat, mDisplayFormat))
571     {
572         return FALSE;
573     }
574 
575     int output_stride = CalculateOutputStride(width);
576 
577     // Initialize Pixelmap structure and
578     // create a buffer to hold the correctly formatted data:
579 
580     UCHAR *pPut = new UCHAR[output_stride * height];
581     GX_PIXELMAP *map = new GX_PIXELMAP;
582 
583     memset(map, 0, sizeof(GX_PIXELMAP));
584 
585     map->gx_pixelmap_data = pPut;
586     map->gx_pixelmap_height = height;
587     map->gx_pixelmap_width = width;
588     map->gx_pixelmap_aux_data_size = 0;
589     map->gx_pixelmap_aux_data = NULL;
590     mSizeTesting = FALSE;
591 
592     // allocate aux data, do color format conversion, dithering if requested
593 
594     switch(mOutputFormat)
595     {
596     case GX_COLOR_FORMAT_MONOCHROME_INVERTED:
597     case GX_COLOR_FORMAT_2BIT_GRAY:
598     case GX_COLOR_FORMAT_2BIT_GRAY_INVERTED:
599     case GX_COLOR_FORMAT_4BIT_GRAY_INVERTED:
600     case GX_COLOR_FORMAT_4BIT_VGA:
601     case GX_COLOR_FORMAT_8BIT_GRAY:
602     case GX_COLOR_FORMAT_8BIT_GRAY_INVERTED:
603     case GX_COLOR_FORMAT_8BIT_PALETTE:
604         mSaveAlpha = FALSE;
605         mWantAlpha = FALSE;
606 
607         if (mInputHasAlpha)
608         {
609             map->gx_pixelmap_flags |= GX_PIXELMAP_TRANSPARENT;
610             map->gx_pixelmap_transparent_color = TRANSPARENT_COLOR;
611         }
612         break;
613 
614     case GX_COLOR_FORMAT_MONOCHROME:
615         mSaveAlpha = FALSE;
616         mWantAlpha = FALSE;
617 
618         if (mInputHasAlpha)
619         {
620             map->gx_pixelmap_flags |= GX_PIXELMAP_TRANSPARENT;
621         }
622         break;
623 
624     case GX_COLOR_FORMAT_4BIT_GRAY:
625         mSaveAlpha = FALSE;
626         mWantAlpha = FALSE;
627         if (mInputHasAlpha)
628         {
629             map->gx_pixelmap_flags |= GX_PIXELMAP_TRANSPARENT;
630             int aux_data_size = ((width + 7) >> 3) * height;
631             map->gx_pixelmap_aux_data = new UCHAR[aux_data_size];
632             map->gx_pixelmap_aux_data_size = aux_data_size;
633         }
634         break;
635 
636     case GX_COLOR_FORMAT_8BIT_PACKED_PIXEL:
637     case GX_COLOR_FORMAT_5551BGRX:
638     case GX_COLOR_FORMAT_1555XRGB:
639     case GX_COLOR_FORMAT_565RGB:
640     case GX_COLOR_FORMAT_565BGR:
641         if (mSaveAlpha) // && !do_compress)
642         {
643             // need a seperate alpha value channel:
644             int aux_data_size = width * height;
645             map->gx_pixelmap_aux_data = new UCHAR[aux_data_size];
646             map->gx_pixelmap_aux_data_size = aux_data_size;
647         }
648         break;
649 
650     case GX_COLOR_FORMAT_4444ARGB:
651     case GX_COLOR_FORMAT_4444BGRA:
652         break;
653 
654     case GX_COLOR_FORMAT_24RGB:
655     case GX_COLOR_FORMAT_24BGR:
656     case GX_COLOR_FORMAT_24XRGB:
657     case GX_COLOR_FORMAT_24BGRX:
658     case GX_COLOR_FORMAT_32ARGB:
659     case GX_COLOR_FORMAT_32RGBA:
660     case GX_COLOR_FORMAT_32ABGR:
661     case GX_COLOR_FORMAT_32BGRA:
662         // don't try to dither if 24 bpp or higher
663         if (!(mDisplayFormat == GX_COLOR_FORMAT_565RGB) || (!mSaveAlpha))
664         {
665             mMode &= ~IMAGE_READER_MODE_DITHER;
666         }
667         break;
668     }
669 
670     ColorSpaceConvert(width, height, map);
671 
672     if (mSaveAlpha)
673     {
674         map->gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
675     }
676     map->gx_pixelmap_format = mOutputFormat;
677 
678     mPixelmapList.Add(map);
679     return TRUE;
680 }
681 
682 
683 ///////////////////////////////////////////////////////////////////////////////
684 // called internally as part of RLE encoding
CountDuplicates(int Index,int Width)685 int image_reader::CountDuplicates(int Index, int Width)
686 {
687     int duplicates = 1;
688     Pixel val1;
689     Pixel val2;
690 
691     val1 = mpReadOutputPixel(this, Index);
692     Index++;
693 
694     while(Index < Width)
695     {
696         val2 = mpReadOutputPixel(this, Index);
697         if (val1 == val2)
698         {
699             duplicates++;
700         }
701         else
702         {
703             break;
704         }
705 
706         Index++;
707     }
708 
709     return(duplicates);
710 }
711 
712 ///////////////////////////////////////////////////////////////////////////////
ComputeGrayThreshod(int width,int height)713 void image_reader::ComputeGrayThreshod(int width, int height)
714 {
715     // This function computes a global threshod lies in range 0 ~ 255) that used
716     // to convert an gray image to binary image
717     mGrayThreshod = 0;
718     int count = 0;
719 
720     Pixel val;
721     GX_UBYTE gray;
722 
723     for (int row = 0; row < height; row++)
724     {
725         mpGetData = GetInputDataPtr(row);
726 
727         for (int col = 0; col < width; col++)
728         {
729             mpReadInputPixel(this, col, &val);
730 
731             if (val.Alpha > 128)
732             {
733                 ConvertRGBToGray(val.Red, val.Green, val.Blue, (GX_UBYTE *)&gray);
734                 mGrayThreshod += gray;
735                 count++;
736             }
737         }
738     }
739 
740     if (count)
741     {
742         mGrayThreshod /= count;
743     }
744 
745     if (mGrayThreshod == 0)
746     {
747         //All pixels are black
748         mGrayThreshod = 255;
749     }
750     else if (mGrayThreshod == 255)
751     {
752         mGrayThreshod = 0;
753     }
754 
755     mMonoMask = 0x80;
756 }
757 
758 ///////////////////////////////////////////////////////////////////////////////
ColorSpaceConvert(int width,int height,GX_PIXELMAP * map)759 void image_reader::ColorSpaceConvert(int width, int height, GX_PIXELMAP *map)
760 {
761     mpPutData = (UCHAR *) map->gx_pixelmap_data;
762     mpPutAux = (UCHAR *) map->gx_pixelmap_aux_data;
763 
764     if (mInputHasAlpha && mWantAlpha)
765     {
766         mSaveAlpha = TRUE;
767     }
768 
769     if (mMode & IMAGE_READER_MODE_DITHER)
770     {
771         InitDither(width);
772     }
773 
774     if (mOutputFormat == GX_COLOR_FORMAT_MONOCHROME)
775     {
776         // Compute gray shreshold that can be used to generate
777         // binary image
778         ComputeGrayThreshod(width, height);
779         mMonoMask = 0x80;
780     }
781     else if (mOutputFormat == GX_COLOR_FORMAT_4BIT_GRAY)
782     {
783         /* Use mNibbleMask to mask the wirte bits of 4bit */
784         mNibbleMask = 0xf0;
785         mMonoMask = 0x80;
786     }
787 
788     for (int row = 0; row < height; row++)
789     {
790         mpGetData = GetInputDataPtr(row);
791 
792         if (mMode & IMAGE_READER_MODE_DITHER)
793         {
794             DitherOneRow(width);
795         }
796         else
797         {
798             ColorSpaceConvertRow(width);
799         }
800 
801         if ((mOutputFormat == GX_COLOR_FORMAT_MONOCHROME) && (mMonoMask != 0x80))
802         {
803             while (mMonoMask)
804             {
805                 /* Set bit to make the output always be same. */
806                 *mpPutData &= ~mMonoMask;
807                 mMonoMask >>= 1;
808             }
809             mpPutData++;
810             mMonoMask = 0x80;
811         }
812         else if (mOutputFormat == GX_COLOR_FORMAT_4BIT_GRAY)
813         {
814             if (mNibbleMask != 0xf0)
815             {
816                 mpPutData++;
817                 mNibbleMask = 0xf0;
818             }
819 
820             if (mMonoMask != 0x80)
821             {
822                 mpPutAux++;
823                 mMonoMask = 0x80;
824             }
825         }
826     }
827 
828     map->gx_pixelmap_data_size = (mpPutData - map->gx_pixelmap_data);
829     map->gx_pixelmap_aux_data_size = (mpPutAux - map->gx_pixelmap_aux_data);
830     map->gx_pixelmap_format = mOutputFormat;
831 
832     if (map->gx_pixelmap_format == GX_COLOR_FORMAT_8BIT_PALETTE)
833     {
834         if (mDisplayFormat > GX_COLOR_FORMAT_8BIT_PALETTE)
835         {
836             map->gx_pixelmap_aux_data = (GX_UBYTE *) GetPalette();
837             map->gx_pixelmap_aux_data_size = GetPalSize() * sizeof(GX_COLOR);
838         }
839     }
840 
841     if (mMode & IMAGE_READER_MODE_DITHER)
842     {
843         DitherCleanup();
844     }
845 }
846 
847 ///////////////////////////////////////////////////////////////////////////////
ColorSpaceConvertRow(int Width)848 void image_reader::ColorSpaceConvertRow(int Width)
849 {
850     Pixel val;
851     int PixIndex;
852 
853     for (PixIndex = 0; PixIndex < Width; PixIndex++)
854     {
855         mpReadInputPixel(this, PixIndex, &val);
856         mpWritePixel(this, val);
857     }
858 }
859 
860 ///////////////////////////////////////////////////////////////////////////////
RleEncode(GX_PIXELMAP * pMap,BOOL targa_format)861 BOOL image_reader::RleEncode(GX_PIXELMAP *pMap, BOOL targa_format)
862 {
863     BOOL status = FALSE;
864     int Row;
865     int OriginalSize;
866     int datasize;
867     int auxsize;
868     int DataWidth;
869     int DataHeight;
870 
871     int RowDataSize = 0;
872     int RowAuxSize = 0;
873     int CompressedDataSize = 0;
874     int CompressedAuxSize = 0;
875 
876     mpGetData = pMap->gx_pixelmap_data;
877     mpGetAux = pMap->gx_pixelmap_aux_data;
878 
879     mSizeTesting = TRUE;
880     mTargaFormat = targa_format;
881 
882     DataWidth = pMap->gx_pixelmap_width;
883     DataHeight = pMap->gx_pixelmap_height;
884     int rowRows = DataHeight;
885     int output_stride = CalculateOutputStride(pMap->gx_pixelmap_width);
886     int auxstride = DataWidth;
887 
888     if (mOutputFormat == GX_COLOR_FORMAT_4BIT_GRAY)
889     {
890         /* Use mMonoMask to mask the wirte bits of 4bit(not trans-info) for 4bpp driver. */
891         mNibbleMask = 0xf0;
892         if (mInputHasAlpha)
893         {
894             auxstride = (auxstride + 7) >> 3;
895         }
896     }
897     else if (mOutputFormat == GX_COLOR_FORMAT_MONOCHROME)
898     {
899         if (mInputHasAlpha)
900         {
901             auxstride = (auxstride + 3) >> 2;
902         }
903         else
904         {
905             auxstride = (auxstride + 7) >> 3;
906         }
907     }
908 
909 
910     // first, compute size of compresses data so that we can
911     // test to see if it is smaller
912     mpPutData = NULL;
913     mpPutAux = NULL;
914 
915     for (Row = 0; Row < DataHeight; Row++)
916     {
917         mpGetData = pMap->gx_pixelmap_data + (Row * output_stride);
918         mpGetAux = pMap->gx_pixelmap_aux_data;
919 
920         if (mpGetAux)
921         {
922             mpGetAux += (Row * auxstride);
923         }
924         datasize = auxsize = 0;
925 
926         RleEncodeRow(DataWidth);
927     }
928 
929     CompressedDataSize = (ULONG) mpPutData;
930     CompressedAuxSize = (ULONG) mpPutAux;
931 
932     if (mOutputFormat == GX_COLOR_FORMAT_4BIT_GRAY)
933     {
934         /* For 4bit driver, mNibbleMask equals 0x0f means there's a pixel is stored,
935         but it hasn't been contain by datasize. See parameter mpPutData in function WritePixel4bppgrayscale for more info. */
936         if ((!mInputHasAlpha) && (mNibbleMask == 0x0f))
937         {
938             CompressedDataSize++;
939         }
940     }
941 
942     mSizeTesting = FALSE;
943     OriginalSize = pMap->gx_pixelmap_data_size;
944     OriginalSize += pMap->gx_pixelmap_aux_data_size;
945 
946     if ((CompressedDataSize + CompressedAuxSize) >= OriginalSize)
947     {
948         // compression does not improve size, just return
949         mTargaFormat = FALSE;
950         //Clear flag mDoCompress.
951         mDoCompress = FALSE;
952         return FALSE;
953     }
954 
955     mpPutData = new UCHAR[CompressedDataSize];
956     memset(mpPutData, 0x0, CompressedDataSize);
957     GX_UBYTE *pNewData = mpPutData;
958 
959     if (CompressedAuxSize)
960     {
961         mpPutAux = new UCHAR[CompressedAuxSize];
962     }
963     GX_UBYTE *pNewAux = mpPutAux;
964 
965     if (mOutputFormat == GX_COLOR_FORMAT_4BIT_GRAY)
966     {
967         /* Use mMonoMask to mask the wirte bits of 4bit(not trans-info) for 4bpp driver. */
968         mNibbleMask = 0xf0;
969     }
970 
971     for (Row = 0; Row < DataHeight; Row++)
972     {
973         mpGetData = pMap->gx_pixelmap_data + (Row * output_stride);
974         mpGetAux = NULL;
975 
976         if (pMap->gx_pixelmap_aux_data)
977         {
978             mpGetAux = pMap->gx_pixelmap_aux_data + (Row * auxstride);
979         }
980         RleEncodeRow(DataWidth);
981     }
982 
983     if (pMap->gx_pixelmap_data)
984     {
985         delete [] pMap->gx_pixelmap_data;
986     }
987     pMap->gx_pixelmap_data = pNewData;
988     pMap->gx_pixelmap_data_size = CompressedDataSize;
989 
990     if (pMap->gx_pixelmap_format != GX_COLOR_FORMAT_8BIT_PALETTE)
991     {
992         if (pMap->gx_pixelmap_aux_data)
993         {
994             delete[] pMap->gx_pixelmap_aux_data;
995         }
996 
997         pMap->gx_pixelmap_aux_data = pNewAux;
998         pMap->gx_pixelmap_aux_data_size = CompressedAuxSize;
999     }
1000 
1001     pMap->gx_pixelmap_flags |= GX_PIXELMAP_COMPRESSED;
1002 
1003     if (mTargaFormat)
1004     {
1005         pMap->gx_pixelmap_flags |= GX_PIXELMAP_TARGA;
1006         mTargaFormat = FALSE;
1007     }
1008     //Clear flag mDoCompress.
1009     mDoCompress = FALSE;
1010     return TRUE;
1011 }
1012 
1013 ///////////////////////////////////////////////////////////////////////////////
GetCountLocation()1014 GX_UBYTE *image_reader::GetCountLocation()
1015 {
1016     GX_UBYTE *pPutByteCount = NULL;
1017 
1018     if (mTargaFormat)
1019     {
1020         pPutByteCount = mpPutData++;
1021     }
1022     else
1023     {
1024         switch(mOutputFormat)
1025         {
1026         case GX_COLOR_FORMAT_MONOCHROME:
1027         case GX_COLOR_FORMAT_MONOCHROME_INVERTED:
1028             pPutByteCount = mpPutData;
1029             break;
1030 
1031         case GX_COLOR_FORMAT_2BIT_GRAY:
1032         case GX_COLOR_FORMAT_2BIT_GRAY_INVERTED:
1033         case GX_COLOR_FORMAT_4BIT_GRAY_INVERTED:
1034         case GX_COLOR_FORMAT_4BIT_VGA:
1035             // FIXME: These formats are not done yet
1036             break;
1037 
1038         case GX_COLOR_FORMAT_4BIT_GRAY:
1039             // counts go in the aux data array:
1040             pPutByteCount = mpPutAux++;
1041             break;
1042 
1043         case GX_COLOR_FORMAT_8BIT_GRAY:
1044         case GX_COLOR_FORMAT_8BIT_GRAY_INVERTED:
1045         case GX_COLOR_FORMAT_8BIT_PALETTE:
1046         case GX_COLOR_FORMAT_8BIT_ALPHAMAP:
1047             pPutByteCount = mpPutData++;
1048             break;
1049 
1050         case GX_COLOR_FORMAT_8BIT_PACKED_PIXEL:
1051             if (mSaveAlpha)
1052             {
1053                 // two byte count in the main data stream
1054                 pPutByteCount = mpPutData;
1055                 mpPutData += 2;
1056             }
1057             else
1058             {
1059                 // 1 byte count in main data stream
1060                 // keep the data pointer quad aligned
1061                 pPutByteCount = mpPutData++;
1062             }
1063             break;
1064 
1065         case GX_COLOR_FORMAT_5551BGRX:
1066         case GX_COLOR_FORMAT_1555XRGB:
1067         case GX_COLOR_FORMAT_565RGB:
1068         case GX_COLOR_FORMAT_565BGR:
1069             if (mSaveAlpha)
1070             {
1071                 // 1 byte count in main data stream
1072                 // keep the data pointer quad aligned
1073                 pPutByteCount = mpPutData;
1074             }
1075             else
1076             {
1077                 // two byte count in the main data stream
1078                 pPutByteCount = mpPutData;
1079                 mpPutData += 2;
1080             }
1081             break;
1082 
1083         case GX_COLOR_FORMAT_4444ARGB:
1084         case GX_COLOR_FORMAT_4444BGRA:
1085             // two byte count in the main data stream
1086             pPutByteCount = mpPutData;
1087             mpPutData += 2;
1088             break;
1089 
1090         case GX_COLOR_FORMAT_24RGB:
1091         case GX_COLOR_FORMAT_24BGR:
1092             // one byte count in the main data stream, but must be
1093             // ULONG aligned
1094 
1095             while(((ULONG) mpPutData) & 0x03)
1096             {
1097                 mpPutData++;
1098             }
1099             pPutByteCount = mpPutData++;
1100             break;
1101 
1102         case GX_COLOR_FORMAT_24XRGB:
1103         case GX_COLOR_FORMAT_24BGRX:
1104         case GX_COLOR_FORMAT_32ARGB:
1105         case GX_COLOR_FORMAT_32BGRA:
1106             // counts go in the aux data array:
1107             pPutByteCount = mpPutAux++;
1108             break;
1109         }
1110     }
1111     return pPutByteCount;
1112 }
1113 
1114 ///////////////////////////////////////////////////////////////////////////////
WriteRleCount(USHORT count,UCHAR * pPutCount,BOOL repeat)1115 USHORT image_reader::WriteRleCount(USHORT count, UCHAR *pPutCount, BOOL repeat)
1116 {
1117     USHORT *pPutWordCount;
1118     count -= 1;
1119 
1120     if (mTargaFormat)
1121     {
1122         if (count > 127)
1123         {
1124             count = 127;
1125         }
1126         if (repeat)
1127         {
1128             count |= 0x80;
1129         }
1130         if (!mSizeTesting)
1131         {
1132             *pPutCount = (UCHAR) count;
1133         }
1134         return ((count & 0x7f) + 1);
1135     }
1136 
1137     switch(mOutputFormat)
1138     {
1139     case GX_COLOR_FORMAT_5551BGRX:
1140     case GX_COLOR_FORMAT_1555XRGB:
1141     case GX_COLOR_FORMAT_565RGB:
1142     case GX_COLOR_FORMAT_565BGR:
1143         if (mSaveAlpha)
1144         {
1145             if (count > 127)
1146             {
1147                 count = 127;
1148             }
1149             if (repeat)
1150             {
1151                 count |= 0x80;
1152             }
1153             if (!mSizeTesting)
1154             {
1155                 *pPutCount = (UCHAR) count;
1156             }
1157             return ((count & 0x7f) + 1);
1158         }
1159         else
1160         {
1161             // 16 bit compressed with no alpha uses a two-byte count
1162             if (repeat)
1163             {
1164                 count |= 0x8000;
1165             }
1166 
1167             pPutWordCount = (USHORT *) pPutCount;
1168             if (!mSizeTesting)
1169             {
1170                 *pPutWordCount = count;
1171             }
1172             return ((count & 0x7fff) + 1);
1173         }
1174         break;
1175 
1176     case GX_COLOR_FORMAT_8BIT_PACKED_PIXEL:
1177         if (mSaveAlpha)
1178         {
1179             if (repeat)
1180             {
1181                 count |= 0x8000;
1182             }
1183 
1184             pPutWordCount = (USHORT *)pPutCount;
1185             if (!mSizeTesting)
1186             {
1187                 *pPutWordCount = count;
1188             }
1189             return ((count & 0x7fff) + 1);
1190 
1191         }
1192         else
1193         {
1194             // 8 bit compressed with no alpha uses a one-byte count
1195             if (count > 127)
1196             {
1197                 count = 127;
1198             }
1199             if (repeat)
1200             {
1201                 count |= 0x80;
1202             }
1203             if (!mSizeTesting)
1204             {
1205                 *pPutCount = (UCHAR)count;
1206             }
1207             return ((count & 0x7f) + 1);
1208         }
1209         break;
1210         break;
1211 
1212     case GX_COLOR_FORMAT_4444ARGB:
1213     case GX_COLOR_FORMAT_4444BGRA:
1214         if (repeat)
1215         {
1216             count |= 0x8000;
1217         }
1218 
1219         pPutWordCount = (USHORT *)pPutCount;
1220         if (!mSizeTesting)
1221         {
1222             *pPutWordCount = count;
1223         }
1224         return ((count & 0x7fff) + 1);
1225         break;
1226 
1227     case GX_COLOR_FORMAT_MONOCHROME:
1228         if (mInputHasAlpha)
1229         {
1230             if (count > 0x1f)
1231             {
1232                 count = 0x1f;
1233             }
1234             if (repeat)
1235             {
1236                 count |= 0x20;
1237             }
1238             if (!mSizeTesting)
1239             {
1240                 *pPutCount |= (GX_UBYTE)(count << 2);
1241             }
1242 
1243             return ((count & 0x1f) + 1);
1244         }
1245         else
1246         {
1247             if (count > 0x3f)
1248             {
1249                 count = 0x3f;
1250             }
1251             if (repeat)
1252             {
1253                 count |= 0x40;
1254             }
1255             if (!mSizeTesting)
1256             {
1257                 *pPutCount |= (GX_UBYTE)(count << 1);
1258             }
1259 
1260             return ((count & 0x3f) + 1);
1261         }
1262         break;
1263 
1264     case GX_COLOR_FORMAT_4BIT_GRAY:
1265     default:
1266         // everything else uses a 1-byte count
1267         if (count > 127)
1268         {
1269             count = 127;
1270         }
1271         if (repeat)
1272         {
1273             count |= 0x80;
1274         }
1275         if (!mSizeTesting)
1276         {
1277             *pPutCount = (UCHAR) count;
1278         }
1279         return ((count & 0x7f) + 1);
1280     }
1281 }
1282 
1283 ///////////////////////////////////////////////////////////////////////////////
RleEncodeRow(int Width)1284 void image_reader::RleEncodeRow(int Width)
1285 {
1286     int PixIndex = 0;
1287     Pixel val;
1288     int count;
1289     int RawCount = 0;
1290     UCHAR *pPutByteCount = NULL;
1291 
1292     while(PixIndex < Width)
1293     {
1294         count = CountDuplicates(PixIndex, Width);
1295 
1296         if (count >= 3)     // have 3 or more duplicates?
1297         {
1298             if (RawCount)   // previous raw count?
1299             {
1300                 // save the raw count to the location previously save address
1301                 WriteRleCount(RawCount, pPutByteCount, FALSE);
1302             }
1303             // the previous raw count is now saved.
1304             // Now write
1305             // out the repeat count and save one value
1306             pPutByteCount = GetCountLocation();
1307             count = WriteRleCount(count, pPutByteCount, TRUE);
1308 
1309             val = mpReadOutputPixel(this, PixIndex);
1310             mpWritePixel(this, val);
1311             PixIndex += count;
1312             RawCount = 0;
1313         }
1314         else
1315         {
1316             if (!RawCount)
1317             {
1318                 // save spot to write our raw count
1319                 pPutByteCount = GetCountLocation();
1320             }
1321 
1322             RawCount++;
1323             val = mpReadOutputPixel(this, PixIndex);
1324             mpWritePixel(this, val);
1325             PixIndex++;
1326 
1327             // check for being forced to write out the raw count value
1328             // because we are at the end of row or our count exceeds
1329             // our max
1330             if (RawCount == 128 || PixIndex == Width)
1331             {
1332                 WriteRleCount(RawCount, pPutByteCount, FALSE);
1333                 RawCount = 0;
1334             }
1335         }
1336     }
1337 }
1338 
1339 
1340 ///////////////////////////////////////////////////////////////////////////////
1341 // Note:
1342 // The dithering code is based on the Independent Jpeg Group
1343 // libjpg code. It's called the Floyd Steinburg dithering
1344 // algorithm, and you can find implementations all over the place,
1345 // including here:
1346 /*
1347 // http://en.literateprograms.org/Floyd-Steinberg_dithering_%28C%29
1348 */
1349 // It's been moved here so that all the color space
1350 // conversions can use this dithering if they want to.
1351 //
1352 // The dithering algorithm simply keeps track of the cumulative error
1353 // in the converted colors, and adds this error to the next requested
1354 // color. This eventually causes us to choose a different color, so that
1355 // sum of the colors matches the requested colors sum over time.
1356 //
1357 // The dithering algorithm works left-to-right on one pass, then right
1358 // to left on the next pass to help prevent vertical lines caused by switching
1359 // colors at the same point on row after row.
1360 ///////////////////////////////////////////////////////////////////////////////
DitherOneRow(int Width)1361 void image_reader::DitherOneRow(int Width)
1362 {
1363     int Index = 0;
1364     Pixel OutPixel;
1365     Pixel WantPixel;
1366     int Col;
1367     int LimitCol;
1368     int SpeckleLimit = DITHER_SPECKLE_LIMIT;
1369 
1370     memset(mpNextRedErr, 0, sizeof(int) * (Width + 2));
1371     memset(mpNextGreenErr, 0, sizeof(int) * (Width + 2));
1372     memset(mpNextBlueErr, 0, sizeof(int) * (Width + 2));
1373 
1374     if (mDitherDirection)
1375     {
1376         Col = 0;
1377         LimitCol = Width;
1378     }
1379     else
1380     {
1381         Col = Width - 1;
1382         LimitCol = -1;
1383         Index = Width - 1;
1384     }
1385 
1386     do
1387     {
1388         mpReadInputPixel(this, Index, &OutPixel);
1389 
1390         OutPixel.Red +=  mpThisRedErr[Col + 1] / FS_SCALE ;
1391         OutPixel.Green += mpThisGreenErr[Col + 1] / FS_SCALE;
1392         OutPixel.Blue  += mpThisBlueErr[Col + 1] / FS_SCALE;
1393 
1394         if (OutPixel.Red < 0)
1395         {
1396             OutPixel.Red = 0;
1397         }
1398         else
1399         {
1400             if (OutPixel.Red > 255)
1401             {
1402                 OutPixel.Red = 255;
1403             }
1404         }
1405 
1406         if (OutPixel.Green < 0)
1407         {
1408             OutPixel.Green = 0;
1409         }
1410         else
1411         {
1412             if (OutPixel.Green > 255)
1413             {
1414                 OutPixel.Green = 255;
1415             }
1416         }
1417 
1418         if (OutPixel.Blue < 0)
1419         {
1420             OutPixel.Blue = 0;
1421         }
1422         else
1423         {
1424             if (OutPixel.Blue > 255)
1425             {
1426                 OutPixel.Blue = 255;
1427             }
1428         }
1429 
1430         WantPixel = OutPixel;
1431         Pixel PixelWritten = mpWritePixel(this, OutPixel);
1432         int err;
1433 
1434         if (mDitherDirection)
1435         {
1436             err = (WantPixel.Red - PixelWritten.Red) * FS_SCALE;
1437 
1438             if (abs(err) > SpeckleLimit)
1439             {
1440                 mpThisRedErr[Col + 2] += ( err * 7 ) / 16;
1441                 mpNextRedErr[Col    ] += ( err * 3 ) / 16;
1442                 mpNextRedErr[Col + 1] += ( err * 5 ) / 16;
1443                 mpNextRedErr[Col + 2] += ( err     ) / 16;
1444             }
1445             else
1446             {
1447                 mpThisRedErr[Col + 2] = 0;
1448                 mpNextRedErr[Col    ] = 0;
1449                 mpNextRedErr[Col + 1] = 0;
1450                 mpNextRedErr[Col + 2] = 0;
1451             }
1452 
1453             err = (WantPixel.Green - PixelWritten.Green) * FS_SCALE;
1454 
1455             if (abs(err) > SpeckleLimit)
1456             {
1457                 mpThisGreenErr[Col + 2] += ( err * 7 ) / 16;
1458                 mpNextGreenErr[Col    ] += ( err * 3 ) / 16;
1459                 mpNextGreenErr[Col + 1] += ( err * 5 ) / 16;
1460                 mpNextGreenErr[Col + 2] += ( err     ) / 16;
1461             }
1462             else
1463             {
1464                 mpThisGreenErr[Col + 2] = 0;
1465                 mpNextGreenErr[Col    ] = 0;
1466                 mpNextGreenErr[Col + 1] = 0;
1467                 mpNextGreenErr[Col + 2] = 0;
1468             }
1469 
1470             err = (WantPixel.Blue - PixelWritten.Blue) * FS_SCALE;
1471 
1472             if (abs(err) > SpeckleLimit)
1473             {
1474                 mpThisBlueErr[Col + 2] += ( err * 7 ) / 16;
1475                 mpNextBlueErr[Col    ] += ( err * 3 ) / 16;
1476                 mpNextBlueErr[Col + 1] += ( err * 5 ) / 16;
1477                 mpNextBlueErr[Col + 2] += ( err     ) / 16;
1478             }
1479             else
1480             {
1481                 mpThisBlueErr[Col + 2] = 0;
1482                 mpNextBlueErr[Col    ] = 0;
1483                 mpNextBlueErr[Col + 1] = 0;
1484                 mpNextBlueErr[Col + 2] = 0;
1485             }
1486         }
1487         else
1488         {
1489             err = (WantPixel.Red - PixelWritten.Red) * FS_SCALE;
1490 
1491             if (abs(err) > SpeckleLimit)
1492             {
1493                 mpThisRedErr[Col    ] += ( err * 7 ) / 16;
1494                 mpNextRedErr[Col + 2] += ( err * 3 ) / 16;
1495                 mpNextRedErr[Col + 1] += ( err * 5 ) / 16;
1496                 mpNextRedErr[Col    ] += ( err     ) / 16;
1497             }
1498             else
1499             {
1500                 mpThisRedErr[Col    ] = 0;
1501                 mpNextRedErr[Col + 2] = 0;
1502                 mpNextRedErr[Col + 1] = 0;
1503                 mpNextRedErr[Col    ] = 0;
1504             }
1505 
1506             err = (WantPixel.Green - PixelWritten.Green) * FS_SCALE;
1507 
1508             if (abs(err) > SpeckleLimit)
1509             {
1510                 mpThisGreenErr[Col    ] += ( err * 7 ) / 16;
1511                 mpNextGreenErr[Col + 2] += ( err * 3 ) / 16;
1512                 mpNextGreenErr[Col + 1] += ( err * 5 ) / 16;
1513                 mpNextGreenErr[Col    ] += ( err     ) / 16;
1514             }
1515             else
1516             {
1517                 mpThisGreenErr[Col    ] = 0;
1518                 mpNextGreenErr[Col + 2] = 0;
1519                 mpNextGreenErr[Col + 1] = 0;
1520                 mpNextGreenErr[Col    ] = 0;
1521             }
1522 
1523             err = (WantPixel.Blue - PixelWritten.Blue) * FS_SCALE;
1524 
1525             if (abs(err) > SpeckleLimit)
1526             {
1527                 mpThisBlueErr[Col    ] += ( err * 7 ) / 16;
1528                 mpNextBlueErr[Col + 2] += ( err * 3 ) / 16;
1529                 mpNextBlueErr[Col + 1] += ( err * 5 ) / 16;
1530                 mpNextBlueErr[Col    ] += ( err     ) / 16;
1531             }
1532             else
1533             {
1534                 mpThisBlueErr[Col    ] = 0;
1535                 mpNextBlueErr[Col + 2] = 0;
1536                 mpNextBlueErr[Col + 1] = 0;
1537                 mpNextBlueErr[Col    ] = 0;
1538             }
1539         }
1540 
1541         if (mDitherDirection)
1542         {
1543             Col++;
1544             Index++;
1545         }
1546         else
1547         {
1548             Col--;
1549             Index--;
1550         }
1551     } while ( Col != LimitCol);
1552 
1553     int *temperr = mpThisRedErr;
1554     mpThisRedErr = mpNextRedErr;
1555     mpNextRedErr = temperr;
1556     temperr = mpThisGreenErr;
1557     mpThisGreenErr = mpNextGreenErr;
1558     mpNextGreenErr = temperr;
1559     temperr = mpThisBlueErr;
1560     mpThisBlueErr = mpNextBlueErr;
1561     mpNextBlueErr = temperr;
1562     //mDitherDirection = !mDitherDirection;
1563 }
1564 
1565 ///////////////////////////////////////////////////////////////////////////////
DitherCleanup(void)1566 void image_reader::DitherCleanup(void)
1567 {
1568     delete mpThisRedErr;
1569     delete mpNextRedErr;
1570     delete mpThisGreenErr;
1571     delete mpNextGreenErr;
1572     delete mpThisBlueErr;
1573     delete mpNextBlueErr;
1574     mDithering = FALSE;
1575 }
1576 
1577 ///////////////////////////////////////////////////////////////////////////////
1578 // allocate space for keeping track of dithering error values
InitDither(int cols)1579 BOOL image_reader::InitDither(int cols)
1580 {
1581     mpThisRedErr = new int[cols + 2];
1582     mpNextRedErr = new int[cols + 2];
1583     mpThisGreenErr = new int[cols + 2];
1584     mpNextGreenErr = new int[cols + 2];
1585     mpThisBlueErr = new int[cols + 2];
1586     mpNextBlueErr = new int[cols + 2];
1587 
1588     memset(mpThisRedErr, 0, sizeof(int) * (cols + 2));
1589     memset(mpThisGreenErr, 0, sizeof(int) * (cols + 2));
1590     memset(mpThisBlueErr, 0, sizeof(int) * (cols + 2));
1591     mDitherDirection = 1;
1592     mDithering = TRUE;
1593     return TRUE;
1594 }
1595 
1596 ///////////////////////////////////////////////////////////////////////////////
1597 // Some very basic pixel readers that might be re-used by several
1598 // codecs so they are included in base image_reader class. Most of the
1599 // readers are provided by the sub-class, since they are specific to
1600 // that file type's data formats.
1601 
ReadPixel16(image_reader * reader,int Index,Pixel * Pixel)1602 void image_reader::ReadPixel16(image_reader *reader, int Index,  Pixel *Pixel)
1603 {
1604     USHORT *pVal = (USHORT *) reader->mpGetData;
1605     pVal += Index;
1606     USHORT RawVal = *pVal;
1607 
1608     Pixel->Red = (RawVal >> 8) & 0xf8;
1609     Pixel->Green = (RawVal >> 3) & 0xfc;
1610     Pixel->Blue = (RawVal << 3) & 0xf8;
1611     Pixel->Alpha = 0xff;
1612 }
1613 
1614 ///////////////////////////////////////////////////////////////////////////////
ReadPixel24(image_reader * reader,int Index,Pixel * Pixel)1615 void image_reader::ReadPixel24(image_reader *reader, int Index, Pixel *Pixel)
1616 {
1617     UCHAR *pGet = (UCHAR *) reader->mpGetData;
1618     pGet += Index * 3;
1619     Pixel->Red = *pGet++;
1620     Pixel->Green = *pGet++;
1621     Pixel->Blue = *pGet;
1622     Pixel->Alpha = 0xff;
1623 }
1624 
1625 ///////////////////////////////////////////////////////////////////////////////
ReadPixel32(image_reader * reader,int Index,Pixel * Pixel)1626 void image_reader::ReadPixel32(image_reader *reader, int Index, Pixel *Pixel)
1627 {
1628     const GX_UBYTE *pGet = reader->mpGetData;
1629     pGet += Index * 4;
1630     Pixel->Alpha = *pGet++;
1631     Pixel->Red = *pGet++;
1632     Pixel->Green = *pGet++;
1633     Pixel->Blue = *pGet;
1634 }
1635 
1636 ///////////////////////////////////////////////////////////////////////////////
SetDefaultPixelReader(int bits_per_pix)1637 void image_reader::SetDefaultPixelReader(int bits_per_pix)
1638 {
1639     switch(bits_per_pix)
1640     {
1641     case 15:
1642     case 16:
1643         mpReadInputPixel = &image_reader::ReadPixel16;
1644         break;
1645 
1646     case 24:
1647         mpReadInputPixel = &image_reader::ReadPixel24;
1648         break;
1649 
1650     case 32:
1651         mpReadInputPixel = &image_reader::ReadPixel32;
1652         break;
1653     }
1654 }
1655 
1656 ///////////////////////////////////////////////////////////////////////////////
SetOutputColorFormat(int output_format,int display_format)1657 BOOL image_reader::SetOutputColorFormat(int output_format, int display_format)
1658 {
1659     mOutputFormat = output_format;
1660     mDisplayFormat = display_format;
1661 
1662     if (mInputHasAlpha && mWantAlpha)
1663     {
1664         mSaveAlpha = TRUE;
1665     }
1666 
1667     switch(output_format)
1668     {
1669     case GX_COLOR_FORMAT_MONOCHROME:
1670     case GX_COLOR_FORMAT_MONOCHROME_INVERTED:
1671         if (mInputHasAlpha)
1672         {
1673             mpReadOutputPixel = &image_reader::ReadPixelMonoTransparent;
1674             mpWritePixel = &image_reader::WritePixelMono_transparent;
1675         }
1676         else
1677         {
1678             mpReadOutputPixel = &image_reader::ReadPixelMono;
1679             mpWritePixel = &image_reader::WritePixelMono;
1680         }
1681         break;
1682 
1683     case GX_COLOR_FORMAT_2BIT_GRAY:
1684     case GX_COLOR_FORMAT_2BIT_GRAY_INVERTED:
1685     case GX_COLOR_FORMAT_4BIT_GRAY_INVERTED:
1686     case GX_COLOR_FORMAT_4BIT_VGA:
1687         // not currently supported
1688         return FALSE;
1689 
1690     case GX_COLOR_FORMAT_8BIT_GRAY:
1691     case GX_COLOR_FORMAT_8BIT_GRAY_INVERTED:
1692         // not currently supported
1693         return FALSE;
1694 
1695     case GX_COLOR_FORMAT_4BIT_GRAY:
1696         if (mInputHasAlpha)
1697         {
1698             mpWritePixel = &image_reader::WritePixel4bppgrayscale_transparent;
1699             mpReadOutputPixel = &image_reader::ReadPixel4bppgrayscale_transparent;
1700         }
1701         else
1702         {
1703             mpWritePixel = &image_reader::WritePixel4bppgrayscale;
1704             mpReadOutputPixel = &image_reader::ReadPixel4bppgrayscale;
1705         }
1706         break;
1707 
1708     case GX_COLOR_FORMAT_8BIT_PALETTE:
1709         mpWritePixel = &image_reader::WritePixel8bppPalette;
1710         mpReadOutputPixel = &image_reader::ReadPixel8bppPalette;
1711         break;
1712 
1713     case GX_COLOR_FORMAT_8BIT_PACKED_PIXEL:
1714         if (mSaveAlpha)
1715         {
1716             /*Not support alpha yet.*/
1717             mpWritePixel = &image_reader::WritePixel8Bit_332_Alpha;
1718             mpReadOutputPixel = &image_reader::ReadPixel8Bit_332_Alpha;
1719         }
1720         else
1721         {
1722             mpWritePixel = &image_reader::WritePixel8Bit_332_RGB;
1723             mpReadOutputPixel = &image_reader::ReadPixel8Bit_332_RGB;
1724         }
1725         break;
1726 
1727     case GX_COLOR_FORMAT_8BIT_ALPHAMAP:
1728         mpWritePixel = &image_reader::WritePixel8bppAlpha;
1729         mpReadOutputPixel = &image_reader::ReadPixel8bppAlpha;
1730         break;
1731 
1732     case GX_COLOR_FORMAT_5551BGRX:
1733         mpWritePixel = &image_reader::WritePixel16Bit_555_BGR;
1734         mpReadOutputPixel = &image_reader::ReadPixel16Bit_555_BGR;
1735         break;
1736 
1737     case GX_COLOR_FORMAT_1555XRGB:
1738         if (mSaveAlpha)
1739         {
1740             mpWritePixel = &image_reader::WritePixel16Bit_555_Alpha;
1741             mpReadOutputPixel = &image_reader::ReadPixel16Bit_555_Alpha;
1742         }
1743         else
1744         {
1745             mpWritePixel = &image_reader::WritePixel16Bit_555;
1746             mpReadOutputPixel = &image_reader::ReadPixel16Bit_555;
1747         }
1748         break;
1749 
1750     case GX_COLOR_FORMAT_565RGB:
1751         if (mSaveAlpha)
1752         {
1753             mpWritePixel = &image_reader::WritePixel16Bit_565_Alpha;
1754             mpReadOutputPixel = &image_reader::ReadPixel16Bit_565_Alpha;
1755         }
1756         else
1757         {
1758             mpWritePixel = &image_reader::WritePixel16Bit_565_RGB;
1759             mpReadOutputPixel = &image_reader::ReadPixel16Bit_565_RGB;
1760         }
1761         break;
1762 
1763     case GX_COLOR_FORMAT_565BGR:
1764         if (mSaveAlpha)
1765         {
1766             //mpWritePixel = &image_reader::WritePixel16Bit_565_Alpha;
1767             //mpReadOutputPixel = &image_reader::ReadPixel16Bit_565_Alpha;
1768             mpWritePixel = &image_reader::WritePixel16Bit_565_BGR_Alpha;
1769             mpReadOutputPixel = &image_reader::ReadPixel16Bit_565_BGR_Alpha;
1770         }
1771         else
1772         {
1773             //mpWritePixel = &image_reader::WritePixel16Bit_565_RGB;
1774             //mpReadOutputPixel = &image_reader::ReadPixel16Bit_565_RGB;
1775 
1776             mpWritePixel = &image_reader::WritePixel16Bit_565_BGR;
1777             mpReadOutputPixel = &image_reader::ReadPixel16Bit_565_BGR;
1778         }
1779         break;
1780 
1781 
1782     case GX_COLOR_FORMAT_4444ARGB:
1783         if (mSaveAlpha)
1784         {
1785             mpWritePixel = &image_reader::WritePixel16Bit_4444_ARGB_Alpha;
1786         }
1787         else
1788         {
1789             mpWritePixel = &image_reader::WritePixel16Bit_4444_ARGB;
1790         }
1791         mpReadOutputPixel = &image_reader::ReadPixel16Bit_4444_ARGB;
1792         break;
1793 
1794     case GX_COLOR_FORMAT_4444BGRA:
1795         // FIXME: 4444 format is not done
1796         mpWritePixel = &image_reader::WritePixel16Bit_4444_BGRA;
1797         mpReadOutputPixel = &image_reader::ReadPixel16Bit_4444_BGRA;
1798         break;
1799 
1800     case GX_COLOR_FORMAT_24RGB:
1801         if (mSaveAlpha)
1802         {
1803             mOutputFormat = GX_COLOR_FORMAT_32ARGB;
1804             mpWritePixel = &image_reader::WritePixel32Bit_ARGB;
1805             mpReadOutputPixel = &image_reader::ReadPixel32Bit_ARGB;
1806         }
1807         else
1808         {
1809             mpWritePixel = &image_reader::WritePixel24Bit_RGBPacked;
1810             mpReadOutputPixel = &image_reader::ReadPixel24Bit_RGBPacked;
1811         }
1812         break;
1813 
1814     case GX_COLOR_FORMAT_24BGR:
1815         if (mSaveAlpha)
1816         {
1817             mOutputFormat = GX_COLOR_FORMAT_32BGRA;
1818             mpWritePixel = &image_reader::WritePixel32Bit_BGRA;
1819             mpReadOutputPixel = &image_reader::ReadPixel32Bit_BGRA;
1820         }
1821         else
1822         {
1823             mpWritePixel = &image_reader::WritePixel24Bit_BGRPacked;
1824             mpReadOutputPixel = &image_reader::ReadPixel24Bit_BGRPacked;
1825         }
1826         break;
1827 
1828     case GX_COLOR_FORMAT_24XRGB:
1829     case GX_COLOR_FORMAT_32ARGB:
1830         if ((mDisplayFormat == GX_COLOR_FORMAT_565RGB) && mSaveAlpha)
1831         {
1832             mpWritePixel = &image_reader::WritePixel32Bit_565_RGB_Alpha;
1833         }
1834         else
1835         {
1836             mpWritePixel = &image_reader::WritePixel32Bit_ARGB;
1837         }
1838         mpReadOutputPixel = &image_reader::ReadPixel32Bit_ARGB;
1839 
1840         break;
1841 
1842     case GX_COLOR_FORMAT_24BGRX:
1843     case GX_COLOR_FORMAT_32BGRA:
1844         mpWritePixel = &image_reader::WritePixel32Bit_BGRA;
1845         mpReadOutputPixel = &image_reader::ReadPixel32Bit_BGRA;
1846         break;
1847 
1848     default:
1849         // undefined format
1850         return FALSE;
1851     }
1852     return TRUE;
1853 }
1854 
1855 ///////////////////////////////////////////////////////////////////////////////
1856 #if 0
1857 void image_reader::SetCompression(BOOL bCompress)
1858 {
1859     if (bCompress)
1860     {
1861         mMode |= IMAGE_READER_MODE_COMPRESS;
1862     }
1863     else
1864     {
1865         mMode &= ~IMAGE_READER_MODE_COMPRESS;
1866     }
1867 }
1868 #endif
1869 
1870 ///////////////////////////////////////////////////////////////////////////////
SetDither(BOOL bDither)1871 void image_reader::SetDither(BOOL bDither)
1872 {
1873     if (bDither)
1874     {
1875         mMode |= IMAGE_READER_MODE_DITHER;
1876     }
1877     else
1878     {
1879         mMode &= ~IMAGE_READER_MODE_DITHER;
1880     }
1881 }
1882 
1883 ///////////////////////////////////////////////////////////////////////////////
1884 //void image_reader::SetDisplayFormat(UINT Format)
1885 //{
1886 //    mDisplayFormat = Format;
1887 //}
1888 
1889 ///////////////////////////////////////////////////////////////////////////////
CalculateOutputStride(int width)1890 int image_reader::CalculateOutputStride(int width)
1891 {
1892     int OutputStride = width;
1893 
1894     switch(mOutputFormat)
1895     {
1896     case GX_COLOR_FORMAT_MONOCHROME:
1897     case GX_COLOR_FORMAT_MONOCHROME_INVERTED:
1898         if (mInputHasAlpha)
1899         {
1900             // 1-bit transparency, 1-bit color
1901             width += 3;
1902             OutputStride = width / 4;
1903         }
1904         else
1905         {
1906             width += 7;
1907             OutputStride = width / 8;
1908         }
1909         break;
1910 
1911     case GX_COLOR_FORMAT_2BIT_GRAY:
1912     case GX_COLOR_FORMAT_2BIT_GRAY_INVERTED:
1913         width += 3;
1914         OutputStride = width / 4;
1915         break;
1916 
1917     case GX_COLOR_FORMAT_4BIT_GRAY:
1918     case GX_COLOR_FORMAT_4BIT_GRAY_INVERTED:
1919     case GX_COLOR_FORMAT_4BIT_VGA:
1920         width++;
1921         OutputStride = width / 2;
1922         break;
1923 
1924     case GX_COLOR_FORMAT_8BIT_GRAY:
1925     case GX_COLOR_FORMAT_8BIT_PALETTE:
1926         break;
1927 
1928     case GX_COLOR_FORMAT_8BIT_PACKED_PIXEL:
1929         OutputStride = width;
1930         break;
1931 
1932     case GX_COLOR_FORMAT_5551BGRX:
1933     case GX_COLOR_FORMAT_1555XRGB:
1934     case GX_COLOR_FORMAT_565RGB:
1935     case GX_COLOR_FORMAT_565BGR:
1936     case GX_COLOR_FORMAT_4444ARGB:
1937     case GX_COLOR_FORMAT_4444BGRA:
1938         OutputStride = width * 2;
1939         break;
1940 
1941     case GX_COLOR_FORMAT_24RGB:
1942     case GX_COLOR_FORMAT_24BGR:
1943         OutputStride = width * 3;
1944         break;
1945 
1946     case GX_COLOR_FORMAT_24XRGB:
1947     case GX_COLOR_FORMAT_24BGRX:
1948     case GX_COLOR_FORMAT_32ARGB:
1949     case GX_COLOR_FORMAT_32BGRA:
1950         OutputStride = width * 4;
1951         break;
1952 
1953     default:
1954         OutputStride = width;  // default to 1-byte per pixel
1955         break;
1956     }
1957     return OutputStride;
1958 }
1959 
1960 ///////////////////////////////////////////////////////////////////////////////
ConvertRGBToGray(GX_UBYTE red,GX_UBYTE green,GX_UBYTE blue,GX_UBYTE * gray_val)1961 void image_reader::ConvertRGBToGray(GX_UBYTE red, GX_UBYTE green, GX_UBYTE blue, GX_UBYTE *gray_val)
1962 {
1963     *gray_val = (GX_UBYTE)(((INT)red * 299 + (INT)green * 587 + (INT)blue * 114) / 1000);
1964 }
1965 
1966 ///////////////////////////////////////////////////////////////////////////////
ConvertRGBToGray(GX_COLOR rgb_val,GX_UBYTE * gray_val)1967 void image_reader::ConvertRGBToGray(GX_COLOR rgb_val, GX_UBYTE *gray_val)
1968 {
1969     GX_UBYTE red = (GX_UBYTE)((rgb_val & 0xff0000) >> 16);
1970     GX_UBYTE green = (GX_UBYTE)((rgb_val & 0xff00) >> 8);
1971     GX_UBYTE blue = (GX_UBYTE)(rgb_val & 0xff);
1972 
1973     ConvertRGBToGray(red, green, blue, gray_val);
1974 
1975 }
1976 
1977 ///////////////////////////////////////////////////////////////////////////////
GetNearestPaletteColor(Pixel want_color,GX_COLOR * palette,int palsize)1978 int image_reader::GetNearestPaletteColor(Pixel want_color, GX_COLOR *palette, int palsize)
1979 {
1980     ULONG nearest_dist = 0x7fffffff;
1981     ULONG dist;
1982     int red_dist;
1983     int green_dist;
1984     int blue_dist;
1985 
1986     int pal_index;
1987     int nearest_index = 0;
1988 
1989     if (palette)
1990     {
1991         for (pal_index = 0; pal_index < palsize; pal_index++)
1992         {
1993             if (pal_index != TRANSPARENT_COLOR)
1994             {
1995                 Pixel pal_color(palette[pal_index]);
1996 
1997                 red_dist = want_color.Red - pal_color.Red;
1998                 green_dist = want_color.Green - pal_color.Green;
1999                 blue_dist = want_color.Blue - pal_color.Blue;
2000 
2001                 dist = (red_dist * red_dist) + (green_dist * green_dist) + (blue_dist * blue_dist);
2002                 if (dist < nearest_dist)
2003                 {
2004                     if (dist == 0)
2005                     {
2006                         return pal_index;
2007                     }
2008                     nearest_dist = dist;
2009                     nearest_index = pal_index;
2010                 }
2011             }
2012         }
2013     }
2014     return nearest_index;
2015 }
2016 
2017 ///////////////////////////////////////////////////////////////////////////////
2018 // pixel data writers. One function for each supported output format
2019 ///////////////////////////////////////////////////////////////////////////////
WritePixelMono_transparent(image_reader * reader,Pixel write)2020 Pixel image_reader::WritePixelMono_transparent(image_reader *reader, Pixel write)
2021 {
2022     Pixel written;
2023     UCHAR *put = reader->mpPutData;
2024     GX_UBYTE gray;
2025     GX_UBYTE transMask;
2026 
2027     if (reader->mDoCompress)
2028     {
2029         /* [1-bit color][1-bit transparency] */
2030         /* Doing RLE here. */
2031         if (!reader->mSizeTesting)
2032         {
2033             if (write.Alpha < 128)
2034             {
2035                 /* Set bits to 0 to mask transparent */
2036                 *put &= 0xfc;
2037             }
2038             else
2039             {
2040                 *put |= 0x01;
2041                 ConvertRGBToGray(write.Red, write.Green, write.Blue, &gray);
2042                 if (gray > reader->mGrayThreshod)
2043                 {
2044                     *put |= 0x02;
2045                 }
2046                 else
2047                 {
2048                     *put &= 0xfd;
2049                 }
2050             }
2051         }
2052         reader->mpPutData++;
2053     }
2054     else
2055     {
2056         transMask = reader->mMonoMask >> 1;
2057         if (!reader->mSizeTesting)
2058         {
2059             if (write.Alpha < 128)
2060             {
2061                 //transparency
2062                 (*put) &= ~transMask;
2063                 //Set bit to make sure the output will always be same.
2064                 (*put) &= ~(reader->mMonoMask);
2065                 written = write;
2066             }
2067             else
2068             {
2069                 (*put) |= transMask;
2070 
2071                 ConvertRGBToGray(write.Red, write.Green, write.Blue, &gray);
2072 
2073                 if (gray > reader->mGrayThreshod)
2074                 {
2075                     written.Red = written.Green = written.Blue = 255;
2076                     (*put) |= reader->mMonoMask;
2077                 }
2078                 else
2079                 {
2080                     written.Red = written.Green = written.Blue = 0;
2081                     (*put) &= ~reader->mMonoMask;
2082                 }
2083             }
2084         }
2085         reader->mMonoMask >>= 2;
2086 
2087         if (!reader->mMonoMask)
2088         {
2089             reader->mpPutData++;
2090             reader->mMonoMask = 0x80;
2091         }
2092     }
2093 
2094     return written;
2095 }
2096 ///////////////////////////////////////////////////////////////////////////////
WritePixelMono(image_reader * reader,Pixel write)2097 Pixel image_reader::WritePixelMono(image_reader *reader, Pixel write)
2098 {
2099     Pixel written;
2100     UCHAR *put = reader->mpPutData;
2101     GX_UBYTE gray;
2102     GX_UBYTE transMask = reader->mMonoMask >> 1;
2103 
2104     if (reader->mDoCompress)
2105     {
2106         /* Doing RLE here. */
2107         if (!reader->mSizeTesting)
2108         {
2109             ConvertRGBToGray(write.Red, write.Green, write.Blue, &gray);
2110             if (gray > reader->mGrayThreshod)
2111             {
2112                 *put |= 0x01;
2113             }
2114             else
2115             {
2116                 *put &= 0xfe;
2117             }
2118         }
2119         reader->mpPutData++;
2120     }
2121     else
2122     {
2123         if (!reader->mSizeTesting)
2124         {
2125             ConvertRGBToGray(write.Red, write.Green, write.Blue, &gray);
2126             if (gray > reader->mGrayThreshod)
2127             {
2128                 written.Red = written.Green = written.Blue = 255;
2129                 (*put) |= reader->mMonoMask;
2130             }
2131             else
2132             {
2133                 written.Red = written.Green = written.Blue = 0;
2134                 (*put) &= ~reader->mMonoMask;
2135             }
2136         }
2137         written.Alpha = 0xff;
2138 
2139         reader->mMonoMask >>= 1;
2140 
2141         if (!reader->mMonoMask)
2142         {
2143             reader->mpPutData++;
2144             reader->mMonoMask = 0x80;
2145         }
2146     }
2147 
2148     return written;
2149 }
2150 
2151 ///////////////////////////////////////////////////////////////////////////////
WritePixel4bppgrayscale_transparent(image_reader * reader,Pixel write)2152 Pixel image_reader::WritePixel4bppgrayscale_transparent(image_reader *reader, Pixel write)
2153 {
2154     Pixel written;
2155     UCHAR *put = reader->mpPutData;
2156     UCHAR *putaux = reader->mpPutAux;
2157     GX_UBYTE gray;
2158 
2159     if (!reader->mSizeTesting)
2160     {
2161         ConvertRGBToGray(write.Red, write.Green, write.Blue, &gray);
2162         gray >>= 4;
2163         written.Red = written.Green = written.Blue = gray | (gray << 4);
2164 
2165         if (reader->mDoCompress)
2166         {
2167             if (write.Alpha < 128)
2168             {
2169                 *put = TRANSPARENT_COLOR;
2170             }
2171             else
2172             {
2173                 *put = gray;
2174             }
2175         }
2176         else
2177         {
2178             *put &= (GX_UBYTE)(~reader->mNibbleMask);
2179             if (reader->mNibbleMask & 0xf0)
2180             {
2181                 *put = gray << 4;
2182             }
2183             else
2184             {
2185                 *put |= gray;
2186             }
2187 
2188             if (reader->mMonoMask == 0x80)
2189             {
2190                 /* Set bits to 0 in case that pixelmap data will be initialized differetly for different enviroment. */
2191                 *putaux = 0;
2192             }
2193 
2194             if (write.Alpha > 128)
2195             {
2196                 *putaux &= (GX_UBYTE)(~reader->mMonoMask);
2197             }
2198             else
2199             {
2200                 *putaux |= reader->mMonoMask;
2201             }
2202         }
2203     }
2204 
2205 
2206     if (reader->mDoCompress)
2207     {
2208         reader->mpPutData++;
2209     }
2210     else
2211     {
2212         reader->mNibbleMask >>= 4;
2213         if (!reader->mNibbleMask)
2214         {
2215             reader->mpPutData++;
2216             reader->mNibbleMask = 0xf0;
2217         }
2218 
2219         reader->mMonoMask >>= 1;
2220         if (reader->mMonoMask == 0)
2221         {
2222             reader->mMonoMask = 0x80;
2223             reader->mpPutAux++;
2224         }
2225     }
2226 
2227     return written;
2228 }
2229 
2230 ///////////////////////////////////////////////////////////////////////////////
WritePixel4bppgrayscale(image_reader * reader,Pixel write)2231 Pixel image_reader::WritePixel4bppgrayscale(image_reader *reader, Pixel write)
2232 {
2233     Pixel written;
2234     UCHAR *put = reader->mpPutData;
2235     GX_UBYTE gray;
2236 
2237     if (!reader->mSizeTesting)
2238     {
2239         ConvertRGBToGray(write.Red , write.Green, write.Blue, &gray);
2240         gray >>= 4;
2241         written.Red = written.Green = written.Blue = gray | (gray << 4);
2242 
2243         *put &= (GX_UBYTE)(~reader->mNibbleMask);
2244         if (reader->mNibbleMask & 0xf0)
2245         {
2246             *put = gray << 4;
2247         }
2248         else
2249         {
2250             *put |= gray;
2251         }
2252     }
2253 
2254     reader->mNibbleMask >>= 4;
2255     if (!reader->mNibbleMask)
2256     {
2257         reader->mpPutData++;
2258         reader->mNibbleMask = 0xf0;
2259     }
2260 
2261     return written;
2262 }
2263 
2264 ///////////////////////////////////////////////////////////////////////////////
WritePixel8bppPalette(image_reader * reader,Pixel write)2265 Pixel image_reader::WritePixel8bppPalette(image_reader *reader, Pixel write)
2266 {
2267     Pixel written;
2268     int PalIndex;
2269     UCHAR *PutIndex = reader->mpPutData;
2270     reader->mpPutData++;;
2271 
2272     if (!reader->mSizeTesting)
2273     {
2274         GX_COLOR *palette = reader->GetPalette();
2275 
2276         if (write.Alpha < 128)
2277         {
2278             *PutIndex = TRANSPARENT_COLOR;
2279             written = write;
2280         }
2281         else
2282         {
2283             if (palette)
2284             {
2285                 PalIndex = GetNearestPaletteColor(write, palette, reader->GetPalSize());
2286 
2287                 *PutIndex = PalIndex;
2288                 Pixel PalColor(palette[PalIndex]);
2289                 written = PalColor;
2290             }
2291             else
2292             {
2293                 *PutIndex = 0;
2294                 written.Red = written.Green = written.Blue = written.Alpha = 0;
2295             }
2296         }
2297     }
2298     return written;
2299 }
2300 
2301 ///////////////////////////////////////////////////////////////////////////////
WritePixel8bppAlpha(image_reader * reader,Pixel write)2302 Pixel image_reader::WritePixel8bppAlpha(image_reader *reader, Pixel write)
2303 {
2304     UCHAR *pData = reader->mpPutData++;
2305     if (!reader->mSizeTesting)
2306     {
2307         *pData = (UCHAR) write.Alpha;
2308     }
2309     return write;
2310 }
2311 ///////////////////////////////////////////////////////////////////////////////
WritePixel8Bit_332_RGB(image_reader * reader,Pixel write)2312 Pixel image_reader::WritePixel8Bit_332_RGB(image_reader *reader, Pixel write)
2313 {
2314 GX_UBYTE HiColor;
2315 GX_UBYTE *pPutHColor;
2316 Pixel written;
2317 
2318     pPutHColor = reader->mpPutData;
2319     reader->mpPutData ++;
2320     written = write;
2321     written.Red &= 0xe0;
2322     written.Green &= 0xe0;
2323     written.Blue &= 0xc0;
2324 
2325     if (!reader->mSizeTesting)
2326     {
2327         HiColor = written.Red;
2328         HiColor |= (written.Green >> 3);
2329         HiColor |= written.Blue >> 6;
2330         *pPutHColor = HiColor;
2331     }
2332     return written;
2333 }
2334 ///////////////////////////////////////////////////////////////////////////////
2335 //haven't support now.
2336 
WritePixel8Bit_332_Alpha(image_reader * reader,Pixel write)2337 Pixel image_reader::WritePixel8Bit_332_Alpha(image_reader *reader, Pixel write)
2338 {
2339 GX_UBYTE    HiColor;
2340 GX_UBYTE   *pPutHColor;
2341 USHORT     *pPut_A_Hcolor;
2342 Pixel       written;
2343 
2344     written = write;
2345     written.Red &= 0xe0;
2346     written.Green &= 0xe0;
2347     written.Blue &= 0xc0;
2348 
2349 
2350     if (!reader->mSizeTesting)
2351     {
2352 
2353         HiColor = written.Red;
2354         HiColor |= (written.Green >> 3);
2355         HiColor |= written.Blue >> 6;
2356 
2357         if (reader->mpPutAux)
2358         {
2359             pPutHColor = (GX_UBYTE *)reader->mpPutData;
2360             reader->mpPutData ++;
2361             *pPutHColor = HiColor;
2362 
2363             // save alpha in seperate array
2364             *reader->mpPutAux = write.Alpha;
2365             reader->mpPutAux++;
2366         }
2367         else
2368         {
2369             pPut_A_Hcolor = (USHORT *)reader->mpPutData;
2370             *pPut_A_Hcolor = ((USHORT)written.Alpha << 8 | HiColor);
2371 
2372             reader->mpPutData += 2;
2373         }
2374     }
2375     else
2376     {
2377         reader->mpPutData += 2;
2378     }
2379     return written;
2380 }
2381 
2382 
2383 ///////////////////////////////////////////////////////////////////////////////
WritePixel16Bit_555(image_reader * reader,Pixel write)2384 Pixel image_reader::WritePixel16Bit_555(image_reader *reader, Pixel write)
2385 {
2386     USHORT HiColor;
2387     USHORT *pPutHColor;
2388     Pixel written;
2389 
2390     pPutHColor = (USHORT *) reader->mpPutData;
2391     reader->mpPutData += 2;
2392     written = write;
2393     written.Red &= 0xf8;
2394     written.Green &= 0xf8;
2395     written.Blue &= 0xf8;
2396 
2397     if (!reader->mSizeTesting)
2398     {
2399         HiColor =  (USHORT) written.Red;
2400         HiColor <<= 7;
2401         HiColor |= ((USHORT) written.Green << 2);
2402         HiColor |= (written.Blue  >> 3);
2403         *pPutHColor = HiColor;
2404     }
2405     return written;
2406 }
2407 
2408 ///////////////////////////////////////////////////////////////////////////////
WritePixel16Bit_555_BGR(image_reader * reader,Pixel write)2409 Pixel image_reader::WritePixel16Bit_555_BGR(image_reader *reader, Pixel write)
2410 {
2411     USHORT HiColor;
2412     USHORT *pPutHColor;
2413     Pixel written;
2414 
2415     pPutHColor = (USHORT *) reader->mpPutData;
2416     reader->mpPutData += 2;
2417     written = write;
2418     written.Red &= 0xf8;
2419     written.Green &= 0xf8;
2420     written.Blue &= 0xf8;
2421 
2422     if (!reader->mSizeTesting)
2423     {
2424         HiColor =  (USHORT) written.Blue;
2425         HiColor <<= 7;
2426         HiColor |= ((USHORT) written.Green << 2);
2427         HiColor |= written.Red  >> 3;
2428         *pPutHColor = HiColor;
2429     }
2430     return written;
2431 }
2432 
2433 
2434 ///////////////////////////////////////////////////////////////////////////////
WritePixel16Bit_555_Alpha(image_reader * reader,Pixel write)2435 Pixel image_reader::WritePixel16Bit_555_Alpha(image_reader *reader, Pixel write)
2436 {
2437     USHORT HiColor;
2438     USHORT *pPutHColor;
2439     Pixel written;
2440 
2441     written = write;
2442     written.Red &= 0xf8;
2443     written.Green &= 0xf8;
2444     written.Blue &= 0xf8;
2445 
2446     if (!reader->mSizeTesting)
2447     {
2448         HiColor =  (USHORT) written.Red;
2449         HiColor <<= 7;
2450         HiColor |= ((USHORT) written.Green << 2);
2451         HiColor |= (written.Blue  >> 3);
2452 
2453         // if we have a seperate alpha channel, then it means we are not
2454         // writing RLE counts, so the alpha goes into it's own array
2455         if (reader->mpPutAux)
2456         {
2457             pPutHColor = (USHORT *)reader->mpPutData;
2458             reader->mpPutData += 2;
2459             *pPutHColor = HiColor;
2460 
2461             // save alpha in seperate array
2462             *reader->mpPutAux = write.Alpha;
2463             reader->mpPutAux++;
2464         }
2465         else
2466         {
2467             // here if the alpha channel is NULL. The count, alpha, and pixel value
2468             // all go into the same data word.
2469             UCHAR *pPutAlpha = reader->mpPutData;
2470             pPutHColor = (USHORT *)reader->mpPutData;
2471             pPutAlpha++;    // skip the count byte
2472             pPutHColor++;   // skip to lower half-word
2473 
2474             *pPutAlpha = write.Alpha;
2475             *pPutHColor = HiColor;
2476 
2477             reader->mpPutData += 4;        // four bytes total for count, alpha, and pixel value
2478         }
2479     }
2480     else
2481     {
2482         reader->mpPutData += 4;        // four bytes total for count, alpha, and pixel value
2483     }
2484 
2485     return written;
2486 }
2487 
2488 ///////////////////////////////////////////////////////////////////////////////
WritePixel16Bit_565_RGB(image_reader * reader,Pixel write)2489 Pixel image_reader::WritePixel16Bit_565_RGB(image_reader *reader, Pixel write)
2490 {
2491     USHORT HiColor;
2492     USHORT *pPutHColor;
2493     Pixel written;
2494 
2495     pPutHColor = (USHORT *) reader->mpPutData;
2496     reader->mpPutData += 2;
2497     written = write;
2498     written.Red &= 0xf8;
2499     written.Green &= 0xfc;
2500     written.Blue &= 0xf8;
2501 
2502     if (!reader->mSizeTesting)
2503     {
2504         HiColor =  (USHORT) written.Red;
2505         HiColor <<= 8;
2506         HiColor |= ((USHORT) written.Green << 3);
2507         HiColor |= written.Blue  >> 3;
2508         *pPutHColor = HiColor;
2509     }
2510     return written;
2511 }
2512 
2513 
2514 ///////////////////////////////////////////////////////////////////////////////
WritePixel16Bit_565_Alpha(image_reader * reader,Pixel write)2515 Pixel image_reader::WritePixel16Bit_565_Alpha(image_reader *reader, Pixel write)
2516 {
2517     USHORT HiColor;
2518     USHORT *pPutHColor;
2519     Pixel written;
2520 
2521     written = write;
2522     written.Red &= 0xf8;
2523     written.Green &= 0xfc;
2524     written.Blue &= 0xf8;
2525 
2526     if (!reader->mSizeTesting)
2527     {
2528         HiColor =  (USHORT) written.Red;
2529         HiColor <<= 8;
2530         HiColor |= ((USHORT) written.Green << 3);
2531         HiColor |= written.Blue  >> 3;
2532 
2533         // if we have a seperate alpha channel, then it means we are not
2534         // writing RLE counts, so the alpha goes into it's own array
2535         if (reader->mpPutAux)
2536         {
2537             pPutHColor = (USHORT *) reader->mpPutData;
2538             reader->mpPutData += 2;
2539             *pPutHColor = HiColor;
2540 
2541             // save alpha in seperate array
2542             *reader->mpPutAux = write.Alpha;
2543             reader->mpPutAux++;
2544         }
2545         else
2546         {
2547             // here if the alpha channel is NULL. The count, alpha, and pixel value
2548             // all go into the same data word.
2549             UCHAR *pPutAlpha = reader->mpPutData;
2550             pPutHColor = (USHORT *) reader->mpPutData;
2551             pPutAlpha++;    // skip the count byte
2552             pPutHColor++;   // skip to lower half-word
2553 
2554             *pPutAlpha = write.Alpha;
2555             *pPutHColor = HiColor;
2556 
2557             reader->mpPutData += 4;        // four bytes total for count, alpha, and pixel value
2558         }
2559     }
2560     else
2561     {
2562         reader->mpPutData += 4;        // four bytes total for count, alpha, and pixel value
2563     }
2564     return written;
2565 }
2566 
2567 ///////////////////////////////////////////////////////////////////////////////
WritePixel16Bit_565_BGR(image_reader * reader,Pixel write)2568 Pixel image_reader::WritePixel16Bit_565_BGR(image_reader *reader, Pixel write)
2569 {
2570     USHORT HiColor;
2571     USHORT *pPutHColor;
2572     Pixel written;
2573 
2574     pPutHColor = (USHORT *) reader->mpPutData;
2575     reader->mpPutData += 2;
2576     written = write;
2577     written.Red &= 0xf8;
2578     written.Green &= 0xfc;
2579     written.Blue &= 0xf8;
2580     if (!reader->mSizeTesting)
2581     {
2582         HiColor =  (USHORT) written.Blue;
2583         HiColor <<= 8;
2584         HiColor |= ((USHORT) written.Green << 3);
2585         HiColor |= written.Red  >> 3;
2586         *pPutHColor = HiColor;
2587     }
2588     return written;
2589 }
2590 
2591 ///////////////////////////////////////////////////////////////////////////////
WritePixel16Bit_4444_ARGB_Alpha(image_reader * reader,Pixel write)2592 Pixel image_reader::WritePixel16Bit_4444_ARGB_Alpha(image_reader *reader, Pixel write)
2593 {
2594     USHORT HiColor;
2595     USHORT *pPutHColor;
2596     Pixel written;
2597 
2598     pPutHColor = (USHORT *)reader->mpPutData;
2599     reader->mpPutData += 2;
2600     written = write;
2601     written.Red &= 0xf0;
2602     written.Green &= 0xf0;
2603     written.Blue &= 0xf0;
2604     written.Alpha &= 0xf0;
2605 
2606     if (!reader->mSizeTesting)
2607     {
2608         HiColor = ((USHORT)written.Blue >> 4);
2609         HiColor |= ((USHORT)written.Green);
2610         HiColor |= ((USHORT)written.Red << 4);
2611         HiColor |= ((USHORT)written.Alpha << 8);
2612         *pPutHColor = HiColor;
2613     }
2614 
2615     return written;
2616 }
2617 
2618 ///////////////////////////////////////////////////////////////////////////////
WritePixel16Bit_4444_ARGB(image_reader * reader,Pixel write)2619 Pixel image_reader::WritePixel16Bit_4444_ARGB(image_reader *reader, Pixel write)
2620 {
2621     USHORT HiColor;
2622     USHORT *pPutHColor;
2623     Pixel written;
2624 
2625     pPutHColor = (USHORT *)reader->mpPutData;
2626     reader->mpPutData += 2;
2627     written = write;
2628     written.Red &= 0xf0;
2629     written.Green &= 0xf0;
2630     written.Blue &= 0xf0;
2631     written.Alpha &= 0xf0;
2632 
2633     if (!reader->mSizeTesting)
2634     {
2635         HiColor = ((USHORT)written.Blue >> 4);
2636         HiColor |= ((USHORT)written.Green);
2637         HiColor |= ((USHORT)written.Red << 4);
2638         HiColor |= 0xf000;
2639         *pPutHColor = HiColor;
2640     }
2641 
2642     return written;
2643 }
2644 
2645 ///////////////////////////////////////////////////////////////////////////////
WritePixel16Bit_4444_BGRA(image_reader * reader,Pixel write)2646 Pixel image_reader::WritePixel16Bit_4444_BGRA(image_reader *reader, Pixel write)
2647 {
2648     USHORT HiColor;
2649     USHORT *pPutHColor;
2650     Pixel written;
2651 
2652     pPutHColor = (USHORT *) reader->mpPutData;
2653     reader->mpPutData += 2;
2654     written = write;
2655     written.Red &= 0xf0;
2656     written.Green &= 0xf0;
2657     written.Blue &= 0xf0;
2658     written.Alpha &= 0xf0;
2659 
2660     if (!reader->mSizeTesting)
2661     {
2662         HiColor = (USHORT)(written.Alpha >> 4);
2663         HiColor |= ((USHORT)written.Red);
2664         HiColor |= ((USHORT)written.Green << 4);
2665         HiColor |= ((USHORT)written.Blue << 8);
2666         *pPutHColor = HiColor;
2667     }
2668     return written;
2669 }
2670 
2671 ///////////////////////////////////////////////////////////////////////////////
2672 // KGM not used, we do bgr order when writing resources
WritePixel16Bit_565_BGR_Alpha(image_reader * reader,Pixel write)2673 Pixel image_reader::WritePixel16Bit_565_BGR_Alpha(image_reader *reader, Pixel write)
2674 {
2675     USHORT HiColor;
2676     USHORT *pPutHColor;
2677     Pixel written;
2678 
2679     written = write;
2680     written.Red &= 0xf8;
2681     written.Green &= 0xfc;
2682     written.Blue &= 0xf8;
2683 
2684     if (!reader->mSizeTesting)
2685     {
2686         HiColor =  (USHORT) written.Blue;
2687         HiColor <<= 8;
2688         HiColor |= ((USHORT) written.Green << 3);
2689         HiColor |= written.Red  >> 3;
2690 
2691         // if we have a seperate alpha channel, then it means we are not
2692         // writing RLE counts, so the alpha goes into it's own array
2693         if (reader->mpPutAux)
2694         {
2695             pPutHColor = (USHORT *) reader->mpPutData;
2696             reader->mpPutData += 2;
2697             *pPutHColor = HiColor;
2698 
2699             // save alpha in seperate array
2700             *reader->mpPutAux = write.Alpha;
2701             reader->mpPutAux += 1;
2702         }
2703         else
2704         {
2705             // here if the alpha channel is NULL. The count, alpha, and pixel value
2706             // all go into the same data word.
2707             UCHAR *pPutAlpha = reader->mpPutData;
2708             pPutHColor = (USHORT *) reader->mpPutData;
2709             pPutAlpha++;    // skip the count byte
2710             pPutHColor++;   // skip to lower half-word
2711 
2712             *pPutAlpha = write.Alpha;
2713             *pPutHColor = HiColor;
2714 
2715             reader->mpPutData += 4;        // four bytes total for count, alpha, and pixel value
2716         }
2717     }
2718     else
2719     {
2720         reader->mpPutData += 4;        // four bytes total for count, alpha, and pixel value
2721     }
2722 
2723     return written;
2724 }
2725 
2726 ///////////////////////////////////////////////////////////////////////////////
WritePixel24Bit_RGBPacked(image_reader * reader,Pixel write)2727 Pixel image_reader::WritePixel24Bit_RGBPacked(image_reader *reader, Pixel write)
2728 {
2729     if (!reader->mSizeTesting)
2730     {
2731         UCHAR *pPut = reader->mpPutData;
2732 
2733         *pPut++ = write.Red;
2734         *pPut++ = write.Green;
2735         *pPut++ = write.Blue;
2736     }
2737     reader->mpPutData += 3;
2738     return write;
2739 }
2740 
2741 ///////////////////////////////////////////////////////////////////////////////
WritePixel24Bit_BGRPacked(image_reader * reader,Pixel write)2742 Pixel image_reader::WritePixel24Bit_BGRPacked(image_reader *reader, Pixel write)
2743 {
2744     if (!reader->mSizeTesting)
2745     {
2746         UCHAR *pPut = reader->mpPutData;
2747 
2748         *pPut++ =  write.Blue;
2749         *pPut++ =  write.Green;
2750         *pPut++ =  write.Red;
2751     }
2752     reader->mpPutData += 3;
2753     return write;
2754 }
2755 
2756 ///////////////////////////////////////////////////////////////////////////////
WritePixel32Bit_BGRA(image_reader * reader,Pixel write)2757 Pixel image_reader::WritePixel32Bit_BGRA(image_reader *reader, Pixel write)
2758 {
2759     if (!reader->mSizeTesting)
2760     {
2761         UCHAR *pPut = reader->mpPutData;
2762 
2763         *pPut++ =  write.Alpha;
2764         *pPut++ =  write.Red;
2765         *pPut++ =  write.Green;
2766         *pPut = write.Blue;
2767     }
2768     reader->mpPutData += 4;
2769     return write;
2770 }
2771 
2772 ///////////////////////////////////////////////////////////////////////////////
WritePixel32Bit_ARGB(image_reader * reader,Pixel write)2773 Pixel image_reader::WritePixel32Bit_ARGB(image_reader *reader, Pixel write)
2774 {
2775     if (!reader->mSizeTesting)
2776     {
2777         UCHAR *pPut = reader->mpPutData;
2778         *pPut++ =  write.Blue;
2779         *pPut++ =  write.Green;
2780         *pPut++ =  write.Red;
2781         *pPut = write.Alpha;
2782     }
2783     reader->mpPutData += 4;
2784     return write;
2785 }
2786 
2787 ///////////////////////////////////////////////////////////////////////////////
WritePixel32Bit_565_RGB_Alpha(image_reader * reader,Pixel pPixel)2788 Pixel image_reader::WritePixel32Bit_565_RGB_Alpha(image_reader *reader, Pixel pPixel)
2789 {
2790     Pixel written;
2791 
2792     written = pPixel;
2793     written.Red &= 0xf8;
2794     written.Green &= 0xfc;
2795     written.Blue &= 0xf8;
2796 
2797     if (!reader->mSizeTesting)
2798     {
2799         UCHAR *pPut = reader->mpPutData;
2800         *pPut++ = written.Blue;
2801         *pPut++ = written.Green;
2802         *pPut++ = written.Red;
2803         *pPut = written.Alpha;
2804     }
2805     reader->mpPutData += 4;
2806 
2807     return written;
2808 }
2809 
2810 ///////////////////////////////////////////////////////////////////////////////
2811 // Pixel data readers. Read specified format data back into Pixel.
2812 ///////////////////////////////////////////////////////////////////////////////
ReadPixelMono(image_reader * reader,int PixIndex)2813 Pixel image_reader::ReadPixelMono(image_reader *reader, int PixIndex)
2814 {
2815     Pixel val;
2816     const GX_UBYTE *pLine = reader->mpGetData;
2817     GX_UBYTE color;
2818 
2819     color = *(pLine + (PixIndex >> 3));
2820 
2821     if (color & (0x80 >> (PixIndex & 0x07)))
2822     {
2823         val.Red = val.Green = val.Blue = 0xff;
2824     }
2825     else
2826     {
2827          val.Red = val.Green = val.Blue = 0;
2828     }
2829     val.Alpha = 0xff;
2830 
2831     return val;
2832 }
2833 
2834 ///////////////////////////////////////////////////////////////////////////////
ReadPixelMonoTransparent(image_reader * reader,int PixIndex)2835 Pixel image_reader::ReadPixelMonoTransparent(image_reader *reader, int PixIndex)
2836 {
2837     Pixel val;
2838     const GX_UBYTE *pLine = reader->mpGetData;
2839     GX_UBYTE color;
2840 
2841     color = *(pLine + (PixIndex >> 2));
2842 
2843     /* [1-bit color][1-bit transparency] */
2844     if (color & (0x40 >> ((PixIndex & 0x03) << 1)))
2845     {
2846         if (color & (0x80 >> ((PixIndex & 0x03) << 1)))
2847         {
2848             val.Red = val.Green = val.Blue = 0xff;
2849         }
2850         else
2851         {
2852             val.Red = val.Green = val.Blue = 0;
2853         }
2854 
2855         val.Alpha = 0xff;
2856     }
2857     else
2858     {
2859         val.Alpha = val.Red = val.Green = val.Blue = 0;
2860     }
2861 
2862     return val;
2863 
2864 }
2865 
2866 ///////////////////////////////////////////////////////////////////////////////
ReadPixel4bppgrayscale(image_reader * reader,int PixIndex)2867 Pixel image_reader::ReadPixel4bppgrayscale(image_reader *reader, int PixIndex)
2868 {
2869     Pixel val;
2870     const UCHAR *pLine = reader->mpGetData;
2871     GX_UBYTE color;
2872 
2873     color = *(pLine + (PixIndex >> 1));
2874     if (PixIndex & 1)
2875     {
2876         color &= 0x0f;
2877     }
2878     else
2879     {
2880         color &= 0xf0;
2881         color >>= 4;
2882     }
2883 
2884     color |= color << 4;
2885     val.Red = val.Green = val.Blue = color;
2886     val.Alpha = 0xff;
2887 
2888     return val;
2889 }
2890 
2891 ///////////////////////////////////////////////////////////////////////////////
ReadPixel4bppgrayscale_transparent(image_reader * reader,int PixIndex)2892 Pixel image_reader::ReadPixel4bppgrayscale_transparent(image_reader *reader, int PixIndex)
2893 {
2894     Pixel val;
2895     const UCHAR *pLine = reader->mpGetData;
2896     const UCHAR *pLineAux = reader->mpGetAux;
2897     INT AuxIndex = PixIndex >> 3;
2898     INT ColorIndex = PixIndex >> 1;
2899     GX_UBYTE color = *(pLine + ColorIndex);
2900     GX_UBYTE TransMask = *(pLineAux + AuxIndex);
2901     /* transparent mask is just 1 bit, and from left to right. So we need move it to the low */
2902     TransMask = (GX_UBYTE)(TransMask >> (7 - (PixIndex & 0x07)));
2903 
2904     if (TransMask & 1)
2905     {
2906         val.Alpha = val.Red = val.Green = val.Blue = 0;
2907     }
2908     else
2909     {
2910         if (PixIndex & 1)
2911         {
2912             color &= 0xf;
2913         }
2914         else
2915         {
2916             color &= 0xf0;
2917             color >>= 4;
2918         }
2919         color |= color << 4;
2920         val.Red = val.Green = val.Blue = color;
2921         val.Alpha = 0xff;
2922     }
2923 
2924     return val;
2925 }
2926 
2927 ///////////////////////////////////////////////////////////////////////////////
ReadPixel8bppPalette(image_reader * reader,int PixIndex)2928 Pixel image_reader::ReadPixel8bppPalette(image_reader *reader, int PixIndex)
2929 {
2930     int pal_index;
2931     Pixel val;
2932     GX_COLOR *palette = reader->GetPalette();
2933     const UCHAR *pLine = reader->mpGetData;
2934 
2935     if (palette)
2936     {
2937         pLine += PixIndex;
2938         pal_index = *pLine;
2939 
2940         if (pal_index == TRANSPARENT_COLOR)
2941         {
2942             val.Alpha = val.Red = val.Green = val.Blue = 0;
2943         }
2944         else
2945         {
2946             if (pal_index < reader->GetPalSize())
2947             {
2948                 ULONG color_val = palette[pal_index];
2949                 val.Red =   (color_val >> 16) & 0xff;
2950                 val.Green = (color_val >> 8) & 0xff;
2951                 val.Blue =  color_val & 0xff;
2952                 val.Alpha = 0xff;
2953             }
2954         }
2955     }
2956     return val;
2957 }
2958 
ReadPixel8bppAlpha(image_reader * reader,int PixIndex)2959 Pixel image_reader::ReadPixel8bppAlpha(image_reader *reader, int PixIndex)
2960 {
2961 Pixel val;
2962     const UCHAR *pLine = reader->mpGetData;
2963 
2964     val.Red = 0;
2965     val.Green = 0;
2966     val.Blue = 0;
2967     val.Alpha = *(pLine + PixIndex);
2968     return val;
2969 }
2970 
2971 ///////////////////////////////////////////////////////////////////////////////
ReadPixel8Bit_332_RGB(image_reader * reader,int PixIndex)2972 Pixel image_reader::ReadPixel8Bit_332_RGB(image_reader *reader, int PixIndex)
2973 {
2974     GX_UBYTE HiColor;
2975     GX_UBYTE *pGetColor;
2976     Pixel val;
2977 
2978     pGetColor = (GX_UBYTE *)reader->mpGetData;
2979     pGetColor += PixIndex;
2980     HiColor = *pGetColor;
2981 
2982     val.Red = (HiColor & 0xe0);
2983     val.Green = ((HiColor & 0x1c) << 3);
2984     val.Blue = (HiColor & 0x3) << 6;
2985     val.Alpha = 0xff;
2986     return val;
2987 }
2988 
2989 ///////////////////////////////////////////////////////////////////////////////
ReadPixel8Bit_332_Alpha(image_reader * reader,int PixIndex)2990 Pixel image_reader::ReadPixel8Bit_332_Alpha(image_reader *reader, int PixIndex)
2991 {
2992 GX_UBYTE   HiColor;
2993 GX_UBYTE  *pGetColor;
2994 Pixel      val;
2995 const GX_UBYTE *pLine = reader->mpGetData;
2996 
2997     pGetColor = (GX_UBYTE *)pLine;
2998     pGetColor += PixIndex;
2999 
3000     HiColor = *pGetColor++;
3001     val.Red = HiColor & 0xe0;
3002     val.Green = (HiColor & 0x1c) << 3;
3003     val.Blue = (HiColor & 0x03) << 6;
3004 
3005     const UCHAR *pAux = reader->mpGetAux;
3006     pAux += PixIndex;
3007     val.Alpha = *pAux;
3008     return val;
3009 }
3010 
3011 ///////////////////////////////////////////////////////////////////////////////
ReadPixel16Bit_555(image_reader * reader,int PixIndex)3012 Pixel image_reader::ReadPixel16Bit_555(image_reader *reader, int PixIndex)
3013 {
3014     USHORT HiColor;
3015     USHORT *pGetColor;
3016     Pixel val;
3017 
3018     const UCHAR *pLine = reader->mpGetData;
3019     pGetColor = (USHORT *) pLine;
3020     pGetColor += PixIndex;
3021     HiColor = *pGetColor;
3022 
3023     val.Red = ((HiColor & 0x7c00) >> 7);
3024     val.Green = ((HiColor & 0x03e0) >> 2);
3025     val.Blue = ((HiColor & 0x1f) << 3);
3026     val.Alpha = 0xff;
3027     return val;
3028 }
3029 
3030 ///////////////////////////////////////////////////////////////////////////////
ReadPixel16Bit_555_BGR(image_reader * reader,int PixIndex)3031 Pixel image_reader::ReadPixel16Bit_555_BGR(image_reader *reader, int PixIndex)
3032 {
3033     USHORT HiColor;
3034     USHORT *pGetColor;
3035     Pixel val;
3036     const UCHAR *pLine = reader->mpGetData;
3037 
3038     pGetColor = (USHORT *) pLine;
3039     pGetColor += PixIndex;
3040     HiColor = *pGetColor;
3041 
3042     val.Blue = ((HiColor & 0x7c00) >> 7);
3043     val.Green = ((HiColor & 0x03e0) >> 2);
3044     val.Red = (HiColor & 0x1f);
3045     val.Alpha = 0xff;
3046     return val;
3047 }
3048 
3049 ///////////////////////////////////////////////////////////////////////////////
ReadPixel16Bit_555_Alpha(image_reader * reader,int PixIndex)3050 Pixel image_reader::ReadPixel16Bit_555_Alpha(image_reader *reader, int PixIndex)
3051 {
3052     USHORT HiColor;
3053     USHORT *pGetColor;
3054     Pixel val;
3055     const UCHAR *pLine = reader->mpGetData;
3056 
3057     pGetColor = (USHORT *) pLine;
3058     pGetColor += PixIndex;
3059     HiColor = *pGetColor;
3060 
3061     val.Red = ((HiColor & 0x7c00) >> 7);
3062     val.Green = ((HiColor & 0x03e0) >> 2);
3063     val.Blue = ((HiColor & 0x1f) << 3);
3064 
3065     const UCHAR *pAux = reader->mpGetAux;
3066     pAux += PixIndex;
3067     val.Alpha = *pAux;
3068     return val;
3069 }
3070 
3071 ///////////////////////////////////////////////////////////////////////////////
ReadPixel16Bit_565_RGB(image_reader * reader,int PixIndex)3072 Pixel image_reader::ReadPixel16Bit_565_RGB(image_reader *reader, int PixIndex)
3073 {
3074     USHORT HiColor;
3075     USHORT *pGetColor;
3076     Pixel val;
3077 
3078     pGetColor = (USHORT *) reader->mpGetData;
3079     pGetColor += PixIndex;
3080     HiColor = *pGetColor;
3081 
3082     val.Red = ((HiColor & 0xf800) >> 8);
3083     val.Green = ((HiColor & 0x07e0) >> 3);
3084     val.Blue = (HiColor & 0x1f) << 3;
3085     val.Alpha = 0xff;
3086     return val;
3087 }
3088 
3089 
3090 ///////////////////////////////////////////////////////////////////////////////
ReadPixel16Bit_565_Alpha(image_reader * reader,int PixIndex)3091 Pixel image_reader::ReadPixel16Bit_565_Alpha(image_reader *reader, int PixIndex)
3092 {
3093     USHORT HiColor;
3094     USHORT *pGetColor;
3095     Pixel val;
3096     const GX_UBYTE *pLine = reader->mpGetData;
3097 
3098     pGetColor = (USHORT *) pLine;
3099     pGetColor += PixIndex;
3100     HiColor = *pGetColor;
3101 
3102     val.Red = ((HiColor & 0xf800) >> 8);
3103     val.Green = ((HiColor & 0x07e0) >> 3);
3104     val.Blue = (HiColor & 0x1f) << 3;
3105 
3106     const UCHAR *pAux  = reader->mpGetAux;
3107     pAux += PixIndex;
3108     val.Alpha = *pAux;
3109     return val;
3110 }
3111 
3112 
3113 ///////////////////////////////////////////////////////////////////////////////
ReadPixel16Bit_565_BGR(image_reader * reader,int PixIndex)3114 Pixel image_reader::ReadPixel16Bit_565_BGR(image_reader *reader, int PixIndex)
3115 {
3116     USHORT HiColor;
3117     USHORT *pGetColor;
3118     Pixel val;
3119     const UCHAR *pLine = reader->mpGetData;
3120 
3121     pGetColor = (USHORT *) pLine;
3122     pGetColor += PixIndex;
3123     HiColor = *pGetColor;
3124 
3125     val.Blue = ((HiColor & 0xf800) >> 8);
3126     val.Green = ((HiColor & 0x07e0) >> 3);
3127     val.Red = (HiColor & 0x1f) << 3;
3128     val.Alpha = 0xff;
3129     return val;
3130 }
3131 
3132 ///////////////////////////////////////////////////////////////////////////////
ReadPixel16Bit_565_BGR_Alpha(image_reader * reader,int PixIndex)3133 Pixel image_reader::ReadPixel16Bit_565_BGR_Alpha(image_reader *reader, int PixIndex)
3134 {
3135     USHORT HiColor;
3136     USHORT *pGetColor;
3137     Pixel val;
3138     const GX_UBYTE *pLine = reader->mpGetData;
3139 
3140     pGetColor = (USHORT *) pLine;
3141     pGetColor += PixIndex;
3142     HiColor = *pGetColor;
3143 
3144     val.Blue = ((HiColor & 0xf800) >> 8);
3145     val.Green = ((HiColor & 0x07e0) >> 3);
3146     val.Red = (HiColor & 0x1f) << 3;
3147 
3148     const UCHAR *pAux = reader->mpGetAux;
3149     pAux += PixIndex;
3150     val.Alpha = *pAux;
3151     return val;
3152 }
3153 
3154 ///////////////////////////////////////////////////////////////////////////////
ReadPixel16Bit_4444_ARGB(image_reader * reader,int PixIndex)3155 Pixel image_reader::ReadPixel16Bit_4444_ARGB(image_reader *reader, int PixIndex)
3156 {
3157     USHORT HiColor;
3158     USHORT *pGetColor;
3159     Pixel val;
3160     const UCHAR *pLine = reader->mpGetData;
3161 
3162     pGetColor = (USHORT *)pLine;
3163     pGetColor += PixIndex;
3164     HiColor = *pGetColor;
3165 
3166     val.Alpha = ((HiColor & 0xf000) >> 8);
3167     val.Red = ((HiColor & 0xf00) >> 4);
3168     val.Green = (HiColor & 0xf0);
3169     val.Blue = (HiColor & 0xf) << 4;
3170 
3171     return val;
3172 }
3173 
3174 ///////////////////////////////////////////////////////////////////////////////
ReadPixel16Bit_4444_BGRA(image_reader * reader,int PixIndex)3175 Pixel image_reader::ReadPixel16Bit_4444_BGRA(image_reader *reader, int PixIndex)
3176 {
3177     USHORT HiColor;
3178     USHORT *pGetColor;
3179     Pixel val;
3180     const UCHAR *pLine = reader->mpGetData;
3181 
3182     pGetColor = (USHORT *)pLine;
3183     pGetColor += PixIndex;
3184     HiColor = *pGetColor;
3185 
3186     val.Blue = ((HiColor & 0xf000) >> 8);
3187     val.Green = ((HiColor & 0xf00) >> 4);
3188     val.Red = (HiColor & 0xf0);
3189     val.Alpha = (HiColor & 0xf) << 4;
3190 
3191     return val;
3192 }
3193 
3194 ///////////////////////////////////////////////////////////////////////////////
ReadPixel24Bit_BGRPacked(image_reader * reader,int PixIndex)3195 Pixel image_reader::ReadPixel24Bit_BGRPacked(image_reader *reader, int PixIndex)
3196 {
3197     Pixel val;
3198     const UCHAR *pLine = reader->mpGetData;
3199 
3200     pLine += PixIndex * 3;
3201     val.Blue = *pLine++;
3202     val.Green = *pLine++;
3203     val.Red = *pLine++;
3204     val.Alpha = 0xff;
3205     return val;
3206 }
3207 
3208 ///////////////////////////////////////////////////////////////////////////////
ReadPixel24Bit_RGBPacked(image_reader * reader,int PixIndex)3209 Pixel image_reader::ReadPixel24Bit_RGBPacked(image_reader *reader, int PixIndex)
3210 {
3211     Pixel val;
3212     const UCHAR *pLine = reader->mpGetData;
3213 
3214     pLine += PixIndex * 3;
3215     val.Red = *pLine++;
3216     val.Green = *pLine++;
3217     val.Blue = *pLine++;
3218     val.Alpha = 0xff;
3219     return val;
3220 }
3221 
3222 ///////////////////////////////////////////////////////////////////////////////
ReadPixel32Bit_ARGB(image_reader * reader,int PixIndex)3223 Pixel image_reader::ReadPixel32Bit_ARGB(image_reader *reader, int PixIndex)
3224 {
3225     Pixel val;
3226     const UCHAR *pLine = reader->mpGetData;
3227 
3228     pLine += PixIndex * 4;
3229     val.Blue = *pLine++;
3230     val.Green = *pLine++;
3231     val.Red = *pLine++;
3232     val.Alpha = *pLine;
3233     return val;
3234 }
3235 
3236 ///////////////////////////////////////////////////////////////////////////////
ReadPixel32Bit_BGRA(image_reader * reader,int PixIndex)3237 Pixel image_reader::ReadPixel32Bit_BGRA(image_reader *reader,  int PixIndex)
3238 {
3239     Pixel val;
3240     const UCHAR *pLine = reader->mpGetData;
3241 
3242     pLine += PixIndex * 4;
3243     val.Alpha = *pLine++;
3244     val.Red = *pLine++;
3245     val.Green = *pLine++;
3246     val.Blue = *pLine;
3247     return val;
3248 }
3249 
3250 ///////////////////////////////////////////////////////////////////////////////
3251 // Transparent data writers. Not being used currently
3252 ///////////////////////////////////////////////////////////////////////////////
WriteTransparentPixel_16(UCHAR * pPut,int PixIndex)3253 void image_reader::WriteTransparentPixel_16(UCHAR *pPut, int PixIndex)
3254 {
3255     USHORT *pWrite = (USHORT *) pPut;
3256     pWrite += PixIndex;
3257     *pWrite = 1;
3258 }
3259 
3260 ///////////////////////////////////////////////////////////////////////////////
WriteTransparentPixel_24_BGR(UCHAR * pPut,int PixIndex)3261 void image_reader::WriteTransparentPixel_24_BGR(UCHAR *pPut, int PixIndex)
3262 {
3263     pPut += PixIndex * 3;
3264     *pPut++ = 1;
3265     *pPut++ = 0;
3266     *pPut++ = 0;
3267 }
3268 
3269 ///////////////////////////////////////////////////////////////////////////////
WriteTransparentPixel_24_RGB(UCHAR * pPut,int PixIndex)3270 void image_reader::WriteTransparentPixel_24_RGB(UCHAR *pPut, int PixIndex)
3271 {
3272     pPut += PixIndex * 3;
3273     *pPut++ = 0;
3274     *pPut++ = 0;
3275     *pPut++ = 1;
3276 }
3277 
3278 ///////////////////////////////////////////////////////////////////////////////
WriteTransparentPixel_32BGRA(UCHAR * pPut,int PixIndex)3279 void image_reader::WriteTransparentPixel_32BGRA(UCHAR *pPut, int PixIndex)
3280 {
3281     ULONG *pData = (ULONG *) pPut;
3282     pData += PixIndex;
3283     *pData = 0x0;
3284 }
3285 
3286 ///////////////////////////////////////////////////////////////////////////////
WriteTransparentPixel_32ARGB(UCHAR * pPut,int PixIndex)3287 void image_reader::WriteTransparentPixel_32ARGB(UCHAR *pPut, int PixIndex)
3288 {
3289     ULONG *pData = (ULONG *) pPut;
3290     pData += PixIndex;
3291     *pData = 0x0;
3292 }
3293 
3294 
3295 
3296