1 // ----------------------------------------------------------------------------
2 // MODULE : BufferDesc
3 // LANGUAGE : C++
4 // CREATOR : Philippe BOSSUT
5 // CREAT. DATE : Monday, March 25, 1996
6 // DESCRIPTION :
7 // COMMENTS :
8 // SCCSID : @(#)buffdesc.cpp 1.10 12:46:27 01 Jul 1997
9 // ----------------------------------------------------------------------------
10 // Copyright (c) 1999 Digital Imaging Group, Inc.
11 // For conditions of distribution and use, see copyright notice
12 // in Flashpix.h
13 // ----------------------------------------------------------------------------
14
15 #ifndef BufferDesc_h
16 #include "buffdesc.h"
17 #endif
18 #include "thmbnail.h"
19 // ----------------------------------------------------------------------------
20
21 // Includes
22 // --------
23
24 #include <stdlib.h>
25 #include <math.h>
26 #ifdef _WINDOWS
27 #include <windows.h>
28 #endif
29
30 #ifndef Debug_h
31 #include "debug.h"
32 #endif
33 #ifndef ColorTwist_h
34 #include "coltwist.h"
35 #endif
36 #ifndef Compresseur32Vers24_h
37 #include "cp32to24.h"
38 #endif
39 #ifndef OLECore_h
40 #include "olecore.h"
41 #endif
42 #ifndef FlashPixUtils_h
43 #include "fpxutils.h"
44 #endif
45 #ifndef SwapBytes_h
46 #include "swapbyte.h"
47 #endif
48
49 // Constants
50 // ---------
51
52 // Variables
53 // ---------
54
55 // ----------------------------------------------------------------------------
56 // Internal Functions
57 // ----------------------------------------------------------------------------
58
59 // Init alpha bytes to 255 (opaque) for each pixel starting at buffer
InitByteTo255(unsigned char * buffer,long size)60 static void InitByteTo255 (unsigned char* buffer, long size)
61 {
62 while (size--) {
63 *buffer = 255;
64 buffer += 4;
65 }
66 }
67
68 #if 0
69 // Init alpha bytes to 0 (transparent) for each pixel starting at buffer
70 static void InitByteTo0 (unsigned char* buffer, long size)
71 {
72 while (size--) {
73 *buffer = 0;
74 buffer += 4;
75 }
76 }
77 #endif
78
79 //Updated the procedure to work on both architedture --**IM-05/16/97
80 // Rotate on the left by 8 bits on each 32 bits long and wrap the last one
Shift8BitsLeft(unsigned char * buffer,long size)81 static void Shift8BitsLeft (unsigned char* buffer, long size)
82 {
83 unsigned char tmp;
84 while (size--) {
85 tmp = buffer[0];
86 buffer[0] = buffer[1];
87 buffer[1] = buffer[2];
88 buffer[2] = buffer[3];
89 buffer[3] = tmp;
90 buffer += 4;
91 }
92 }
93
94 // Rotate on the right by 8 bits on each 32 bits long and wrap the last one
Shift8BitsRight(unsigned char * buffer,long size)95 static void Shift8BitsRight (unsigned char* buffer, long size)
96 {
97 unsigned char tmp;
98 while (size--) {
99 tmp = buffer[3];
100 buffer[3] = buffer[2];
101 buffer[2] = buffer[1];
102 buffer[1] = buffer[0];
103 buffer[0] = tmp;
104 buffer += 4;
105 }
106 }
107
108 // Copy a byte and erase its ancient address be 2 bytes on the right (don't move the rest)
MoveByteRightBy2(unsigned char * buffer,long size)109 static void MoveByteRightBy2(unsigned char* buffer, long size)
110 {
111 register unsigned char* next;
112 next = buffer + 2;
113 while (size--) {
114 *next = *buffer;
115 *buffer = 0;
116 buffer += 4;
117 next += 4;
118 }
119 }
120
121 // Copy a byte and erase its ancient address be 2 bytes on the left (don't move the rest)
MoveByteLeftBy2(unsigned char * buffer,long size)122 static void MoveByteLeftBy2(unsigned char* buffer, long size)
123 {
124 register unsigned char* next;
125 next = buffer - 2;
126 while (size--) {
127 *next = *buffer;
128 *buffer = 0;
129 buffer += 4;
130 next += 4;
131 }
132 }
133
134
135 // Apply the transformations :
136 // ---------------------------
137 // CAUTION: For the moment, we make the hypothesis that T44 is equal to 1 and that a
138 // pixel is 4 bytes wide.
139
ConvertRGBtoYCC(unsigned char * buffer,long size)140 void ConvertRGBtoYCC(unsigned char* buffer, long size)
141 {
142 PColorTwist tRGBTorgb(RGB8_to_rgb); // 8-bit NIF RGB to normalized PhotoRGB
143 PColorTwist trgbToycc(rgb_to_ycc); // Normalized PhotoRGB to normalized PhotoYCC
144 PColorTwist tyccToYCC(ycc_to_YCC8); // Normalized PhotoYCC to 8-bit PhotoYCC
145
146 PColorTwist tRGBtoYCC;
147 tRGBtoYCC = trgbToycc * tRGBTorgb;
148 tRGBtoYCC = tyccToYCC * tRGBtoYCC;
149
150 // PTCH_302 Added the following call to apply a shaping LUT to the output of
151 // the matrix transform.
152 tRGBtoYCC.ApplyRGBtoYCCLut(buffer,size);
153 }
154
ConvertYCCtoRGB(unsigned char * buffer,long size,Boolean useAlpha)155 void ConvertYCCtoRGB(unsigned char* buffer, long size, Boolean useAlpha)
156 {
157 PColorTwist tYCCtoycc(YCC8_to_ycc); // 8-bit PhotoYCC to normalized PhotoYCC
158 PColorTwist tyccTorgb(ycc_to_rgb); // Normalized PhotoYCC to normalized PhotoRGB
159 PColorTwist trgbToRGB(rgb_to_RGB8); // Normalized PhotoRGB to 8-bit NIF RGB
160
161 PColorTwist tYCCtoRGB;
162 tYCCtoRGB = tyccTorgb * tYCCtoycc;
163 tYCCtoRGB = trgbToRGB * tYCCtoRGB;
164
165 tYCCtoRGB.UsePortfolioLut();
166 if(useAlpha)
167 tYCCtoRGB.UseAlphaChannel();
168 tYCCtoRGB.ApplyToBuffer(buffer,size);
169 }
170
171
172 // PTCH_302 ConvertYCCtoMonochrome() was completely rewritten
ConvertYCCtoMonochrome(unsigned char * buffer,long size)173 static void ConvertYCCtoMonochrome(unsigned char* buffer, long size)
174 {
175 PColorTwist tRGBtorgb(RGB8_to_rgb);
176 PColorTwist trgbTomono(rgb_to_mono);
177 PColorTwist tmonoToMONO(rgb_to_RGB8);
178
179 ConvertYCCtoRGB(buffer, size, FALSE);
180
181 PColorTwist tRGBtoMONO;
182 tRGBtoMONO = trgbTomono * tRGBtorgb;
183 tRGBtoMONO = tmonoToMONO * tRGBtoMONO;
184
185 tRGBtoMONO.ApplyToBuffer(buffer,size);
186
187 /* pre-PTCH_302 code
188 while (size--) {
189 *(buffer+2) = *buffer;
190 *buffer = 0;
191 *(buffer+1) = 0;
192 buffer += 4;
193 }
194 */
195 }
196
197 // PTCH_302 ConvertRGBtoMonochrome() was completely rewritten
ConvertRGBtoMonochrome(unsigned char * buffer,long size)198 static void ConvertRGBtoMonochrome(unsigned char* buffer, long size)
199 {
200 PColorTwist tRGBtorgb(RGB8_to_rgb);
201 PColorTwist trgbTomono(rgb_to_mono);
202 PColorTwist tmonoToMONO(rgb_to_RGB8);
203
204 PColorTwist tRGBtoMONO;
205 tRGBtoMONO = trgbTomono * tRGBtorgb;
206 tRGBtoMONO = tmonoToMONO * tRGBtoMONO;
207
208 tRGBtoMONO.ApplyToBuffer(buffer,size);
209
210 /* pre-PTCH_302 code
211 ConvertRGBtoYCC(buffer,size);
212 ConvertYCCtoMonochrome(buffer,size);
213 */
214 }
215
ConvertMonochrometoRGB(unsigned char * buffer,long size)216 static void ConvertMonochrometoRGB(unsigned char* buffer, long size)
217 {
218 while (size--) {
219 *buffer = *(buffer+2);
220 *(buffer+1) = *(buffer+2);
221 buffer += 4;
222 }
223 }
224
225 // PTCH_302 ConvertMonochrometoYCC() was completely rewritten
ConvertMonochrometoYCC(unsigned char * buffer,long size)226 static void ConvertMonochrometoYCC(unsigned char* buffer, long size)
227 {
228 ConvertMonochrometoRGB(buffer, size);
229 ConvertRGBtoYCC(buffer, size);
230 }
231
232
233
234 // ----------------------------------------------------------------------------
235 // Member Functions
236 // ----------------------------------------------------------------------------
InitImageDesc(FPXBaselineColorSpace colorSpace)237 void FPXBufferDesc::InitImageDesc(FPXBaselineColorSpace colorSpace)
238 {
239 colorSpaceType = colorSpace;
240
241 // Allocate an image descriptor
242 FPXdesc = new FPXImageDesc;
243 if (FPXdesc==NULL) {
244 return;
245 }
246 localDesc = true;
247
248 // Set the things common to all Baseline descriptors
249 FPXdesc->components[0].myColorType.myDataType = DATA_TYPE_UNSIGNED_BYTE;
250 FPXdesc->components[1].myColorType.myDataType = DATA_TYPE_UNSIGNED_BYTE;
251 FPXdesc->components[2].myColorType.myDataType = DATA_TYPE_UNSIGNED_BYTE;
252 FPXdesc->components[3].myColorType.myDataType = DATA_TYPE_UNSIGNED_BYTE;
253
254 FPXdesc->components[0].horzSubSampFactor = 1;
255 FPXdesc->components[1].horzSubSampFactor = 1;
256 FPXdesc->components[2].horzSubSampFactor = 1;
257 FPXdesc->components[3].horzSubSampFactor = 1;
258
259 FPXdesc->components[0].vertSubSampFactor = 1;
260 FPXdesc->components[1].vertSubSampFactor = 1;
261 FPXdesc->components[2].vertSubSampFactor = 1;
262 FPXdesc->components[3].vertSubSampFactor = 1;
263
264 FPXdesc->components[0].columnStride = 4;
265 FPXdesc->components[1].columnStride = 4;
266 FPXdesc->components[2].columnStride = 4;
267 FPXdesc->components[3].columnStride = 4;
268
269 FPXdesc->components[0].lineStride = width * 4;
270 FPXdesc->components[1].lineStride = width * 4;
271 FPXdesc->components[2].lineStride = width * 4;
272 FPXdesc->components[3].lineStride = width * 4;
273
274 // Set the specific part according to the color space type
275 switch (colorSpaceType) {
276 case SPACE_32_BITS_RGB:
277 FPXdesc->numberOfComponents = 3;
278 FPXdesc->components[0].myColorType.myColor = NIFRGB_R;
279 FPXdesc->components[1].myColorType.myColor = NIFRGB_G;
280 FPXdesc->components[2].myColorType.myColor = NIFRGB_B;
281 FPXdesc->components[0].theData = (unsigned char*)(buffer) + 1;
282 FPXdesc->components[1].theData = (unsigned char*)(buffer) + 2;
283 FPXdesc->components[2].theData = (unsigned char*)(buffer) + 3;
284 break;
285 case SPACE_32_BITS_ARGB:
286 FPXdesc->numberOfComponents = 4;
287 FPXdesc->components[0].myColorType.myColor = ALPHA;
288 FPXdesc->components[1].myColorType.myColor = NIFRGB_R;
289 FPXdesc->components[2].myColorType.myColor = NIFRGB_G;
290 FPXdesc->components[3].myColorType.myColor = NIFRGB_B;
291 FPXdesc->components[0].theData = (unsigned char*)(buffer);
292 FPXdesc->components[1].theData = (unsigned char*)(buffer) + 1;
293 FPXdesc->components[2].theData = (unsigned char*)(buffer) + 2;
294 FPXdesc->components[3].theData = (unsigned char*)(buffer) + 3;
295 break;
296 case SPACE_32_BITS_RGBA:
297 FPXdesc->numberOfComponents = 4;
298 FPXdesc->components[0].myColorType.myColor = NIFRGB_R;
299 FPXdesc->components[1].myColorType.myColor = NIFRGB_G;
300 FPXdesc->components[2].myColorType.myColor = NIFRGB_B;
301 FPXdesc->components[3].myColorType.myColor = ALPHA;
302 FPXdesc->components[0].theData = (unsigned char*)(buffer);
303 FPXdesc->components[1].theData = (unsigned char*)(buffer) + 1;
304 FPXdesc->components[2].theData = (unsigned char*)(buffer) + 2;
305 FPXdesc->components[3].theData = (unsigned char*)(buffer) + 3;
306 break;
307 case SPACE_32_BITS_YCC:
308 FPXdesc->numberOfComponents = 3;
309 FPXdesc->components[0].myColorType.myColor = PHOTO_YCC_Y;
310 FPXdesc->components[1].myColorType.myColor = PHOTO_YCC_C1;
311 FPXdesc->components[2].myColorType.myColor = PHOTO_YCC_C2;
312 FPXdesc->components[0].theData = (unsigned char*)(buffer) + 1;
313 FPXdesc->components[1].theData = (unsigned char*)(buffer) + 2;
314 FPXdesc->components[2].theData = (unsigned char*)(buffer) + 3;
315 break;
316 case SPACE_32_BITS_AYCC:
317 FPXdesc->numberOfComponents = 4;
318 FPXdesc->components[0].myColorType.myColor = ALPHA;
319 FPXdesc->components[1].myColorType.myColor = PHOTO_YCC_Y;
320 FPXdesc->components[2].myColorType.myColor = PHOTO_YCC_C1;
321 FPXdesc->components[3].myColorType.myColor = PHOTO_YCC_C2;
322 FPXdesc->components[0].theData = (unsigned char*)(buffer);
323 FPXdesc->components[1].theData = (unsigned char*)(buffer) + 1;
324 FPXdesc->components[2].theData = (unsigned char*)(buffer) + 2;
325 FPXdesc->components[3].theData = (unsigned char*)(buffer) + 3;
326 break;
327 case SPACE_32_BITS_YCCA:
328 FPXdesc->numberOfComponents = 4;
329 FPXdesc->components[0].myColorType.myColor = PHOTO_YCC_Y;
330 FPXdesc->components[1].myColorType.myColor = PHOTO_YCC_C1;
331 FPXdesc->components[2].myColorType.myColor = PHOTO_YCC_C2;
332 FPXdesc->components[3].myColorType.myColor = ALPHA;
333 FPXdesc->components[0].theData = (unsigned char*)(buffer);
334 FPXdesc->components[1].theData = (unsigned char*)(buffer) + 1;
335 FPXdesc->components[2].theData = (unsigned char*)(buffer) + 2;
336 FPXdesc->components[3].theData = (unsigned char*)(buffer) + 3;
337 break;
338 case SPACE_32_BITS_M:
339 FPXdesc->numberOfComponents = 1;
340 FPXdesc->components[0].myColorType.myColor = MONOCHROME;
341 FPXdesc->components[0].theData = (unsigned char*)(buffer) + 3;
342 break;
343 case SPACE_32_BITS_AM:
344 FPXdesc->numberOfComponents = 2;
345 FPXdesc->components[0].myColorType.myColor = ALPHA;
346 FPXdesc->components[1].myColorType.myColor = MONOCHROME;
347 FPXdesc->components[0].theData = (unsigned char*)(buffer) + 2;
348 FPXdesc->components[1].theData = (unsigned char*)(buffer) + 3;
349 break;
350 case SPACE_32_BITS_MA:
351 FPXdesc->numberOfComponents = 2;
352 FPXdesc->components[0].myColorType.myColor = MONOCHROME;
353 FPXdesc->components[1].myColorType.myColor = ALPHA;
354 FPXdesc->components[0].theData = (unsigned char*)(buffer) + 2;
355 FPXdesc->components[1].theData = (unsigned char*)(buffer) + 3;
356 break;
357 case SPACE_32_BITS_O:
358 FPXdesc->numberOfComponents = 1;
359 FPXdesc->components[0].myColorType.myColor = ALPHA;
360 FPXdesc->components[0].theData = (unsigned char*)(buffer) + 3;
361 break;
362 default: // Not authorized in Baseline
363 assert(false);
364 break;
365 }
366 }
367
368
FPXBufferDesc(unsigned char * theBuffer,long theWidth,long theHeight,FPXBaselineColorSpace colorSpace)369 FPXBufferDesc::FPXBufferDesc (unsigned char* theBuffer, long theWidth, long theHeight, FPXBaselineColorSpace colorSpace)
370 {
371 // Set the private datas
372 width = theWidth;
373 height = theHeight;
374
375 buffer = theBuffer;
376 localBuffer = false;
377 useInternalBuffer = true; // PTCH_102
378
379 // Init the color space description
380 InitImageDesc(colorSpace);
381 }
382
FPXBufferDesc(long theColor,long theWidth,long theHeight,FPXBaselineColorSpace colorSpace)383 FPXBufferDesc::FPXBufferDesc (long theColor, long theWidth, long theHeight, FPXBaselineColorSpace colorSpace)
384 {
385 // Set the private datas
386 width = theWidth;
387 height = theHeight;
388
389 localBuffer = true;
390 buffer = new unsigned char [width * height * 4];
391 if (buffer==NULL) {
392 return;
393 }
394 useInternalBuffer = false; // PTCH_102
395
396 // Init the color space description
397 InitImageDesc(colorSpace);
398
399 // Fill the buffer with the background color: copy 32 bits at once
400 int32_t *pt = (int32_t*)(buffer);
401 for (int i = 0; i < height; ++i)
402 for (int j = 0; j < width; ++j, ++pt)
403 *pt = theColor;
404 }
405
FPXBufferDesc(FPXImageDesc * desc,long theWidth,long theHeight,unsigned char * internalBuffer)406 FPXBufferDesc::FPXBufferDesc (FPXImageDesc* desc, long theWidth, long theHeight,
407 unsigned char *internalBuffer)
408 {
409 width = theWidth;
410 height = theHeight;
411 FPXdesc = desc;
412 localDesc = false;
413
414 FPXColorspace colorSpace;
415 ExtractFPXColorSpaceFromFPXImageDesc(*desc, &colorSpace);
416 colorSpaceType = AnalyseFPXColorSpace(colorSpace);
417 useInternalBuffer = false;
418
419 if (IsASupportedDescriptor(*desc,width)) {
420 localBuffer = false;
421 buffer = FPXdesc->components[0].theData - (4 - FPXdesc->numberOfComponents);
422 }
423 else if (internalBuffer != NULL) {
424 localBuffer = true;
425 useInternalBuffer = true;
426 buffer = internalBuffer;
427 }
428 else {
429 localBuffer = true;
430 buffer = new unsigned char [width * height * 4];
431 if (buffer==NULL) {
432 return;
433 }
434 }
435 }
436
~FPXBufferDesc()437 FPXBufferDesc::~FPXBufferDesc ()
438 {
439 if (localDesc)
440 delete FPXdesc;
441
442 if (localBuffer && !useInternalBuffer)
443 {
444 delete [] buffer;
445 buffer = NULL;
446 }
447 }
448
UpdateBuffer()449 void FPXBufferDesc::UpdateBuffer ()
450 {
451 // If the pixels are stored in a local buffer, they have to be transfered from the
452 // image descriptor to the buffer
453 if (localBuffer) {
454 register long i, j;
455
456 register long incLine0 = FPXdesc->components[0].lineStride;
457 register long incLine1 = FPXdesc->components[1].lineStride;
458 register long incLine2 = FPXdesc->components[2].lineStride;
459 register long incLine3 = FPXdesc->components[3].lineStride;
460 register long incCol0 = FPXdesc->components[0].columnStride;
461 register long incCol1 = FPXdesc->components[1].columnStride;
462 register long incCol2 = FPXdesc->components[2].columnStride;
463 register long incCol3 = FPXdesc->components[3].columnStride;
464
465 unsigned char* pt0;
466 unsigned char* pt1;
467 unsigned char* pt2;
468 unsigned char* pt3;
469
470 unsigned char* pix;
471 long nbChan = FPXdesc->numberOfComponents;
472 register long incCol;
473
474 if (nbChan == 1) {
475 pix = buffer + 3;
476 incCol = 4;
477 for (j = 0; j < height; j++) {
478 pt0 = (unsigned char*)(FPXdesc->components[0].theData) + j*incLine0;
479 for (i = 0; i < width; i++, pix += incCol) {
480 *pix = *pt0;
481 pt0 += incCol0;
482 }
483 }
484 } else if (nbChan == 2) {
485 pix = buffer + 2;
486 incCol = 3;
487 for (j = 0; j < height; j++) {
488 pt0 = (unsigned char*)(FPXdesc->components[0].theData) + j*incLine0;
489 pt1 = (unsigned char*)(FPXdesc->components[1].theData) + j*incLine1;
490 for (i = 0; i < width; i++, pix += incCol) {
491 *pix++ = *pt0; *pix = *pt1;
492 pt0 += incCol0; pt1 += incCol1;
493 }
494 }
495 } else if (nbChan == 3) {
496 pix = buffer + 1;
497 incCol = 2;
498 for (j = 0; j < height; j++) {
499 pt0 = (unsigned char*)(FPXdesc->components[0].theData) + j*incLine0;
500 pt1 = (unsigned char*)(FPXdesc->components[1].theData) + j*incLine1;
501 pt2 = (unsigned char*)(FPXdesc->components[2].theData) + j*incLine2;
502 for (i = 0; i < width; i++, pix += incCol) {
503 *pix++ = *pt0; *pix++ = *pt1; *pix = *pt2;
504 pt0 += incCol0; pt1 += incCol1; pt2 += incCol2;
505 }
506 }
507 } else if (nbChan == 4) {
508 pix = buffer;
509 for (j = 0; j < height; j++) {
510 pt0 = (unsigned char*)(FPXdesc->components[0].theData) + j*incLine0;
511 pt1 = (unsigned char*)(FPXdesc->components[1].theData) + j*incLine1;
512 pt2 = (unsigned char*)(FPXdesc->components[2].theData) + j*incLine2;
513 pt3 = (unsigned char*)(FPXdesc->components[3].theData) + j*incLine3;
514 for (i = 0; i < width; i++) {
515 *pix++ = *pt0; *pix++ = *pt1; *pix++ = *pt2; *pix++ = *pt3;
516 pt0 += incCol0; pt1 += incCol1; pt2 += incCol2; pt3 += incCol3;
517 }
518 }
519 }
520
521 }
522 }
523
UpdateDescriptor()524 void FPXBufferDesc::UpdateDescriptor ()
525 {
526 // If the pixels are stored in a local buffer, they have to be transfered to the
527 // image descriptor
528 if (localBuffer) {
529 register long i, j;
530
531 register long incLine0 = FPXdesc->components[0].lineStride;
532 register long incLine1 = FPXdesc->components[1].lineStride;
533 register long incLine2 = FPXdesc->components[2].lineStride;
534 register long incLine3 = FPXdesc->components[3].lineStride;
535 register long incCol0 = FPXdesc->components[0].columnStride;
536 register long incCol1 = FPXdesc->components[1].columnStride;
537 register long incCol2 = FPXdesc->components[2].columnStride;
538 register long incCol3 = FPXdesc->components[3].columnStride;
539
540 unsigned char* pt0;
541 unsigned char* pt1;
542 unsigned char* pt2;
543 unsigned char* pt3;
544
545 unsigned char* pix;
546 long nbChan = FPXdesc->numberOfComponents;
547 register long incCol;
548
549 if (nbChan == 1) {
550 pix = buffer + 3;
551 incCol = 4;
552 for (j = 0; j < height; j++) {
553 pt0 = (unsigned char*)(FPXdesc->components[0].theData) + j*incLine0;
554 for (i = 0; i < width; i++, pix += incCol) {
555 *pt0 = *pix;
556 pt0 += incCol0;
557 }
558 }
559 } else if (nbChan == 2) {
560 pix = buffer + 2;
561 incCol = 3;
562 for (j = 0; j < height; j++) {
563 pt0 = (unsigned char*)(FPXdesc->components[0].theData) + j*incLine0;
564 pt1 = (unsigned char*)(FPXdesc->components[1].theData) + j*incLine1;
565 for (i = 0; i < width; i++, pix += incCol) {
566 *pt0 = *pix++; *pt1 = *pix;
567 pt0 += incCol0; pt1 += incCol1;
568 }
569 }
570 } else if (nbChan == 3) {
571 pix = buffer + 1;
572 incCol = 2;
573 for (j = 0; j < height; j++) {
574 pt0 = (unsigned char*)(FPXdesc->components[0].theData) + j*incLine0;
575 pt1 = (unsigned char*)(FPXdesc->components[1].theData) + j*incLine1;
576 pt2 = (unsigned char*)(FPXdesc->components[2].theData) + j*incLine2;
577 for (i = 0; i < width; i++, pix += incCol) {
578 *pt0 = *pix++; *pt1 = *pix++; *pt2 = *pix;
579 pt0 += incCol0; pt1 += incCol1; pt2 += incCol2;
580 }
581 }
582 } else if (nbChan == 4) {
583 pix = buffer;
584 for (j = 0; j < height; j++) {
585 pt0 = (unsigned char*)(FPXdesc->components[0].theData) + j*incLine0;
586 pt1 = (unsigned char*)(FPXdesc->components[1].theData) + j*incLine1;
587 pt2 = (unsigned char*)(FPXdesc->components[2].theData) + j*incLine2;
588 pt3 = (unsigned char*)(FPXdesc->components[3].theData) + j*incLine3;
589 for (i = 0; i < width; i++) {
590 *pt0 = *pix++; *pt1 = *pix++; *pt2 = *pix++; *pt3 = *pix++;
591 pt0 += incCol0; pt1 += incCol1; pt2 += incCol2; pt3 += incCol3;
592 }
593 }
594 }
595 }
596 }
597
598
599 // ----------------------------------------------------------------------------
600 // External Functions
601 // ----------------------------------------------------------------------------
602
603 // Tells if the space contains an alpha channel
IsAlphaBaseline(FPXBaselineColorSpace baseSpace)604 Boolean IsAlphaBaseline(FPXBaselineColorSpace baseSpace)
605 {
606 Boolean isAlpha = true;
607 if ((baseSpace == SPACE_32_BITS_RGB) ||
608 (baseSpace == SPACE_32_BITS_YCC) ||
609 (baseSpace == SPACE_32_BITS_M))
610 isAlpha = false;
611 return isAlpha;
612 }
613
614 // Get the position of the alpha channel in a 32 bits pixel according to the color space used
GetAlphaOffsetBaseline(FPXBaselineColorSpace baseSpace)615 long GetAlphaOffsetBaseline(FPXBaselineColorSpace baseSpace)
616 {
617 long offset;
618 switch (baseSpace) {
619 case SPACE_32_BITS_ARGB:
620 case SPACE_32_BITS_AYCC:
621 case SPACE_32_BITS_RGB:
622 case SPACE_32_BITS_YCC:
623 case SPACE_32_BITS_M:
624 offset = 0;
625 break;
626 case SPACE_32_BITS_AM:
627 offset = 2;
628 break;
629 case SPACE_32_BITS_O:
630 case SPACE_32_BITS_RGBA:
631 case SPACE_32_BITS_YCCA:
632 case SPACE_32_BITS_MA:
633 offset = 3;
634 break;
635 default: // This shouldn't happen
636 assert(false); // Makes a beep for debug purposes
637 offset = 0;
638 break;
639 }
640 return offset;
641 }
642
643 // Give the number of channels of a baseline color space description
GetNbChannel(FPXBaselineColorSpace baseSpace)644 long GetNbChannel(FPXBaselineColorSpace baseSpace)
645 {
646 long channelNumber;
647 switch (baseSpace) {
648 case SPACE_32_BITS_ARGB:
649 case SPACE_32_BITS_RGBA:
650 case SPACE_32_BITS_AYCC:
651 case SPACE_32_BITS_YCCA:
652 channelNumber = 4;
653 break;
654 case SPACE_32_BITS_RGB:
655 case SPACE_32_BITS_YCC:
656 channelNumber = 3;
657 break;
658 case SPACE_32_BITS_AM:
659 case SPACE_32_BITS_MA:
660 channelNumber = 2;
661 break;
662 case SPACE_32_BITS_M:
663 case SPACE_32_BITS_O:
664 channelNumber = 1;
665 break;
666 default: // We go for the worst case to do our computation, but this shouldn't happen
667 assert(false); // Makes a beep for debug purposes
668 channelNumber = 4;
669 break;
670 }
671 return channelNumber;
672 }
673
674 // This function update a FPXColorspace structure according to the kind of
675 // baseline space chosen
CreateFPXColorSpace(FPXBaselineColorSpace baseSpace,FPXColorspace * colorSpace)676 void CreateFPXColorSpace (FPXBaselineColorSpace baseSpace, FPXColorspace* colorSpace)
677 {
678 switch (baseSpace) {
679 case SPACE_32_BITS_RGB: {
680 colorSpace->numberOfComponents = 3;
681 colorSpace->theComponents[0].myColor = NIFRGB_R;
682 colorSpace->theComponents[1].myColor = NIFRGB_G;
683 colorSpace->theComponents[2].myColor = NIFRGB_B;
684 colorSpace->theComponents[0].myDataType = DATA_TYPE_UNSIGNED_BYTE;
685 colorSpace->theComponents[1].myDataType = DATA_TYPE_UNSIGNED_BYTE;
686 colorSpace->theComponents[2].myDataType = DATA_TYPE_UNSIGNED_BYTE;
687 break;
688 }
689 case SPACE_32_BITS_ARGB: {
690 colorSpace->numberOfComponents = 4;
691 colorSpace->theComponents[0].myColor = ALPHA;
692 colorSpace->theComponents[1].myColor = NIFRGB_R;
693 colorSpace->theComponents[2].myColor = NIFRGB_G;
694 colorSpace->theComponents[3].myColor = NIFRGB_B;
695 colorSpace->theComponents[0].myDataType = DATA_TYPE_UNSIGNED_BYTE;
696 colorSpace->theComponents[1].myDataType = DATA_TYPE_UNSIGNED_BYTE;
697 colorSpace->theComponents[2].myDataType = DATA_TYPE_UNSIGNED_BYTE;
698 colorSpace->theComponents[3].myDataType = DATA_TYPE_UNSIGNED_BYTE;
699 break;
700 }
701 case SPACE_32_BITS_RGBA: {
702 colorSpace->numberOfComponents = 4;
703 colorSpace->theComponents[0].myColor = NIFRGB_R;
704 colorSpace->theComponents[1].myColor = NIFRGB_G;
705 colorSpace->theComponents[2].myColor = NIFRGB_B;
706 colorSpace->theComponents[3].myColor = ALPHA;
707 colorSpace->theComponents[0].myDataType = DATA_TYPE_UNSIGNED_BYTE;
708 colorSpace->theComponents[1].myDataType = DATA_TYPE_UNSIGNED_BYTE;
709 colorSpace->theComponents[2].myDataType = DATA_TYPE_UNSIGNED_BYTE;
710 colorSpace->theComponents[3].myDataType = DATA_TYPE_UNSIGNED_BYTE;
711 break;
712 }
713 case SPACE_32_BITS_YCC: {
714 colorSpace->numberOfComponents = 3;
715 colorSpace->theComponents[0].myColor = PHOTO_YCC_Y;
716 colorSpace->theComponents[1].myColor = PHOTO_YCC_C1;
717 colorSpace->theComponents[2].myColor = PHOTO_YCC_C2;
718 colorSpace->theComponents[0].myDataType = DATA_TYPE_UNSIGNED_BYTE;
719 colorSpace->theComponents[1].myDataType = DATA_TYPE_UNSIGNED_BYTE;
720 colorSpace->theComponents[2].myDataType = DATA_TYPE_UNSIGNED_BYTE;
721 break;
722 }
723 case SPACE_32_BITS_AYCC: {
724 colorSpace->numberOfComponents = 4;
725 colorSpace->theComponents[0].myColor = ALPHA;
726 colorSpace->theComponents[1].myColor = PHOTO_YCC_Y;
727 colorSpace->theComponents[2].myColor = PHOTO_YCC_C1;
728 colorSpace->theComponents[3].myColor = PHOTO_YCC_C2;
729 colorSpace->theComponents[0].myDataType = DATA_TYPE_UNSIGNED_BYTE;
730 colorSpace->theComponents[1].myDataType = DATA_TYPE_UNSIGNED_BYTE;
731 colorSpace->theComponents[2].myDataType = DATA_TYPE_UNSIGNED_BYTE;
732 colorSpace->theComponents[3].myDataType = DATA_TYPE_UNSIGNED_BYTE;
733 break;
734 }
735 case SPACE_32_BITS_YCCA: {
736 colorSpace->numberOfComponents = 4;
737 colorSpace->theComponents[0].myColor = PHOTO_YCC_Y;
738 colorSpace->theComponents[1].myColor = PHOTO_YCC_C1;
739 colorSpace->theComponents[2].myColor = PHOTO_YCC_C2;
740 colorSpace->theComponents[3].myColor = ALPHA;
741 colorSpace->theComponents[0].myDataType = DATA_TYPE_UNSIGNED_BYTE;
742 colorSpace->theComponents[1].myDataType = DATA_TYPE_UNSIGNED_BYTE;
743 colorSpace->theComponents[2].myDataType = DATA_TYPE_UNSIGNED_BYTE;
744 colorSpace->theComponents[3].myDataType = DATA_TYPE_UNSIGNED_BYTE;
745 break;
746 }
747 case SPACE_32_BITS_M: {
748 colorSpace->numberOfComponents = 1;
749 colorSpace->theComponents[0].myColor = MONOCHROME;
750 colorSpace->theComponents[0].myDataType = DATA_TYPE_UNSIGNED_BYTE;
751 break;
752 }
753 case SPACE_32_BITS_AM: {
754 colorSpace->numberOfComponents = 2;
755 colorSpace->theComponents[0].myColor = ALPHA;
756 colorSpace->theComponents[1].myColor = MONOCHROME;
757 colorSpace->theComponents[0].myDataType = DATA_TYPE_UNSIGNED_BYTE;
758 colorSpace->theComponents[1].myDataType = DATA_TYPE_UNSIGNED_BYTE;
759 break;
760 }
761 case SPACE_32_BITS_MA: {
762 colorSpace->numberOfComponents = 2;
763 colorSpace->theComponents[0].myColor = MONOCHROME;
764 colorSpace->theComponents[1].myColor = ALPHA;
765 colorSpace->theComponents[0].myDataType = DATA_TYPE_UNSIGNED_BYTE;
766 colorSpace->theComponents[1].myDataType = DATA_TYPE_UNSIGNED_BYTE;
767 break;
768 }
769 case SPACE_32_BITS_O: {
770 colorSpace->numberOfComponents = 1;
771 colorSpace->theComponents[0].myColor = ALPHA;
772 colorSpace->theComponents[0].myDataType = DATA_TYPE_UNSIGNED_BYTE;
773 break;
774 }
775 case NON_AUTHORIZED_SPACE:
776 break;
777 }
778 }
779
780 // This function analyses a FPXColorSpace given by a user of the Toolkit and checks
781 // if it's consistent and handled by the Baseline implementation.
782 // It returns one of the 10 authorized model or NON_AUTHORIZED_SPACE if nothing fits.
AnalyseFPXColorSpace(FPXColorspace & colorSpace)783 FPXBaselineColorSpace AnalyseFPXColorSpace (FPXColorspace& colorSpace)
784 {
785 FPXBaselineColorSpace spaceFound = NON_AUTHORIZED_SPACE;
786
787 // The data type must be DATA_TYPE_UNSIGNED_BYTE
788 for (long i = 0; i < colorSpace.numberOfComponents; i++) {
789 if (colorSpace.theComponents[i].myDataType != DATA_TYPE_UNSIGNED_BYTE) {
790 assert(false);
791 return spaceFound;
792 }
793 }
794
795 // Switch according to the number of components
796 if (colorSpace.numberOfComponents == 1) {
797 if (colorSpace.theComponents[0].myColor == MONOCHROME)
798 spaceFound = SPACE_32_BITS_M;
799 else if (colorSpace.theComponents[0].myColor == ALPHA)
800 spaceFound = SPACE_32_BITS_O;
801 } else if (colorSpace.numberOfComponents == 2) {
802 if ((colorSpace.theComponents[0].myColor == ALPHA) &&
803 (colorSpace.theComponents[1].myColor == MONOCHROME))
804 spaceFound = SPACE_32_BITS_AM;
805 else if ((colorSpace.theComponents[0].myColor == MONOCHROME) &&
806 (colorSpace.theComponents[1].myColor == ALPHA))
807 spaceFound = SPACE_32_BITS_MA;
808 } else if (colorSpace.numberOfComponents == 3) {
809 if ((colorSpace.theComponents[0].myColor == NIFRGB_R) &&
810 (colorSpace.theComponents[1].myColor == NIFRGB_G) &&
811 (colorSpace.theComponents[2].myColor == NIFRGB_B))
812 spaceFound = SPACE_32_BITS_RGB;
813 else if ((colorSpace.theComponents[0].myColor == PHOTO_YCC_Y) &&
814 (colorSpace.theComponents[1].myColor == PHOTO_YCC_C1) &&
815 (colorSpace.theComponents[2].myColor == PHOTO_YCC_C2))
816 spaceFound = SPACE_32_BITS_YCC;
817 } else if (colorSpace.numberOfComponents == 4) {
818 if ((colorSpace.theComponents[0].myColor == ALPHA) &&
819 (colorSpace.theComponents[1].myColor == NIFRGB_R) &&
820 (colorSpace.theComponents[2].myColor == NIFRGB_G) &&
821 (colorSpace.theComponents[3].myColor == NIFRGB_B))
822 spaceFound = SPACE_32_BITS_ARGB;
823 else if ((colorSpace.theComponents[0].myColor == NIFRGB_R) &&
824 (colorSpace.theComponents[1].myColor == NIFRGB_G) &&
825 (colorSpace.theComponents[2].myColor == NIFRGB_B) &&
826 (colorSpace.theComponents[3].myColor == ALPHA))
827 spaceFound = SPACE_32_BITS_RGBA;
828 else if ((colorSpace.theComponents[0].myColor == ALPHA) &&
829 (colorSpace.theComponents[1].myColor == PHOTO_YCC_Y) &&
830 (colorSpace.theComponents[2].myColor == PHOTO_YCC_C1) &&
831 (colorSpace.theComponents[3].myColor == PHOTO_YCC_C2))
832 spaceFound = SPACE_32_BITS_AYCC;
833 else if ((colorSpace.theComponents[0].myColor == PHOTO_YCC_Y) &&
834 (colorSpace.theComponents[1].myColor == PHOTO_YCC_C1) &&
835 (colorSpace.theComponents[2].myColor == PHOTO_YCC_C2) &&
836 (colorSpace.theComponents[3].myColor == ALPHA))
837 spaceFound = SPACE_32_BITS_YCCA;
838 }
839
840 assert(spaceFound != NON_AUTHORIZED_SPACE);
841 return spaceFound;
842 }
843
ExtractFPXColorSpaceFromFPXImageDesc(FPXImageDesc & desc,FPXColorspace * colorSpace)844 void ExtractFPXColorSpaceFromFPXImageDesc(FPXImageDesc& desc, FPXColorspace* colorSpace)
845 {
846 colorSpace->numberOfComponents = (short) desc.numberOfComponents;
847 for (long i = 0; i < (long) desc.numberOfComponents; i++) {
848 colorSpace->theComponents[i] = desc.components[i].myColorType;
849 }
850 }
851
IsA32bitsBufferDescriptor(FPXImageDesc & desc,long width)852 Boolean IsA32bitsBufferDescriptor(FPXImageDesc& desc, long width)
853 {
854 Boolean is32 = true;
855 long i;
856
857 // Special case if only one channel
858 if (desc.numberOfComponents == 1) {
859 if (desc.components[0].columnStride != 4)
860 is32 = false;
861 }
862
863 // Check the horizontal subsampling factors
864 if (is32) {
865 for (i = 0; i < (long) desc.numberOfComponents; i++)
866 is32 &= (desc.components[i].horzSubSampFactor == 1);
867 }
868
869 // Check the vertical subsampling factors
870 if (is32) {
871 for (i = 0; i <(long) desc.numberOfComponents; i++)
872 is32 &= (desc.components[i].vertSubSampFactor == 1);
873 }
874
875 // Check the column increment
876 if (is32) {
877 for (i = 0; i < (long) desc.numberOfComponents; i++)
878 is32 &= (desc.components[i].columnStride == 4);
879 }
880
881 // Check the line increment
882 if (is32) {
883 long lineStride = width * 4;
884 for (i = 0; i < (long)desc.numberOfComponents; i++)
885 is32 &= (desc.components[i].lineStride == lineStride);
886 }
887
888 // Check the buffer differences (must be one byte)
889 if (is32) {
890 for (i = 0; i < (long)(desc.numberOfComponents-1); i++)
891 is32 &= ((desc.components[i+1].theData - desc.components[i].theData) == 1);
892 }
893
894 return is32;
895 }
896
IsASupportedDescriptor(FPXImageDesc & desc,long width)897 Boolean IsASupportedDescriptor(FPXImageDesc& desc, long width)
898 {
899 Boolean isSupported = true;
900
901 FPXColorspace colorSpace;
902 ExtractFPXColorSpaceFromFPXImageDesc(desc, &colorSpace);
903
904 FPXBaselineColorSpace baselineSpace = AnalyseFPXColorSpace(colorSpace);
905 if (baselineSpace == NON_AUTHORIZED_SPACE)
906 isSupported = false;
907
908 if (isSupported) {
909 isSupported = IsA32bitsBufferDescriptor(desc,width);
910 }
911
912 return isSupported;
913 }
914
915 // Check to see if all pixels in a tile are same and return the pixel value
IsTileAllSamePixel(Pixel * entireTile,short width,short height,Pixel * singleColorPixel)916 Boolean IsTileAllSamePixel(Pixel *entireTile, short width, short height, Pixel* singleColorPixel)
917 {
918 register unsigned long numofpixel = width * height;
919
920 *singleColorPixel = entireTile[0];
921 for ( unsigned long i = 1; i< numofpixel; i++ )
922 if ( singleColorPixel->rouge != entireTile[i].rouge ||
923 singleColorPixel->vert != entireTile[i].vert ||
924 singleColorPixel->bleu != entireTile[i].bleu )
925 return false;
926
927 return true;
928 }
929
930 // Handle all the color conversion / 32 bits interleaving options available in Baseline.
931 // Basically, it's just moving bytes and converting 24bits per pixel colors... it's long so...
932 // We tried to minimize the quantities of computation for each individual case. Could have been done
933 // differently (and less efficiently) by going systematically to some kind of space and converting to all
934 // others... Or using a twist matrix (to much computation so...).
ConvertPixelBuffer(unsigned char * buffer,long size,FPXBaselineColorSpace source,FPXBaselineColorSpace destination)935 void ConvertPixelBuffer(unsigned char* buffer, long size, FPXBaselineColorSpace source, FPXBaselineColorSpace destination)
936 {
937 switch (source) {
938 case SPACE_32_BITS_RGB:
939 switch (destination) {
940 case SPACE_32_BITS_RGB:
941 // Nothing to do
942 break;
943 case SPACE_32_BITS_ARGB:
944 InitByteTo255(buffer,size);
945 break;
946 case SPACE_32_BITS_RGBA:
947 InitByteTo255(buffer,size);
948 Shift8BitsLeft(buffer,size);
949 break;
950 case SPACE_32_BITS_YCC:
951 ConvertRGBtoYCC(buffer+1,size);
952 break;
953 case SPACE_32_BITS_AYCC:
954 ConvertRGBtoYCC(buffer+1,size);
955 InitByteTo255(buffer,size);
956 break;
957 case SPACE_32_BITS_YCCA:
958 ConvertRGBtoYCC(buffer+1,size);
959 InitByteTo255(buffer, size);
960 Shift8BitsLeft(buffer,size);
961 break;
962 case SPACE_32_BITS_M:
963 ConvertRGBtoMonochrome(buffer+1,size);
964 break;
965 case SPACE_32_BITS_AM:
966 ConvertRGBtoMonochrome(buffer+1,size);
967 InitByteTo255(buffer+2,size);
968 break;
969 case SPACE_32_BITS_MA:
970 ConvertRGBtoMonochrome(buffer+1,size);
971 InitByteTo255(buffer,size);
972 Shift8BitsLeft(buffer,size);
973 break;
974 case SPACE_32_BITS_O:
975 ConvertRGBtoMonochrome(buffer+1,size);
976 break;
977 case NON_AUTHORIZED_SPACE:
978 break;
979 }
980 break;
981 case SPACE_32_BITS_ARGB:
982 switch (destination) {
983 case SPACE_32_BITS_RGB:
984 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
985 break;
986 case SPACE_32_BITS_ARGB:
987 // Nothing to do
988 break;
989 case SPACE_32_BITS_RGBA:
990 Shift8BitsLeft(buffer,size);
991 break;
992 case SPACE_32_BITS_YCC:
993 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
994 ConvertRGBtoYCC(buffer+1,size);
995 break;
996 case SPACE_32_BITS_AYCC:
997 ConvertRGBtoYCC(buffer+1,size);
998 break;
999 case SPACE_32_BITS_YCCA:
1000 ConvertRGBtoYCC(buffer+1,size);
1001 Shift8BitsLeft(buffer,size);
1002 //**IM--05/16/97--Maybe it's better to have:
1003 //Shift8BitsLeft(buffer,size);
1004 //ConvertRGBtoYCC(buffer+1,size);
1005 break;
1006 case SPACE_32_BITS_M:
1007 ConvertRGBtoMonochrome(buffer+1,size);
1008 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1009 break;
1010 case SPACE_32_BITS_AM:
1011 ConvertRGBtoMonochrome(buffer+1,size);
1012 MoveByteRightBy2(buffer,size);
1013 break;
1014 case SPACE_32_BITS_MA:
1015 ConvertRGBtoMonochrome(buffer+1,size);
1016 Shift8BitsLeft(buffer,size);
1017 break;
1018 case SPACE_32_BITS_O:
1019 ConvertRGBtoMonochrome(buffer+1,size);
1020 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1021 break;
1022 case NON_AUTHORIZED_SPACE:
1023 break;
1024 }
1025 break;
1026 case SPACE_32_BITS_RGBA:
1027 switch (destination) {
1028 case SPACE_32_BITS_RGB:
1029 Shift8BitsRight(buffer,size);
1030 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1031 break;
1032 case SPACE_32_BITS_ARGB:
1033 Shift8BitsRight(buffer,size);
1034 break;
1035 case SPACE_32_BITS_RGBA:
1036 // Nothing to do
1037 break;
1038 case SPACE_32_BITS_YCC:
1039 Shift8BitsRight(buffer,size);
1040 ConvertRGBtoYCC(buffer+1,size);
1041 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1042 break;
1043 case SPACE_32_BITS_AYCC:
1044 Shift8BitsRight(buffer,size);
1045 ConvertRGBtoYCC(buffer+1,size);
1046 break;
1047 case SPACE_32_BITS_YCCA:
1048 ConvertRGBtoYCC(buffer,size);
1049 break;
1050 case SPACE_32_BITS_M:
1051 Shift8BitsRight(buffer,size);
1052 ConvertRGBtoMonochrome(buffer+1,size);
1053 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1054 break;
1055 case SPACE_32_BITS_AM:
1056 ConvertRGBtoMonochrome(buffer,size);
1057 Shift8BitsRight(buffer,size);
1058 MoveByteRightBy2(buffer,size);
1059 break;
1060 case SPACE_32_BITS_MA:
1061 ConvertRGBtoMonochrome(buffer,size);
1062 break;
1063 case SPACE_32_BITS_O:
1064 Shift8BitsRight(buffer,size);
1065 ConvertRGBtoMonochrome(buffer+1,size);
1066 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1067 break;
1068 case NON_AUTHORIZED_SPACE:
1069 break;
1070 }
1071 break;
1072 case SPACE_32_BITS_YCC:
1073 switch (destination) {
1074 case SPACE_32_BITS_RGB:
1075 ConvertYCCtoRGB(buffer+1,size,FALSE);
1076 break;
1077 case SPACE_32_BITS_ARGB:
1078 ConvertYCCtoRGB(buffer+1,size,FALSE);
1079 InitByteTo255(buffer,size);
1080 break;
1081 case SPACE_32_BITS_RGBA:
1082 //ConvertYCCtoRGB(buffer+1,size,TRUE);
1083 //InitByteTo255(buffer,size);
1084 //Shift8BitsLeft(buffer,size);
1085 //**IM--05/16/97--If Opacity is used never use buffer + 1,..., TRUE
1086 Shift8BitsLeft(buffer,size); //get YCCA
1087 ConvertYCCtoRGB(buffer,size,TRUE);//get RGBA using the right Opacity
1088 InitByteTo255(buffer+3,size);//set Opacity 255;
1089 break;
1090 case SPACE_32_BITS_YCC:
1091 // Nothing to do
1092 break;
1093 case SPACE_32_BITS_AYCC:
1094 InitByteTo255(buffer,size);
1095 break;
1096 case SPACE_32_BITS_YCCA:
1097 InitByteTo255(buffer,size);
1098 Shift8BitsLeft(buffer,size);
1099 break;
1100 case SPACE_32_BITS_M:
1101 ConvertYCCtoMonochrome(buffer+1,size);
1102 break;
1103 case SPACE_32_BITS_AM:
1104 ConvertYCCtoMonochrome(buffer+1,size);
1105 InitByteTo255(buffer+2,size);
1106 break;
1107 case SPACE_32_BITS_MA:
1108 ConvertYCCtoMonochrome(buffer+1,size);
1109 Shift8BitsLeft(buffer,size);
1110 InitByteTo255(buffer+3,size);
1111 break;
1112 case SPACE_32_BITS_O:
1113 ConvertYCCtoMonochrome(buffer+1,size);
1114 break;
1115 case NON_AUTHORIZED_SPACE:
1116 break;
1117 }
1118 break;
1119 case SPACE_32_BITS_AYCC:
1120 switch (destination) {
1121 case SPACE_32_BITS_RGB:
1122 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1123 Shift8BitsLeft(buffer,size); //get YCCA--**IM--05/16/97
1124 //ConvertYCCtoRGB(buffer+1,size,TRUE);
1125 ConvertYCCtoRGB(buffer,size,TRUE);//get RGBA
1126 Shift8BitsRight(buffer,size);//get ARGB
1127 break;
1128 case SPACE_32_BITS_ARGB:
1129 //ConvertYCCtoRGB(buffer+1,size,TRUE);
1130 Shift8BitsLeft(buffer,size); //get YCCA--**IM--05/16/97
1131 ConvertYCCtoRGB(buffer,size,TRUE);//get RGBA
1132 Shift8BitsRight(buffer,size);//get ARGB
1133 break;
1134 case SPACE_32_BITS_RGBA:
1135 //ConvertYCCtoRGB(buffer+1,size,TRUE);
1136 //Shift8BitsLeft(buffer,size);
1137 Shift8BitsLeft(buffer,size);//get YCCA --**IM--05/16/97
1138 ConvertYCCtoRGB(buffer,size,TRUE);//get RGBA
1139 break;
1140 case SPACE_32_BITS_YCC:
1141 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1142 break;
1143 case SPACE_32_BITS_AYCC:
1144 // Nothing to do
1145 break;
1146 case SPACE_32_BITS_YCCA:
1147 Shift8BitsLeft(buffer,size);
1148 break;
1149 case SPACE_32_BITS_M:
1150 ConvertYCCtoMonochrome(buffer+1,size);
1151 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1152 break;
1153 case SPACE_32_BITS_AM:
1154 ConvertYCCtoMonochrome(buffer+1,size);
1155 MoveByteRightBy2(buffer,size);
1156 break;
1157 case SPACE_32_BITS_MA:
1158 ConvertYCCtoMonochrome(buffer+1,size);
1159 Shift8BitsLeft(buffer,size);
1160 break;
1161 case SPACE_32_BITS_O:
1162 ConvertYCCtoMonochrome(buffer+1,size);
1163 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1164 break;
1165 case NON_AUTHORIZED_SPACE:
1166 break;
1167 }
1168 break;
1169 case SPACE_32_BITS_YCCA:
1170 switch (destination) {
1171 case SPACE_32_BITS_RGB:
1172 //Shift8BitsRight(buffer,size);
1173 //ConvertYCCtoRGB(buffer+1,size);
1174 ConvertYCCtoRGB(buffer,size,TRUE);//get RGBA
1175 Shift8BitsRight(buffer,size); //get ARGB
1176 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1177 break;
1178 case SPACE_32_BITS_ARGB:
1179 // Shift8BitsRight(buffer,size);
1180 // ConvertYCCtoRGB(buffer+1,size,TRUE);
1181 ConvertYCCtoRGB(buffer,size,TRUE);//get RGBA --**IM--05/02/97--fixed bug 17998
1182 Shift8BitsRight(buffer,size);//get ARGB
1183 break;
1184 case SPACE_32_BITS_RGBA:
1185 ConvertYCCtoRGB(buffer,size,TRUE);
1186 break;
1187 case SPACE_32_BITS_YCC:
1188 Shift8BitsRight(buffer,size);
1189 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1190 break;
1191 case SPACE_32_BITS_AYCC:
1192 Shift8BitsRight(buffer,size);
1193 break;
1194 case SPACE_32_BITS_YCCA:
1195 // Nothing to do
1196 break;
1197 case SPACE_32_BITS_M:
1198 Shift8BitsRight(buffer,size);
1199 ConvertYCCtoMonochrome(buffer+1,size);
1200 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1201 break;
1202 case SPACE_32_BITS_AM:
1203 ConvertYCCtoMonochrome(buffer,size);
1204 Shift8BitsRight(buffer,size);
1205 MoveByteRightBy2(buffer,size);
1206 break;
1207 case SPACE_32_BITS_MA:
1208 ConvertYCCtoMonochrome(buffer,size);
1209 break;
1210 case SPACE_32_BITS_O:
1211 Shift8BitsRight(buffer,size);
1212 ConvertYCCtoMonochrome(buffer+1,size);
1213 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1214 break;
1215 case NON_AUTHORIZED_SPACE:
1216 break;
1217 }
1218 break;
1219 case SPACE_32_BITS_M:
1220 case SPACE_32_BITS_O:
1221 switch (destination) {
1222 case SPACE_32_BITS_RGB:
1223 ConvertMonochrometoRGB(buffer+1,size);
1224 break;
1225 case SPACE_32_BITS_ARGB:
1226 ConvertMonochrometoRGB(buffer+1,size);
1227 InitByteTo255(buffer,size);
1228 break;
1229 case SPACE_32_BITS_RGBA:
1230 ConvertMonochrometoRGB(buffer+1,size);
1231 InitByteTo255(buffer,size);
1232 Shift8BitsLeft(buffer,size);
1233 break;
1234 case SPACE_32_BITS_YCC:
1235 ConvertMonochrometoYCC(buffer+1,size);
1236 break;
1237 case SPACE_32_BITS_AYCC:
1238 ConvertMonochrometoYCC(buffer+1,size);
1239 InitByteTo255(buffer,size);
1240 break;
1241 case SPACE_32_BITS_YCCA:
1242 ConvertMonochrometoYCC(buffer+1,size);
1243 InitByteTo255(buffer,size);
1244 Shift8BitsLeft(buffer,size);
1245 break;
1246 case SPACE_32_BITS_M:
1247 // Nothing to do
1248 break;
1249 case SPACE_32_BITS_AM:
1250 InitByteTo255(buffer+2,size);
1251 break;
1252 case SPACE_32_BITS_MA:
1253 InitByteTo255(buffer,size);
1254 Shift8BitsLeft(buffer,size);
1255 break;
1256 case SPACE_32_BITS_O:
1257 // Nothing to do
1258 break;
1259 case NON_AUTHORIZED_SPACE:
1260 break;
1261 }
1262 break;
1263 case SPACE_32_BITS_AM:
1264 switch (destination) {
1265 case SPACE_32_BITS_RGB:
1266 MoveByteLeftBy2(buffer+2,size);
1267 ConvertMonochrometoRGB(buffer+1,size);
1268 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1269 break;
1270 case SPACE_32_BITS_ARGB:
1271 MoveByteLeftBy2(buffer+2,size);
1272 ConvertMonochrometoRGB(buffer+1,size);
1273 break;
1274 case SPACE_32_BITS_RGBA:
1275 MoveByteLeftBy2(buffer+2,size);
1276 ConvertMonochrometoRGB(buffer+1,size);
1277 Shift8BitsLeft(buffer,size);
1278 break;
1279 case SPACE_32_BITS_YCC:
1280 MoveByteLeftBy2(buffer+2,size);
1281 ConvertMonochrometoYCC(buffer+1,size);
1282 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1283 break;
1284 case SPACE_32_BITS_AYCC:
1285 MoveByteLeftBy2(buffer+2,size);
1286 ConvertMonochrometoYCC(buffer+1,size);
1287 break;
1288 case SPACE_32_BITS_YCCA:
1289 MoveByteLeftBy2(buffer+2,size);
1290 ConvertMonochrometoYCC(buffer+1,size);
1291 Shift8BitsLeft(buffer,size);
1292 break;
1293 case SPACE_32_BITS_M:
1294 // InitByteTo0(buffer+2,size); now we prefer to preserve the alpha channel if any
1295 break;
1296 case SPACE_32_BITS_AM:
1297 // Nothing to do
1298 break;
1299 case SPACE_32_BITS_MA:
1300 Shift8BitsLeft(buffer,size);
1301 MoveByteRightBy2(buffer+1,size);
1302 break;
1303 case SPACE_32_BITS_O:
1304 // InitByteTo0(buffer+2,size); now we prefer to preserve the alpha channel if any
1305 break;
1306 case NON_AUTHORIZED_SPACE:
1307 break;
1308 }
1309 break;
1310 case SPACE_32_BITS_MA:
1311 switch (destination) {
1312 case SPACE_32_BITS_RGB:
1313 Shift8BitsRight(buffer,size);
1314 ConvertMonochrometoRGB(buffer+1,size);
1315 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1316 break;
1317 case SPACE_32_BITS_ARGB:
1318 Shift8BitsRight(buffer,size);
1319 ConvertMonochrometoRGB(buffer+1,size);
1320 break;
1321 case SPACE_32_BITS_RGBA:
1322 ConvertMonochrometoRGB(buffer,size);
1323 break;
1324 case SPACE_32_BITS_YCC:
1325 Shift8BitsRight(buffer,size);
1326 ConvertMonochrometoYCC(buffer+1,size);
1327 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1328 break;
1329 case SPACE_32_BITS_AYCC:
1330 Shift8BitsRight(buffer,size);
1331 ConvertMonochrometoYCC(buffer+1,size);
1332 break;
1333 case SPACE_32_BITS_YCCA:
1334 ConvertMonochrometoYCC(buffer,size);
1335 break;
1336 case SPACE_32_BITS_M:
1337 Shift8BitsRight(buffer,size);
1338 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1339 break;
1340 case SPACE_32_BITS_AM:
1341 Shift8BitsRight(buffer,size);
1342 MoveByteRightBy2(buffer,size);
1343 break;
1344 case SPACE_32_BITS_MA:
1345 // Nothing to do
1346 break;
1347 case SPACE_32_BITS_O:
1348 Shift8BitsRight(buffer,size);
1349 // InitByteTo0(buffer,size); now we prefer to preserve the alpha channel if any
1350 break;
1351 case NON_AUTHORIZED_SPACE:
1352 break;
1353 }
1354 break;
1355 default:
1356 {
1357 }
1358 }
1359 }
1360
1361 // Create a thumbnail image in windows DIB format
CreateThumbnail(unsigned char * buf,FPXBaselineColorSpace baseSpace,unsigned short thumbNailWidth,unsigned short thumbNailHeight,CLIPDATA * clipData)1362 Boolean CreateThumbnail(unsigned char* buf, FPXBaselineColorSpace baseSpace,
1363 unsigned short thumbNailWidth, unsigned short thumbNailHeight,
1364 CLIPDATA * clipData)
1365 {
1366 Ptr buffer;
1367 long thumbnailSize;
1368 ptr_Compresseur monCompresseur;
1369 BITMAPINFOHEADER bmpInfoHdr;
1370
1371 // Get the TLC_32Vers24 compressor
1372 if ( !(monCompresseur = (*tousLesCodecs)[TLC_32Vers24]) )
1373 return FALSE;
1374
1375 // Thumbnails cannot be stored in YCC. Convert to RGB if necessary
1376 if ( (baseSpace == SPACE_32_BITS_YCC) || (baseSpace == SPACE_32_BITS_YCCA) ) {
1377 ConvertPixelBuffer( (unsigned char*)(buf), thumbNailWidth * thumbNailHeight,
1378 baseSpace, SPACE_32_BITS_RGB);
1379 baseSpace = SPACE_32_BITS_RGB;
1380 }
1381
1382 // In the case of simple compression, we have to set the number of channels and the direction
1383 // of the compression. This is optimized only for the most common cases.
1384 Boolean leftShift = FALSE;
1385 if ( (baseSpace == SPACE_32_BITS_RGBA) || (baseSpace == SPACE_32_BITS_YCCA) )
1386 leftShift = TRUE;
1387
1388 // For thumbnail, 4 channels is compressed to 3 channels image, and 2 channels is compressed to 1 channel image
1389 short nbChannels = (short) GetNbChannel(baseSpace);
1390 switch(nbChannels)
1391 {
1392 case 4:
1393 case 3:
1394 {
1395 nbChannels = 3;
1396 ((obj_Compresseur32Vers24 *)monCompresseur)->SetCompressionParameters(nbChannels,leftShift);
1397
1398 if ( !((obj_Compresseur32Vers24 *)monCompresseur)->Compresse((Ptr)buf, thumbNailWidth, thumbNailHeight,
1399 &buffer, &thumbnailSize))
1400 return FALSE;
1401 break;
1402 }
1403 case 2:
1404 {
1405 // For SPACE_32_BITS_MA, first convert to SPACE_32_BITS_AM image, then compressed to 1 channel image
1406 // For SPACE_32_BITS_AM, it can be considered as 1 channel image
1407 if ( baseSpace == SPACE_32_BITS_MA )
1408 ConvertPixelBuffer((unsigned char*)(buf),thumbNailWidth*thumbNailHeight,SPACE_32_BITS_MA,SPACE_32_BITS_AM);
1409
1410 nbChannels = 1;
1411 ((obj_Compresseur32Vers24 *)monCompresseur)->SetCompressionParameters(nbChannels, leftShift);
1412 if ( !((obj_Compresseur32Vers24 *)monCompresseur)->Compresse((Ptr)buf, thumbNailWidth, thumbNailHeight,
1413 &buffer, &thumbnailSize))
1414 return FALSE;
1415
1416 break;
1417 }
1418 case 1:
1419 {
1420 ((obj_Compresseur32Vers24 *)monCompresseur)->SetCompressionParameters(nbChannels,leftShift);
1421
1422 if ( !((obj_Compresseur32Vers24 *)monCompresseur)->Compresse((Ptr)buf, thumbNailWidth, thumbNailHeight,
1423 &buffer, &thumbnailSize))
1424 return FALSE;
1425 break;
1426 }
1427 default:
1428 return FALSE;
1429 }
1430
1431 // PTCH_203 Recalculate "thumbnailSize" and account for required DIB line padding ...
1432 if (nbChannels >= 3) {
1433 int padBytes = (4 - ((thumbNailWidth * 3) % 4)) & 0x03;
1434 thumbnailSize = (thumbNailWidth * 3 + padBytes) * thumbNailHeight;
1435 }
1436 else {
1437 int padWidth = ((thumbNailWidth + 3) /4) * 4;
1438 thumbnailSize = padWidth * thumbNailHeight;
1439 }
1440 // PTCH_203 ...end of change
1441
1442 // Alloc for clipdata. For single channel image, additional space for palette is also included
1443 if ( nbChannels == 1 )
1444 clipData->cbSize = thumbnailSize + sizeof(BITMAPINFOHEADER) + 2 * sizeof(long) + DefaultPaletteSize * sizeof(RGBQUAD);
1445 else
1446 clipData->cbSize = thumbnailSize + sizeof(BITMAPINFOHEADER) + 2 * sizeof(long);
1447
1448 clipData->pClipData = new unsigned char[clipData->cbSize]; // PTCH_103 mod: + 300];
1449
1450 if ( !clipData->pClipData )
1451 return FALSE;
1452
1453 // Write thumbnail header
1454 unsigned long ignore1 = 0xFFFFFFFF; // Write ignore1 of thumbnail header
1455 unsigned long ignore2 = 0x00000008; // Write ignore2 of thumbnail header
1456
1457 // Write bitmap info header
1458 bmpInfoHdr.biSize = sizeof(BITMAPINFOHEADER); // Write size of bitmap info header
1459 bmpInfoHdr.biWidth = thumbNailWidth; // Write bitmap width
1460 bmpInfoHdr.biHeight = thumbNailHeight; // Write bitmap width
1461 bmpInfoHdr.biPlanes = 1; // Write bitmap planes
1462 /**
1463 if ( nbChannels == 1 )
1464 bmpInfoHdr.biBitCount = 0x3d08; // Write bitmap bit count for single channel
1465 else
1466 bmpInfoHdr.biBitCount = 0x3d24; // Write bitmap bit count for multi channels
1467 **/
1468 if ( nbChannels == 1 )
1469 bmpInfoHdr.biBitCount = 8; // Write bitmap bit count for single channel
1470
1471 else
1472 bmpInfoHdr.biBitCount = 24; // Write bitmap bit count for multi channels
1473
1474 bmpInfoHdr.biCompression = BI_RGB; // Write bitmap compression
1475 bmpInfoHdr.biSizeImage = thumbnailSize; // Write bitmap size
1476 bmpInfoHdr.biXPelsPerMeter = 75 * 39; // Write X dpi per meter
1477 bmpInfoHdr.biYPelsPerMeter = 75 * 39; // Write Y dpi per meter
1478 bmpInfoHdr.biClrUsed = 0; // Write biClrUsed
1479 bmpInfoHdr.biClrImportant = 0; // Write biClrImportant
1480
1481 // Swap bytes if necessary
1482 #ifdef IN_BIG_ENDIAN
1483 ignore1 = (unsigned long) SwapBytes( (int32) ignore1 );
1484 ignore2 = (unsigned long) SwapBytes( (int32) ignore2 );
1485
1486 bmpInfoHdr.biSize = (long) SwapBytes( (int32) bmpInfoHdr.biSize );
1487 bmpInfoHdr.biWidth = (long) SwapBytes( (int32) bmpInfoHdr.biWidth );
1488 bmpInfoHdr.biHeight = (long) SwapBytes( (int32) bmpInfoHdr.biHeight );
1489 bmpInfoHdr.biPlanes = (unsigned short) SwapBytes( (int16) bmpInfoHdr.biPlanes );
1490 bmpInfoHdr.biBitCount = (unsigned short) SwapBytes( (int16) bmpInfoHdr.biBitCount );
1491 bmpInfoHdr.biCompression = (unsigned long) SwapBytes( (int32) bmpInfoHdr.biCompression );
1492 bmpInfoHdr.biSizeImage = (unsigned long) SwapBytes( (int32) bmpInfoHdr.biSizeImage );
1493 bmpInfoHdr.biXPelsPerMeter = (unsigned long) SwapBytes( (int32) bmpInfoHdr.biXPelsPerMeter );
1494 bmpInfoHdr.biYPelsPerMeter = (unsigned long) SwapBytes( (int32) bmpInfoHdr.biYPelsPerMeter );
1495 bmpInfoHdr.biClrUsed = (unsigned long) SwapBytes( (int32) bmpInfoHdr.biClrUsed );
1496 bmpInfoHdr.biClrImportant = (unsigned long) SwapBytes( (int32) bmpInfoHdr.biClrImportant );
1497 #endif
1498
1499 // Copy thumbnail header into clipdata
1500 memcpy(clipData->pClipData, &ignore1, sizeof(long));
1501 memcpy(clipData->pClipData + sizeof(long), &ignore2, sizeof(long));
1502
1503 // Copy bitmap info header into clipdata
1504 memcpy(clipData->pClipData + 2 * sizeof(long), &bmpInfoHdr, sizeof(BITMAPINFOHEADER));
1505
1506 // Get a new position for clipData->pClipData
1507 unsigned char * ptr = clipData->pClipData + 2 * sizeof(long) + sizeof(BITMAPINFOHEADER);
1508
1509 // Get window DIB format data
1510 switch(nbChannels)
1511 {
1512 case 1:
1513 {
1514 // For single channel images, create a default palette
1515 SetDefaultPalette(ptr);
1516
1517 // Get the new buffer pointer
1518 ptr += DefaultPaletteSize * sizeof(RGBQUAD);
1519
1520 // Write the thumbnail data
1521 //memcpy(ptr, (unsigned char *)buffer, thumbnailSize);
1522 writeDIB1((unsigned char *)buffer, ptr, thumbNailWidth, thumbNailHeight);
1523 break;
1524 }
1525 case 3:
1526 // Convert RGB format to BGR (Windows DIB format)
1527 writeDIB24((unsigned char *)buffer, ptr, thumbNailWidth, thumbNailHeight);
1528 break;
1529
1530 default:
1531 return FALSE;
1532 }
1533
1534 #ifdef _WINDOWS
1535 clipData->ulClipFmt = -1;
1536 #else
1537 #ifdef macintosh
1538 clipData->ulClipFmt = -2;
1539 #endif
1540 #endif
1541
1542 return TRUE;
1543 }
1544
1545 // Create window DIB default palette, which is grayscale ramp of 256 RGBQUAD
SetDefaultPalette(unsigned char * palBuffer)1546 void SetDefaultPalette(unsigned char *palBuffer)
1547 {
1548 register unsigned long *all;
1549
1550 // Set the grayscale ramp of RGBQUADs
1551 all = (unsigned long *)(palBuffer);
1552 for ( long i = 0; i < DefaultPaletteSize; i++ ) {
1553 *all = i << 24 | i << 16 | i << 8 | 0 ;
1554
1555 #ifdef IN_LITTLE_ENDIAN
1556
1557 *all = (unsigned long) SwapBytes( (int32) *all );
1558
1559 #endif
1560
1561
1562 all++;
1563 }
1564 }
1565
1566 // Convert RGB format to BGR (Windows DIB format)
writeDIB24(unsigned char * obp,unsigned char * pic24,unsigned long w,unsigned long h)1567 void writeDIB24(unsigned char *obp, unsigned char *pic24, unsigned long w, unsigned long h)
1568 {
1569 long i, j, padb;
1570 unsigned char *pp;
1571
1572 padb = (4 - ((w * 3) % 4)) & 0x03; // # of pad bytes to write at EOscanline */
1573
1574 // DIBs are upside down... how typical...
1575 for ( i = h - 1; i >= 0; i-- ) {
1576 pp = pic24 + (i * (w * 3 + padb));
1577
1578 for (j = 0; j < (long) w; j++) {
1579 pp[2] = *obp++; /* B (again, how typical...) */
1580 pp[1] = *obp++; /* G */
1581 pp[0] = *obp++; /* R */
1582 pp+=3;
1583 }
1584 for (j = 0; j < padb; j++)
1585 *pp++ = 0;
1586 }
1587 }
1588
writeDIB1(unsigned char * obp,unsigned char * pic8,unsigned long w,unsigned long h)1589 void writeDIB1(unsigned char *obp, unsigned char *pic8, unsigned long w, unsigned long h)
1590 {
1591 unsigned long j, padw;
1592 long i;
1593 unsigned char *pp;
1594
1595 padw = ((w + 3)/4) * 4; /* 'w', padded to be a multiple of 32 */
1596
1597 for (i=h-1; i>=0; i--) {
1598 pp = pic8 + (i * padw);
1599
1600 for (j=0; j<w; j++) *pp++ = *obp++;
1601 for ( ; j<padw; j++) *pp++ = 0;
1602 }
1603 }
1604 // - EOF ----------------------------------------------------------------------
1605