0023912: TDataStd_ExtStringArray::Value() returns a copy of TCollection_ExtendedStrin...
[occt.git] / src / AlienImage / AlienImage_GIFAlienData.cxx
1 // Created by: DCB
2 // Copyright (c) 1998-1999 Matra Datavision
3 // Copyright (c) 1999-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 // Notes:
21 //    Read()/Write() code is taken from ZOV's sources from Xw package.
22 //    _convert24to8() sources and all concerned code is taken from
23 //      EUG's code of WNT_ImageProcessor.
24
25 #define TEST    //GG_140699
26 //              Check GIF format first.
27
28 #ifdef WNT
29 //it is important to undefine NOGDI and enforce including <windows.h> before
30 //Standard_Macro.hxx defines it and includes <windows.h> making GDI-related
31 //stuff unavailable and causing compilation errors
32 #undef NOGDI
33 #include <windows.h>
34 #endif
35
36 #include <AlienImage_GIFAlienData.ixx>
37 #include <AlienImage_GIFLZWDict.hxx>
38
39 #include <Aspect_GenericColorMap.hxx>
40 #include <Aspect_ColorMapEntry.hxx>
41 #include <Image_Convertor.hxx>
42 #include <Image_DitheringMethod.hxx>
43
44 #ifdef _DEBUG
45 //# define TRACE
46 #endif
47
48 #ifdef TRACE
49 # include <OSD_Timer.hxx>
50 #endif
51
52 #define STGMGR_ALLOC(size)    Standard::Allocate(size)
53 #define STGMGR_FREE(buf,size) Standard::Free((void*&)buf)
54 #define COLORS_SIZE           256*sizeof(BYTE)
55 #define RED                   ((PBYTE)myRedColors)
56 #define GREEN                 ((PBYTE)myGreenColors)
57 #define BLUE                  ((PBYTE)myBlueColors)
58 #define PIXEL                 ((PBYTE)myData)
59
60 #define ZERO_COLORS()                     \
61   memset (myRedColors,   0, COLORS_SIZE); \
62   memset (myGreenColors, 0, COLORS_SIZE); \
63   memset (myBlueColors,  0, COLORS_SIZE);
64
65 #define _ADD_PIXEL(idx)                                     \
66 {                                                           \
67   if (y < height)                                           \
68    *((PBYTE)myData + y*width + x) = ((BYTE)(idx));          \
69   if (++x == width) {                                       \
70     x = 0;                                                  \
71     if (!isInterlace)  ++y;                                 \
72     else  switch (pass) {                                   \
73     case 0:  y += 8; if (y >= height) ++pass, y = 4; break; \
74     case 1:  y += 8; if (y >= height) ++pass, y = 2; break; \
75     case 2:  y += 4; if (y >= height) ++pass, y = 1; break; \
76     default: y += 2;                                        \
77     }                                                       \
78   }                                                         \
79 }
80
81 //================================================================
82 AlienImage_GIFAlienData::AlienImage_GIFAlienData()
83                         : AlienImage_AlienImageData ()
84 {
85   myRedColors      = NULL;
86   myGreenColors    = NULL;
87   myBlueColors     = NULL;
88
89   myData   = NULL;
90   myWidth  = 0;
91   myHeight = 0;
92 }
93
94 //================================================================
95 void AlienImage_GIFAlienData::Clear ()
96 {
97   if (myRedColors) {
98     STGMGR_FREE (myRedColors, COLORS_SIZE);
99     myRedColors = NULL;
100   }
101   if (myGreenColors) {
102     STGMGR_FREE (myGreenColors, COLORS_SIZE);
103     myGreenColors = NULL;
104   }
105   if (myBlueColors) {
106     STGMGR_FREE (myBlueColors, COLORS_SIZE);
107     myBlueColors = NULL;
108   }
109
110   if (myData) {
111     STGMGR_FREE (myData, myWidth*myHeight);
112     myData = NULL;
113     myWidth = myHeight = 0;
114   }
115 }
116
117 //================================================================
118 Standard_Boolean AlienImage_GIFAlienData::Read (OSD_File& file)
119 {
120   Standard_Integer nFileSize = file.Size(), nReadCount;
121   unsigned *OutCode=NULL, *Prefix=NULL, *Suffix=NULL,
122     BitMask, CodeSize, ClearCode, EOFCode, FreeCode, x, y, pass, width, height,
123     InitCodeSize, MaxCode, ReadMask, FirstFree, OutCount, BitOffset,
124     ByteOffset, Code, CurCode, OldCode=0, FinChar=0, InCode;
125   int isInterlace, hasColormap;
126   int i, ncolors;
127   BYTE byte, byte1;
128   PBYTE pFileStream = NULL;
129   // Allocate memory to read the file
130   PBYTE pFileBuffer =
131     (PBYTE) STGMGR_ALLOC (nFileSize);
132   PBYTE rasterPtr = NULL, ptr1;
133   pFileStream = pFileBuffer + 10;
134
135 #ifdef TRACE
136   OSD_Timer timer;
137   cout << "AlienImage_GIFAlienData::Read () starts" << endl << flush;
138   timer.Start ();
139 #endif
140
141   // Read file into memory
142   file.Read ((void*&)pFileBuffer, nFileSize, nReadCount);
143   if (nFileSize != nReadCount) {
144     cout << "GIFAlienData::Read() : BAD file size." << endl << flush;
145     goto _ExitReadError;
146   }
147
148 #ifdef TEST
149   if( strncmp ((char*)pFileBuffer, "GIF87a", 6) &&
150                 strncmp ((char*)pFileBuffer, "GIF89a", 6) )
151     goto _ExitReadError;
152 #endif
153
154   // Determine if the image has colormap
155   byte        = *pFileStream++; // Color descriptor byte (M#CR0#BP)
156   hasColormap = byte & 0x80;
157   ncolors     = hasColormap ? 1<<((byte & 0x07) + 1): 1<<8;
158   BitMask     = ncolors - 1;
159
160   pFileStream += 2; // Skip background byte and following zero byte
161   if (ncolors > 0 && ncolors <= 256) { // Allocate Color Table entries
162     myRedColors   = STGMGR_ALLOC (COLORS_SIZE);
163     myGreenColors = STGMGR_ALLOC (COLORS_SIZE);
164     myBlueColors  = STGMGR_ALLOC (COLORS_SIZE);
165     ZERO_COLORS ();
166
167     for (i=0; i<ncolors; i++) {
168       // Fill in array of XColor's used
169       // Note, that if there's no colormap specified then I use gray scale
170       RED  [i] = ((BYTE)(hasColormap ? *pFileStream++: i));
171       GREEN[i] = ((BYTE)(hasColormap ? *pFileStream++: i));
172       BLUE [i] = ((BYTE)(hasColormap ? *pFileStream++: i));
173     }
174   } else {
175     cout << "GIFAlienData::Read() : There's no colormap"
176          << " in the image (or too big): " << ncolors << endl << flush;
177     goto _ExitReadError;
178   }
179
180   // Skip extension blocks if any.
181   // Format:  <'!'><size><...><size><...><0>
182   while (*pFileStream == '!') {
183     pFileStream += 2; // skip code byte followed '!' sign
184     while (*pFileStream)
185       pFileStream += (unsigned)(1 + *(PBYTE)pFileStream);
186     pFileStream ++;
187   }
188
189   if (*pFileStream++ != ',') { // must be an image descriptor
190     cout << "GIFAlienData::Read() : There's no separator"
191          << " following the colormap" << endl << flush;
192     goto _ExitReadError;
193   }
194
195   pFileStream += 2*2; // Skip image left & top offsets
196   width   = (unsigned) *pFileStream++;
197   width  += ((unsigned)*pFileStream++) << 8;
198   height  = (unsigned) *pFileStream++;
199   height += ((unsigned)*pFileStream++) << 8;
200
201   byte = *pFileStream++;
202   isInterlace = byte & 0x40;
203   if (byte & 0x80) {
204     cout << "GIFAlienData::Read() : Can't read GIF image"
205          << " with locally defined colormap" << endl << flush;
206     goto _ExitReadError;
207   }
208
209   // Allocate the pixel buffer
210   rasterPtr = (PBYTE) STGMGR_ALLOC (nFileSize);
211
212   OutCode = (unsigned *) STGMGR_ALLOC (1025 * sizeof (unsigned int));
213   Prefix  = (unsigned *) STGMGR_ALLOC (4096 * sizeof (unsigned int));
214   Suffix  = (unsigned *) STGMGR_ALLOC (4096 * sizeof (unsigned int));
215
216   // Decode compressed raster data.
217   CodeSize  = *pFileStream++;
218   ClearCode = 1 << CodeSize;
219   EOFCode   = ClearCode + 1;
220   FreeCode  = FirstFree = EOFCode + 1;
221
222   ++CodeSize;
223   InitCodeSize = CodeSize;
224   MaxCode      = 1 << CodeSize;
225   ReadMask     = MaxCode - 1;
226   ptr1         = rasterPtr;
227
228   // Read encoded data to a continuous array pointed to by rasterPtr
229   do {
230     byte = byte1 = *pFileStream++;
231     while (byte--)
232       *ptr1++ = *pFileStream++;
233     if ((long) (ptr1 - rasterPtr) > nFileSize) {// Currupt file
234       cout << "GIFAlienData::Read() : BAD file size." << endl << flush;
235       goto _ExitReadError;
236     }
237   } while (byte1);
238   // The file data has been already read
239   STGMGR_FREE (pFileBuffer, nFileSize);
240   pFileBuffer = NULL;
241
242   // Allocate image data
243   myWidth  = width;
244   myHeight = height;
245   myData = STGMGR_ALLOC (myWidth*myHeight);
246
247   x = y = pass = OutCount = BitOffset = ByteOffset = 0;
248   // Fetch the next code (3 to 12 bits) from the raster data stream
249   Code = rasterPtr[0] + (((unsigned) rasterPtr[1]) << 8);
250   if (CodeSize >= 8)
251     Code += ((unsigned) rasterPtr[2]) << 16;
252
253   Code >>= BitOffset & 0x7;
254   BitOffset += CodeSize;
255   Code      &= ReadMask;
256
257   while (Code != EOFCode) {
258     if (Code == ClearCode) {
259       // Read the next code
260       CodeSize   = InitCodeSize;
261       MaxCode    = 1 << CodeSize;
262       ReadMask   = MaxCode - 1;
263       FreeCode   = FirstFree;
264       ByteOffset = BitOffset >> 3;
265       Code       = rasterPtr[ByteOffset]
266                    + (((unsigned) rasterPtr[ByteOffset + 1]) << 8);
267
268       if (CodeSize >= 8)
269         Code += ((unsigned) rasterPtr[ByteOffset + 2]) << 16;
270
271       Code      >>= BitOffset & 0x7;
272       BitOffset +=  CodeSize;
273       Code      &=  ReadMask;
274
275       CurCode = OldCode = Code;
276       FinChar = CurCode & BitMask;
277
278       _ADD_PIXEL (FinChar);
279     } else {
280       CurCode = InCode = Code;
281       if (CurCode >= FreeCode) {
282         CurCode = OldCode;
283         OutCode[OutCount++] = FinChar;
284       }
285       while (CurCode > BitMask) {
286         if (OutCount > 1024) {
287           cout << "GIFAlienData::Read() : BAD file size." << endl << flush;
288           goto _ExitReadError;
289         }
290         OutCode [OutCount++] = Suffix [CurCode];
291         CurCode = Prefix [CurCode];
292       }
293       FinChar = CurCode & BitMask;
294       OutCode [OutCount++] = FinChar;
295       for (i = OutCount - 1; i >= 0; --i)
296         _ADD_PIXEL (OutCode [i]);
297
298       OutCount = 0;
299       Prefix [FreeCode] = OldCode;
300       Suffix [FreeCode] = FinChar;
301       OldCode = InCode;
302       ++FreeCode;
303       if (FreeCode >= MaxCode) {
304         if (CodeSize < 12) {
305           ++CodeSize;
306           MaxCode <<= 1;
307           ReadMask = (1 << CodeSize) - 1;
308         }
309       }
310     }
311
312     ByteOffset = BitOffset >> 3;
313     Code = (unsigned) rasterPtr[ByteOffset]
314            + (((unsigned) rasterPtr[ByteOffset + 1]) << 8);
315
316     if (CodeSize >= 8)
317       Code += ((unsigned) rasterPtr[ByteOffset + 2]) << 16;
318
319     Code >>= (BitOffset & 0x7);
320     BitOffset += CodeSize;
321     Code &=  ReadMask;
322   } // while (Code != EOFCode)
323
324   // Free allocated memory
325   STGMGR_FREE (rasterPtr, nFileSize);
326   STGMGR_FREE (OutCode, 1025 * sizeof (unsigned int));
327   STGMGR_FREE (Prefix,  4096 * sizeof (unsigned int));
328   STGMGR_FREE (Suffix,  4096 * sizeof (unsigned int));
329 #ifdef TRACE
330   timer.Stop ();
331   timer.Show (cout);
332   cout << "AlienImage_GIFAlienData::Read () finished\n" << endl << flush;
333 #endif
334   return Standard_True;
335
336 _ExitReadError:
337 //  cout << "GIFAlienData::Read() : Read file error." << endl << flush;
338   if (pFileBuffer)  STGMGR_FREE (pFileBuffer, nFileSize);
339   if (OutCode)      STGMGR_FREE (OutCode, 1025 * sizeof (unsigned int));
340   if (Prefix)       STGMGR_FREE (Prefix,  4096 * sizeof (unsigned int));
341   if (Suffix)       STGMGR_FREE (Suffix,  4096 * sizeof (unsigned int));
342   if (myRedColors) {
343     STGMGR_FREE (myRedColors, COLORS_SIZE);
344     myRedColors = NULL;
345   }
346   if (myGreenColors) {
347     STGMGR_FREE (myGreenColors, COLORS_SIZE);
348     myGreenColors = NULL;
349   }
350   if (myBlueColors) {
351     STGMGR_FREE (myBlueColors, COLORS_SIZE);
352     myBlueColors = NULL;
353   }
354   if (myData) {
355     STGMGR_FREE (myData, myWidth*myHeight);
356     myData = NULL;
357     myWidth = myHeight = 0;
358   }
359
360   return Standard_False;
361 }
362
363 //================================================================
364 Standard_Boolean AlienImage_GIFAlienData::Write (OSD_File& file) const
365 {
366   SCREEN_DESCR sd;
367   IMAGE_DESCR  id;
368   BYTE image_sep = 0x2C; // gif colormap delimiter
369   WORD wZero = 0x00;
370   BYTE colors256 [256][3];
371   BYTE bEnd  = 0x3B;
372   int i;
373
374 #ifdef TRACE
375   OSD_Timer timer;
376   cout << "AlienImage_GIFAlienData::Write () starts" << endl << flush;
377   timer.Start ();
378 #endif
379   // Check if image is loaded
380   if (myData == NULL || myRedColors == NULL ||
381       myGreenColors == NULL || myBlueColors == NULL ||
382       myWidth == 0 || myHeight == 0)
383     goto _ExitWriteError;
384
385   // Build file header
386   memcpy (sd.gifID, "GIF87a", 6);
387   sd.scrnWidth  = SWAP_WORD ((WORD) myWidth );
388   sd.scrnHeight = SWAP_WORD ((WORD) myHeight);
389   sd.scrnFlag   = 0x80 | (  ( 7/*[=depth-1]*/ << 4 ) & 0x70  ) | 0x07;
390   id.imgX       = 0;
391   id.imgY       = 0;
392   id.imgWidth   = SWAP_WORD ((WORD) myWidth );
393   id.imgHeight  = SWAP_WORD ((WORD) myHeight);
394 //          imgFlag
395 //        +-+-+-+-+-+-----+       M=0 - Use global color map, ignore 'pixel'
396 //        |M|I|0|0|0|pixel| 10    M=1 - Local color map follows, use 'pixel'
397 //        +-+-+-+-+-+-----+       I=0 - Image formatted in Sequential order
398 //                                I=1 - Image formatted in Interlaced order
399 //                                pixel+1 - # bits per pixel for this image
400   id.imgFlag   = 0x07; // Global color map, Sequential order, 8 bits per pixel
401
402   for (i = 0; i < 256; i++) {
403     colors256[i] [0/*R*/] = RED   [i];
404     colors256[i] [1/*G*/] = GREEN [i];
405     colors256[i] [2/*B*/] = BLUE  [i];
406   }
407
408   // Write off the buffers
409   file.Write (&sd, 11); // Screen descriptor
410   if (file.Failed())
411     goto _ExitWriteError;
412
413   file.Write (&wZero, 2); // Zero word
414   if (file.Failed())
415     goto _ExitWriteError;
416
417   file.Write (colors256, 256*3); // Colormap
418   if (file.Failed())
419     goto _ExitWriteError;
420
421   file.Write (&image_sep, 1); // Separator
422   if (file.Failed())
423     goto _ExitWriteError;
424
425   file.Write (&id, 9); // Image descriptor
426   if (file.Failed())
427     goto _ExitWriteError;
428
429   // Write off the image data
430   if (!_lzw_encode (file, (PBYTE) myData, myWidth, myHeight, myWidth))
431     goto _ExitWriteError;
432
433   file.Write (&bEnd, 1); // End of image
434   if (file.Failed())
435     goto _ExitWriteError;
436
437   // Return SUCCESS status if there were no errors.
438 #ifdef TRACE
439   timer.Stop ();
440   timer.Show (cout);
441   cout << "AlienImage_GIFAlienData::Write () finished\n" << endl << flush;
442 #endif
443   return Standard_True;
444
445   // Exit on error
446 _ExitWriteError:
447   file.Seek (0, OSD_FromBeginning);
448   return Standard_False;
449 }
450
451 //================================================================
452 Handle_Image_Image AlienImage_GIFAlienData::ToImage () const
453 {
454 #ifdef TRACE
455   OSD_Timer timer;
456   cout << "AlienImage_GIFAlienData::ToImage () starts" << endl << flush;
457   timer.Start ();
458 #endif
459   Standard_Integer i, x, y, LowX, LowY;
460   Standard_Real r, g, b;
461   Aspect_ColorMapEntry entry;
462   Aspect_IndexPixel index;
463   Quantity_Color color;
464
465   // Build colormap
466   Handle(Aspect_GenericColorMap) aColorMap =
467     new Aspect_GenericColorMap ();
468   for (i = 0; i < 256; i++) {
469     r = ((float)RED   [i] / 255.);
470     g = ((float)GREEN [i] / 255.);
471     b = ((float)BLUE  [i] / 255.);
472     color.SetValues (r, g, b, Quantity_TOC_RGB);
473     entry.SetValue  (i, color);
474     aColorMap -> AddEntry (entry);
475   }
476
477   // Fill image data
478   Handle(Image_Image) theImage =
479     new Image_PseudoColorImage (0, 0, myWidth, myHeight, aColorMap);
480   LowX = theImage -> LowerX ();
481   LowY = theImage -> LowerY ();
482   for (y = 0; y < myHeight; y++) {
483     for (x = 0; x < myWidth; x++) {
484       index.SetValue (PIXEL[y*myWidth + x]);
485       theImage -> SetPixel (LowX + x, LowY + y, index);
486     }
487   }
488 #ifdef TRACE
489   timer.Stop ();
490   timer.Show (cout);
491   cout << "AlienImage_GIFAlienData::ToImage () finished\n" << endl << flush;
492 #endif
493   return theImage;
494 }
495
496 //================================================================
497 void AlienImage_GIFAlienData::FromImage (const Handle_Image_Image& anImage)
498 {
499   if (anImage -> Type() == Image_TOI_PseudoColorImage) {
500     // Build from PseudoColorImage
501     Handle(Image_PseudoColorImage) aPImage =
502       Handle(Image_PseudoColorImage)::DownCast(anImage);
503     FromPseudoColorImage (aPImage);
504   } else if (anImage -> Type() == Image_TOI_ColorImage) {
505     // Build from ColorImage
506     Handle(Image_ColorImage) aCImage =
507       Handle(Image_ColorImage)::DownCast(anImage);
508     FromColorImage (aCImage);
509   } else {
510     // Unknown type of image
511     Standard_TypeMismatch_Raise_if (Standard_True,
512       "Attempt to convert a unknown Image_Image type to a GIFAlienData");
513   }
514 }
515
516 //================================================================
517 void AlienImage_GIFAlienData::FromPseudoColorImage (
518                 const Handle(Image_PseudoColorImage)& anImage)
519 {
520   int width  = anImage -> Width  ();
521   int height = anImage -> Height ();
522   unsigned short x, y, i;
523   Standard_Real r, g, b;
524   Aspect_ColorMapEntry entry;
525   Aspect_IndexPixel index;
526   Quantity_Color color;
527   Standard_Integer LowX = anImage -> LowerX();
528   Standard_Integer LowY = anImage -> LowerY();
529   BYTE ei;
530
531 #ifdef TRACE
532   OSD_Timer timer;
533   cout << "AlienImage_GIFAlienData::FromPseudoColorImage () starts" << endl << flush;
534   timer.Start ();
535 #endif
536   if (width*height > 0) {
537     Handle(Aspect_ColorMap) aColorMap = anImage -> ColorMap ();
538     // Clear old values if any
539     Clear ();
540
541     myRedColors   = STGMGR_ALLOC (COLORS_SIZE);
542     myGreenColors = STGMGR_ALLOC (COLORS_SIZE);
543     myBlueColors  = STGMGR_ALLOC (COLORS_SIZE);
544     ZERO_COLORS ();
545
546     // Build colors from colormap
547     for (i = 1; i <= aColorMap -> Size (); i++) {
548       entry = aColorMap -> Entry (i);
549       ei = entry.Index ();
550       color = entry.Color ();
551       color.Values (r, g, b, Quantity_TOC_RGB);
552       RED  [ei] = (BYTE)(r*255.);
553       GREEN[ei] = (BYTE)(g*255.);
554       BLUE [ei] = (BYTE)(b*255.);
555     }
556
557     // Build imagedata from Image_PseudoColorImage
558     myWidth = width;
559     myHeight = height;
560     myData = STGMGR_ALLOC (myWidth*myHeight);
561     for (y = 0; y < myHeight; y++) {
562       for (x = 0; x < myWidth; x++) {
563         index = anImage -> Pixel (LowX + x, LowY + y);
564         PIXEL[y*myWidth + x] = (BYTE)index.Value ();
565       }
566     }
567   }
568 #ifdef TRACE
569   timer.Stop ();
570   timer.Show (cout);
571   cout << "AlienImage_GIFAlienData::FromPseudoColorImage () finished\n" << endl << flush;
572 #endif
573 }
574
575 //================================================================
576 void AlienImage_GIFAlienData::FromColorImage (
577                 const Handle(Image_ColorImage)& anImage)
578 {
579 #ifdef TRACE
580   OSD_Timer timer;
581   cout << "AlienImage_GIFAlienData::FromColorImage () starts" << endl << flush;
582   timer.Start ();
583 #endif // TRACE
584
585   int width  = anImage -> Width  ();
586   int height = anImage -> Height ();
587   int i, x, y, LowX = anImage -> LowerX(), LowY = anImage -> LowerY();
588   Quantity_Color color;
589   Standard_Real r, g, b;
590
591   if (width*height > 0) {
592     Aspect_ColorMapEntry entry;
593     // Clear old values if any
594     Clear ();
595     myWidth  = width;
596     myHeight = height;
597     LPRGBQUAD pColors = (LPRGBQUAD) STGMGR_ALLOC (256*sizeof(RGBQUAD));
598     PBYTE     pBits24 = (PBYTE)     STGMGR_ALLOC (width*height*3);
599     memset (pColors, 0, 256*sizeof(RGBQUAD));
600
601     myData        = STGMGR_ALLOC (width*height);
602     myRedColors   = STGMGR_ALLOC (COLORS_SIZE);
603     myGreenColors = STGMGR_ALLOC (COLORS_SIZE);
604     myBlueColors  = STGMGR_ALLOC (COLORS_SIZE);
605
606     for (y = 0, i = 0; y < myHeight; y++) {
607       for (x = 0; x < myWidth; x++) {
608         color = anImage -> PixelColor (LowX + x, LowY + y);
609         color.Values (r, g, b, Quantity_TOC_RGB);
610         pBits24 [i + 0] = (BYTE)(b*255.);
611         pBits24 [i + 1] = (BYTE)(g*255.);
612         pBits24 [i + 2] = (BYTE)(r*255.);
613         i += 3;
614       }
615     }
616
617     if (_convert24to8 (pColors, pBits24, (PBYTE)myData, myWidth, myHeight)) {
618       Handle(Aspect_GenericColorMap) aColorMap = new Aspect_GenericColorMap ();
619       for (i = 0; i < 256; i++) {
620         r = ((float)pColors[i].rgbRed   / 255.);
621         g = ((float)pColors[i].rgbGreen / 255.);
622         b = ((float)pColors[i].rgbBlue  / 255.);
623         color.SetValues (r, g, b, Quantity_TOC_RGB);
624         entry.SetValue (i, color);
625         aColorMap -> AddEntry (entry);
626         RED  [i] = pColors[i].rgbRed;
627         GREEN[i] = pColors[i].rgbGreen;
628         BLUE [i] = pColors[i].rgbBlue;
629       }
630     } else {
631       Image_Convertor aConvertor;
632       aConvertor.SetDitheringMethod (Image_DM_ErrorDiffusion);
633       Handle(Aspect_ColorMap) aColorMap  = anImage -> ChooseColorMap (256);
634       Handle(Image_PseudoColorImage) aPImage =
635         aConvertor.Convert (anImage, aColorMap);
636       FromPseudoColorImage (aPImage);
637     }
638
639     STGMGR_FREE (pColors, 256*sizeof(RGBQUAD));
640     STGMGR_FREE (pBits24, width*height*3);
641   }
642
643 #ifdef TRACE
644   timer.Stop ();
645   timer.Show (cout);
646   cout << "AlienImage_GIFAlienData::FromColorImage () finished\n" << endl << flush;
647 #endif // TRACE
648 }
649