b311480e |
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 | |
7fd59977 |
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. |
7fd59977 |
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 | |