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