1 // ----------------------------------------------------------------------------
2 //
3 // FlashPix FILE MANAGEMENT
4 //
5 // MODULE : FileFlashPixIO.cpp
6 // LANGUAGE : C++
7 // AUTHOR : Nicolas ROMANTZOFF
8 // DATE : Wednesday, July 5th 1995
9 // DESCRIPTION :
10 // COMMENT :
11 // SCCSID : @(#)f_fpxio.cpp 1.6 12:47:06 01 Jul 1997
12 // ----------------------------------------------------------------------------
13 // Copyright (c) 1999 Digital Imaging Group, Inc.
14 // For conditions of distribution and use, see copyright notice
15 // in Flashpix.h
16 // ----------------------------------------------------------------------------
17 #include "f_fpxio.h"
18 // #define Memoire_Debug // doesn't work without our memory management
19 // ----------------------------------------------------------------------------
20
21 // Includes
22 // --------
23
24 #include <string.h>
25 #include <stdio.h>
26
27 #if defined(USE_LEGACY_INCLUDES)
28 # include <fstream.h>
29 #else
30 # include <fstream>
31 using namespace std;
32 #endif
33
34 #ifdef macintosh
35 #include <Errors.h>
36 #endif
37 #ifndef Numbers_h
38 #include "numbers.h"
39 #endif
40 #ifndef Memoire_h
41 //include "b_memory.h"
42 #endif
43 #ifndef Debug_h
44 #include "debug.h"
45 #endif
46
47 #ifndef FPXBaselineIO_h
48 #include "fpxlibio.h"
49 #endif
50 #ifndef FPXBaselineView_h
51 #include "fpxlib.h"
52 #endif
53
54 #ifndef PageIVUE_h
55 #include "ri_page.h"
56 #endif
57
58
59 #ifndef OLECommun_h
60 #include "olecomm.h"
61 #endif
62 #ifndef OLECore_h
63 #include "olecore.h"
64 #endif
65 #ifndef OLEStorages_h
66 #include "olestorg.h"
67 #endif
68 #ifndef OLEHeaderStream_h
69 #include "olehstrm.h"
70 #endif
71 #ifndef OLEProperties_h
72 #include "oleprop.h"
73 #endif
74 #ifndef OLEPropertySet_h
75 #include "oleprops.h"
76 #endif
77 #ifndef OLEFiles_h
78 #include "olefiles.h"
79 #endif
80
81 #ifndef FlashPixUtils_h
82 #include "fpxutils.h"
83 #endif
84 #ifndef FlashPixFormat_h
85 #include "fpxformt.h"
86 #endif
87
88 #ifndef PResolutionFlashPix_h
89 #include "pres_fpx.h"
90 #endif
91 #ifndef PTile_h
92 #include "ptile.h"
93 #endif
94 #ifndef BufferDesc_h
95 #include "buffdesc.h"
96 #endif
97 #ifndef FPXThumbnail_h
98 #include "thmbnail.h"
99 #endif
100
101 // Constants
102 // ---------
103 //
104
105 #define WRITING_BUFFER_SIZE (512*1024)
106
107 #define SW 0
108 #define SE 1
109 #define NW 2
110 #define NE 3
111
112 #define NB_MAX_ERREUR 5
113
114 // Variables
115 // ---------
116
117 // ----------------------------------------------------------------------------
118 #ifdef macintosh
119 #pragma segment FileFlashPixIO
120 #endif
121 // ----------------------------------------------------------------------------
122
123 // ----------------------------------------------------------------------------
124 // Internal Functions
125 // ----------------------------------------------------------------------------
126
ComputeNumberOfResolutions(int width,int height,int tileWidth)127 static int ComputeNumberOfResolutions (int width, int height, int tileWidth)
128 {
129 int nbResolutions = 1;
130
131 while ((width > tileWidth) || (height > tileWidth)) {
132 nbResolutions++;
133 width = (width + 1) / 2;
134 height = (height + 1) / 2;
135 }
136
137 return nbResolutions;
138 }
139
140 // ----------------------------------------------------------------------------
141 // External functions
142 // ----------------------------------------------------------------------------
143
144
145 // ----------------------------------------------------------------------------
146 // Methods
147 // ----------------------------------------------------------------------------
148
149 // ----------------------------------------------------------------------------
150 // Methods of the PFileFlashPixIO class
151 //
152 // Manage all records to an FPX file. The field "firstSubImage" points to the
153 // full resolution image which points of the /4 subimage, and so on�
154 //
155 // ----------------------------------------------------------------------------
156
157
158 // Open a file in Read mode only (compressed or uncompressed) :
159 // CAUTION : the file is opened as long as necessary
PFileFlashPixIO(FicNom & refName,const char * theStorageName)160 PFileFlashPixIO::PFileFlashPixIO (FicNom& refName, const char* theStorageName) : PHierarchicalImage (refName)
161 {
162 Init (); // Init the object
163 SetTileParameter (FPX_TILE_WIDTH, FPX_TILE_WIDTH);
164 storageName = theStorageName;
165 }
166
167
168 // ----------------------------------------------------------------------------
PFileFlashPixIO(OLEStorage * theOwningStorage,const char * theStorageName)169 PFileFlashPixIO::PFileFlashPixIO (OLEStorage* theOwningStorage, const char* theStorageName) : PHierarchicalImage (0)
170 {
171 Init (); // Init the object
172 SetTileParameter (FPX_TILE_WIDTH, FPX_TILE_WIDTH);
173 owningStorage = theOwningStorage;
174 storageName = theStorageName;
175 }
176
177
178 // ----------------------------------------------------------------------------
179 // Open a file in Read or Write mode (compressed or uncompressed) :
180 // CAUTION : the file is opened as long as necessary
PFileFlashPixIO(FicNom & refName,const char * theStorageName,mode_Ouverture openMode)181 PFileFlashPixIO::PFileFlashPixIO (FicNom& refName, const char* theStorageName, mode_Ouverture openMode) : PHierarchicalImage (refName)
182 {
183 Init (); // Init the object
184 SetTileParameter (FPX_TILE_WIDTH, FPX_TILE_WIDTH);
185 storageName = theStorageName;
186 }
187
188
189 // ----------------------------------------------------------------------------
PFileFlashPixIO(OLEStorage * theOwningStorage,const char * theStorageName,mode_Ouverture openMode)190 PFileFlashPixIO::PFileFlashPixIO (OLEStorage* theOwningStorage, const char* theStorageName, mode_Ouverture openMode) : PHierarchicalImage (0, openMode)
191 {
192 Init (); // Init the object
193 SetTileParameter (FPX_TILE_WIDTH, FPX_TILE_WIDTH);
194 owningStorage = theOwningStorage;
195 storageName = theStorageName;
196 }
197
198
199 // ----------------------------------------------------------------------------
200 // Open a file in Create mode (compressed or uncompressed) :
201 // CAUTION : the file is opened as long as necessary
PFileFlashPixIO(FicNom & refName,int width,int height,float resolution,FPXBaselineColorSpace baseSpace,unsigned long backColor,FPXCompressionOption FPXCompressOption,Boolean baseUncalibrated)202 PFileFlashPixIO::PFileFlashPixIO (FicNom& refName,
203 int width, int height, float resolution,
204 FPXBaselineColorSpace baseSpace, unsigned long backColor,
205 FPXCompressionOption FPXCompressOption,
206 Boolean baseUncalibrated)
207 : PHierarchicalImage (refName, width, height, resolution)
208
209 {
210 Init (); // Init the object
211
212 // Set compression mode. If the image being created is mono or opacity-only,
213 // then clear the "internal color conversion" flags and set the compression
214 // subtype (i.e., chroma subsample) to (1,1). For these cases, RGB-to-YCC color
215 // conversion should not be performed, nor should any data be subsampled.
216
217 if ((baseSpace == SPACE_32_BITS_AM) || (baseSpace == SPACE_32_BITS_MA)
218 || (baseSpace == SPACE_32_BITS_M) || (baseSpace == SPACE_32_BITS_O)) {
219 FPXCompressionSubType &= 0xFFFF00FF; // Clear chroma subsample flags
220 FPXCompressionSubType |= 0x00001100; // and insert (1,1)
221 FPXCompressionSubType &= 0xFF00FFFF; // Clear compression subtype flags
222 }
223
224 SetCompression((Typ_Compression)FPXCompressOption);
225 SetBaseColorSpace(baseSpace); // Set the native color space of the file
226 SetUncalibratedFlag(baseUncalibrated);
227 SetBackgroundColor(baseSpace, backColor); // Set the background color of the file
228 SetTileParameter (FPX_TILE_WIDTH, FPX_TILE_WIDTH);
229 }
230
231
232 // ----------------------------------------------------------------------------
PFileFlashPixIO(OLEStorage * theOwningStorage,const char * theStorageName,int width,int height,float resolution,FPXBaselineColorSpace baseSpace,unsigned long backColor,FPXCompressionOption FPXCompressOption,Boolean baseUncalibrated)233 PFileFlashPixIO::PFileFlashPixIO (OLEStorage* theOwningStorage, const char* theStorageName,
234 int width, int height, float resolution,
235 FPXBaselineColorSpace baseSpace, unsigned long backColor,
236 FPXCompressionOption FPXCompressOption,
237 Boolean baseUncalibrated)
238 : PHierarchicalImage (0, width, height, resolution)
239 {
240 Init (); // Init the object
241
242 // Set compression mode. If the image being created is mono or opacity-only,
243 // then clear the "internal color conversion" flags and set the compression
244 // subtype (i.e., chroma subsample) to (1,1). For these cases, RGB-to-YCC color
245 // conversion should not be performed, nor should any data be subsampled.
246
247 if ((baseSpace == SPACE_32_BITS_AM) || (baseSpace == SPACE_32_BITS_MA)
248 || (baseSpace == SPACE_32_BITS_M) || (baseSpace == SPACE_32_BITS_O)) {
249 FPXCompressionSubType &= 0xFFFF00FF; // Clear chroma subsample flags
250 FPXCompressionSubType |= 0x00001100; // and insert (1,1)
251 FPXCompressionSubType &= 0xFF00FFFF; // Clear compression subtype flags
252 }
253
254 SetCompression((Typ_Compression)FPXCompressOption); // Set compression mode
255 SetBaseColorSpace(baseSpace); // Set the native color space of the file
256 SetUncalibratedFlag(baseUncalibrated);
257 SetBackgroundColor(baseSpace, backColor); // Set the background color of the file
258 SetTileParameter (FPX_TILE_WIDTH, FPX_TILE_WIDTH);
259 owningStorage = theOwningStorage;
260 storageName = theStorageName;
261 }
262
263
264 // ----------------------------------------------------------------------------
265 // Close file and clean memory
~PFileFlashPixIO()266 PFileFlashPixIO::~PFileFlashPixIO()
267 {
268 if (tilesHasBeenModified) {
269 // CAUTION : delete sub-images before closing file because
270 // some file's information are used to close sub-images�
271 if (firstSubImage)
272 firstSubImage->CloseSubImage();
273 // In write mode, we have to commit (write) all changes before deleting anything
274 if ((mode != mode_Lecture))
275 CloseFile();
276 }
277 }
278
279
280 // ----------------------------------------------------------------------------
281 // Init local private stuff
Init()282 void PFileFlashPixIO::Init()
283 {
284 owningStorage = NULL;
285 storageName = NULL;
286
287 // Set default compression option and subtype
288 FPXCompression = NONE; // No compression
289 FPXCompressionSubType = 0x01012200; // Default setting are interleave, subsampling, color conversion, and
290 // jpeg table id of 1
291
292 // Set default quality factor
293 FPXQualityFactor = 10;
294
295 // No resolution created to start with
296 nbCreatedResolutions = 0;
297
298 // No tiles written
299 tilesHasBeenModified = false;
300
301 // Set default unit
302 GtheSystemToolkit->GetUnit((Typ_Unit*)(&fileUnit));
303 }
304
305
306 // ----------------------------------------------------------------------------
307 // Make a sub image in read or write mode
CreateInitResolutionLevel(int * offset,long id)308 PResolutionLevel* PFileFlashPixIO::CreateInitResolutionLevel(int* offset, long id)
309 {
310 PResolutionFlashPix* ptrResolution = new PResolutionFlashPix(this, offset, id);
311 if (ptrResolution)
312 ptrResolution->InitWhenReading();
313 return ptrResolution;
314 }
315
316
317 // ----------------------------------------------------------------------------
318 // Make a sub image list in read or write mode and initialize it
CreateInitResolutionLevelList()319 FPXStatus PFileFlashPixIO::CreateInitResolutionLevelList()
320 {
321 PResolutionLevel* ssImageTmp;
322 int nbImgs, id, tileHeight;
323 int offset;
324
325 if (!nbSubImages) { // Means that "open" failed
326 RaiseError(FPX_FILE_NOT_OPEN_ERROR);
327 return FPX_FILE_NOT_OPEN_ERROR;
328 }
329
330 nbImgs = nbSubImages;
331 id = 0;
332
333 // Create the first sub image and init it reading the file "filePtr"
334 firstSubImage = CreateInitResolutionLevel(&offset, id);
335
336 ssImageTmp = firstSubImage;
337 nbImgs--;
338
339 // While the sub image is correct and there is another : create and init the next
340 while ((ssImageTmp->Status() == 0) && (nbImgs > 0))
341 {
342 ssImageTmp->next = CreateInitResolutionLevel(&offset, ++id);
343 ssImageTmp = ssImageTmp->next;
344 nbImgs--;
345 }
346 if (nbImgs) { // an error has occured during the creation
347 RaiseError(FPX_FILE_CREATE_ERROR);
348 return FPX_FILE_CREATE_ERROR;
349 }
350
351 // Get info from the image file
352 if (GetInfo (&width, &height, &tileWidth, &tileHeight, &compression))
353 RaiseError(FPX_FILE_CREATE_ERROR);
354
355 // Update missing parameters
356 cropX0 = 0;
357 cropY0 = 0;
358 cropX1 = width;
359 cropY1 = height;
360 hotSpotX = width/2;
361 hotSpotY = height/2;
362
363 return Status();
364 }
365
366
367 // ----------------------------------------------------------------------------
368 // Make a sub image in create mode
CreateEmptyResolutionLevel(int width,int height,int * whichImage)369 PResolutionLevel* PFileFlashPixIO::CreateEmptyResolutionLevel(int width, int height, int* whichImage)
370 {
371 PResolutionFlashPix* ptrResolution = new PResolutionFlashPix(this, width, height, whichImage);
372 if (ptrResolution)
373 ptrResolution->InitWhenCreate();
374 return ptrResolution;
375 }
376
377
378 // ----------------------------------------------------------------------------
379 // Make a sub image list in create mode
CreateEmptyResolutionLevelList()380 FPXStatus PFileFlashPixIO::CreateEmptyResolutionLevelList()
381 {
382 PResolutionLevel* ssImageTmp;
383 int width, height;
384 int nb = 0;
385 FPXStatus err = FPX_OK;
386
387 // Compute the number of resolutions
388 width = this->width;
389 height = this->height;
390 nbSubImages = ComputeNumberOfResolutions (width, height, tileWidth);
391
392 // Create the first resolution
393 firstSubImage = CreateEmptyResolutionLevel(width, height, &nb);
394 ssImageTmp = firstSubImage;
395
396 // While the creation is correct create the next sub image
397 while (ssImageTmp->Status() == 0) {
398 width = (width + 1) / 2;
399 height = (height + 1) / 2;
400 ssImageTmp->next = CreateEmptyResolutionLevel(width, height, &nb);
401 ssImageTmp = ssImageTmp->next;
402 }
403
404 if (nb == 0) { // If an error occured during the creation
405 RaiseError(FPX_FILE_CREATE_ERROR);
406 err = FPX_FILE_CREATE_ERROR;
407 nbSubImages = 0; // Invalid the PFileFlashPixIO object
408 }
409
410 if (err == FPX_OK)
411 err = Status();
412 return err;
413 }
414
415
416 // ----------------------------------------------------------------------------
417 // Open the file, create it if necessary (if mode is write)
OpenFile()418 FPXStatus PFileFlashPixIO::OpenFile ()
419 {
420 FPXStatus err = FPX_OK;
421 OSErr fileErr;
422 OLEProperty *aProp;
423 Boolean resFromFile = FALSE;
424
425 // Open the FPX file
426 if (owningStorage) {
427 filePtr = new PFlashPixFile (owningStorage, storageName, mode);
428 }
429 else {
430 // Call the generic search function which may be trapped by the different toolkits
431 if (mode == mode_Lecture)
432 fileName.Search ();
433 filePtr = new PFlashPixFile (fileName, storageName, mode);
434 }
435
436 // If error while opening : signal error
437 if (!filePtr)
438 err = FPX_FILE_NOT_OPEN_ERROR;
439 else if ((fileErr = ((PFlashPixFile*)filePtr)->Erreur()) != noErr) {
440 filePtr->SignaleErreur();
441 if (fileErr == badFidErr)
442 err = FPX_FILE_NOT_FOUND;
443 else
444 err = FPX_FILE_NOT_OPEN_ERROR;
445 }
446
447 // Read or initialize the number of resolutions
448 if ((err == FPX_OK) && (mode != mode_Ecrasement)) {
449 // If open successful in read or write but not Create mode :
450 // The file is opened and the Image Content Property Set point to the
451 // begining of the stream -> Read the number of resolutions.
452
453 // Number of resolutions (required)
454 if (((PFlashPixFile*)filePtr)->GetImageContentProperty (PID_NbResolutions, &aProp))
455 nbCreatedResolutions = int32_t(*aProp);
456 else
457 err = FPX_FILE_READ_ERROR;
458
459 if(nbCreatedResolutions == 1)
460 isFlatFile = TRUE;
461 else
462 isFlatFile = FALSE;
463
464 // Full resolution width (required)
465 if (((PFlashPixFile*)filePtr)->GetImageContentProperty (PID_HiResWidth, &aProp))
466 width = int32_t(*aProp);
467 else
468 err = FPX_FILE_READ_ERROR;
469
470 // Full resolution height (required)
471 if (((PFlashPixFile*)filePtr)->GetImageContentProperty (PID_HiResHeight, &aProp))
472 height = int32_t(*aProp);
473 else
474 err = FPX_FILE_READ_ERROR;
475
476 // Compute the theorical number of resolutions
477 nbSubImages = ComputeNumberOfResolutions (width, height, tileWidth);
478
479 // Compute the resolution according to the default size
480 resolution = (float)(300.0/25.4); // Default resolution
481 fileUnit = FPX_INCHES; // Default unit
482 float widthInUnits, heightInUnits;
483
484 // Units (optionnal)
485 if (((PFlashPixFile*)filePtr)->GetImageContentProperty (PID_DefaultDisplUnit, &aProp))
486 fileUnit = (FPXResolutionUnit)int32_t(*aProp);
487
488 float convertRatio;
489 switch (fileUnit) {
490 case FPX_INCHES: convertRatio = (float)25.4; break;
491 case FPX_METERS: convertRatio = (float)1000.0; break;
492 case FPX_CENTIMETERS: convertRatio = (float)10.0; break;
493 case FPX_MILLIMETERS: convertRatio = (float)1.0; break;
494 }
495
496 // Height (optionnal)
497 if (((PFlashPixFile*)filePtr)->GetImageContentProperty (PID_DefaultDisplHeight, &aProp)) {
498 heightInUnits = (float)(*aProp);
499 resolution = (float)(height)/(heightInUnits*convertRatio);
500 resFromFile = TRUE;
501 }
502
503 // Width (optionnal)
504 if (((PFlashPixFile*)filePtr)->GetImageContentProperty (PID_DefaultDisplWidth, &aProp)) {
505 widthInUnits = (float)(*aProp);
506 resolution = (float)(width)/(widthInUnits*convertRatio);
507 resFromFile = TRUE;
508 }
509 if(!resFromFile)
510 resolution = (float)height;
511
512 // Path specification Group
513
514 if (err)
515 RaiseError(err);
516
517 if ((((PFlashPixFile*)filePtr)->Erreur()) || err) // If an error occurs during reading of information
518 RaiseError(err);
519
520 }
521 else if (mode == mode_Ecrasement && err == FPX_OK) {
522 // In create mode, will have to compute the number of levels to create
523 nbSubImages = 0;
524 }
525
526 if (!Status() && (GtheSystemToolkit->GetErrorsList() != NULL))
527 RaiseError(err);
528
529 if (Status() || (err != FPX_OK)) {
530 delete filePtr; // Close the current file if any
531 filePtr = NULL; // Reset to NULL
532 nbSubImages = 0; // Reset to 0 : means that "open" failed
533 mode = mode_Lecture; // Force mode to be read only
534 if (err == FPX_OK)
535 err = Status();
536 }
537 return err;
538 }
539
540
541 // ----------------------------------------------------------------------------
542 // Create the "subImages" array of pointers according to the "firstSubImage" list
InitResolutionLevelsTable()543 FPXStatus PFileFlashPixIO::InitResolutionLevelsTable()
544 {
545 int i;
546
547 FPXStatus err = PHierarchicalImage::InitResolutionLevelsTable();
548 if (err)
549 return err;
550
551 // Init compression type, quality factor and compression table group
552 for ( i = 0; i < nbSubImages; i++) {
553 ((PResolutionFlashPix *)subImages[i])->compression = FPXCompression;
554 ((PResolutionFlashPix *)subImages[i])->qualityFactor = FPXQualityFactor;
555 ((PResolutionFlashPix *)subImages[i])->compressTableGroup = (unsigned char)(nbSubImages - i);
556 ((PResolutionFlashPix *)subImages[i])->compressionSubtype = SET_JPEGTablesIndex(FPXCompressionSubType, (unsigned char)(nbSubImages - i));
557 }
558
559 // Resolution Description Groups
560 for ( i = 0; i < nbSubImages; i++)
561 if ((err = ((PResolutionFlashPix*)subImages[i])->GetResolutionDescription()) != FPX_OK) {
562 break;
563 }
564
565 // Set the base space being the one of the high res level
566 baseSpace = ((PResolutionFlashPix *)subImages[0])->GetBaselineSpace();
567
568 return err;
569 }
570
571
572 // ----------------------------------------------------------------------------
573 // Store the header of the file before closing
CloseFile()574 FPXStatus PFileFlashPixIO::CloseFile()
575 {
576 FPXStatus err = FPX_OK;
577 OLEProperty *aProp;
578 OLEProperty *aProp0;
579 short i;
580
581 // Number of resolutions (required)
582 if (((PFlashPixFile *)filePtr)->SetImageContentProperty (PID_NbResolutions, TYP_NbResolutions, &aProp))
583 *aProp = (int32_t)(nbCreatedResolutions);
584 else
585 err = FPX_FILE_WRITE_ERROR;
586
587 // Full resolution width (required)
588 if (((PFlashPixFile *)filePtr)->SetImageContentProperty (PID_HiResWidth, TYP_HiResWidth, &aProp))
589 *aProp = (int32_t)(width);
590 else
591 err = FPX_FILE_WRITE_ERROR;
592
593 // Full resolution height (required)
594 if (((PFlashPixFile *)filePtr)->SetImageContentProperty (PID_HiResHeight, TYP_HiResHeight, &aProp))
595 *aProp = (int32_t)(height);
596 else
597 err = FPX_FILE_WRITE_ERROR;
598
599 // Compute the default size according to the resolution
600 float convertRatio;
601 switch (fileUnit) {
602 case FPX_INCHES: convertRatio = (float)25.4; break;
603 case FPX_METERS: convertRatio = (float)1000.0; break;
604 case FPX_CENTIMETERS: convertRatio = (float)10.0; break;
605 case FPX_MILLIMETERS: convertRatio = (float)1.0; break;
606 }
607 float widthInUnits = (float)(width )/(resolution*convertRatio);
608 float heightInUnits = (float)(height)/(resolution*convertRatio);
609
610 // Height (optionnal)
611 if (((PFlashPixFile*)filePtr)->SetImageContentProperty (PID_DefaultDisplHeight, TYP_DefaultDisplHeight, &aProp))
612 *aProp = (float)(heightInUnits);
613 else
614 err = FPX_FILE_WRITE_ERROR;
615
616 // Width (optionnal)
617 if (((PFlashPixFile*)filePtr)->SetImageContentProperty (PID_DefaultDisplWidth, TYP_DefaultDisplWidth, &aProp))
618 *aProp = (float)(widthInUnits);
619 else
620 err = FPX_FILE_WRITE_ERROR;
621
622 // Unit (optionnal)
623 if (((PFlashPixFile*)filePtr)->SetImageContentProperty (PID_DefaultDisplUnit, TYP_DefaultDisplUnit, &aProp))
624 *aProp = (int32_t)(fileUnit);
625 else
626 err = FPX_FILE_WRITE_ERROR;
627
628 // Create the Resolution Description Groups
629 for (i = 0; i < nbCreatedResolutions; i++) {
630 if ((err = (((PResolutionFlashPix*)subImages[i])->SetResolutionDescription())) != FPX_OK) {
631 break;
632 }
633 }
634
635 // Create a thumbnail image in summary info property set if it doesn't exist
636
637 if (((PFlashPixFile *)filePtr)->GetSummaryInfoProperty (PID_THUMBNAIL, &aProp0)) {
638 if (((PFlashPixFile *)filePtr)->SetSummaryInfoProperty (PID_THUMBNAIL, TYP_THUMBNAIL, &aProp)) {
639 err = MakeNewThumbnail ( aProp);
640 }
641 else
642 err = FPX_FILE_READ_ERROR;
643 }
644 // Else if image has been changed, write the thumbnail image again
645 else if (tilesHasBeenModified) {
646 if (((PFlashPixFile *)filePtr)->SetSummaryInfoProperty (PID_THUMBNAIL, TYP_THUMBNAIL, &aProp)) {
647 err = MakeNewThumbnail ( aProp);
648 }
649 else
650 err = FPX_FILE_READ_ERROR;
651 }
652
653 // Create the Compression Information Group
654
655 // Create the Path specification Group
656
657 if (err == FPX_OK)
658 ((PFlashPixFile*)filePtr)->Commit();
659 return err;
660 }
661
662
663 // ----------------------------------------------------------------------------
664 // Create a new thumbnail image and save it in the file
MakeNewThumbnail(OLEProperty * aProp)665 FPXStatus PFileFlashPixIO::MakeNewThumbnail ( OLEProperty *aProp)
666 {
667 FPXStatus err = FPX_OK; // PTCH_102
668
669
670 // Determine the width and height of thumbnail
671 int thumbNailWidth, thumbNailHeight;
672 if ( width >= height ) {
673 thumbNailWidth = MaxThumbNailSize;
674 thumbNailHeight = (int)( thumbNailWidth * height ) / width;
675 }
676 else {
677 thumbNailHeight = MaxThumbNailSize;
678 thumbNailWidth = (int)( thumbNailHeight * width ) / height;
679 }
680
681 // The thumbnail should either be monochrome or 24-bit RGB (never YCC). Save the old
682 // image's colorSpace and force a new one specifically for the thumbnail
683 FPXBaselineColorSpace saved_usedSpace = usedSpace;
684 if ( (usedSpace == SPACE_32_BITS_MA) || (usedSpace == SPACE_32_BITS_AM)
685 || (usedSpace == SPACE_32_BITS_M) )
686 usedSpace = SPACE_32_BITS_MA;
687 else
688 usedSpace = SPACE_32_BITS_RGB;
689
690 // Create a buffer to hold the image to be created
691 FPXBufferDesc thumbNail(1, thumbNailWidth, thumbNailHeight, usedSpace);
692 if (thumbNail.Get32BitsBuffer() == NULL) {
693 return FPX_MEMORY_ALLOCATION_FAILED;
694 }
695
696 // Thumbnails are to be composited on a white background. Save the old background
697 // color and set the current background color to white.
698 Pixel backgroundColor = GtheSystemToolkit->backgroundColor;
699 Pixel whiteColor = 0xFFFFFFFF;
700 GtheSystemToolkit->SetBackgroundColor (whiteColor, SPACE_32_BITS_RGB);
701
702
703 // Now render a new thumbnail image
704 PageImage page (this, thumbNailWidth, thumbNailHeight, (float)0.0);
705 page.ReadPage(thumbNail.Get32BitsBuffer());
706
707 // Create the thumbnail property in the CLIPDATA format
708 CLIPDATA cf;
709 if ( CreateThumbnail((unsigned char *)thumbNail.Get32BitsBuffer(), usedSpace,
710 (short)thumbNailWidth, (short)thumbNailHeight,&cf) )
711 {
712 *aProp = (CLIPDATA *)&cf;
713 delete[] cf.pClipData;
714 }
715 else
716 err = FPX_ERROR;
717
718 // Reset the used colorSpace and the background color
719 usedSpace = saved_usedSpace;
720 GtheSystemToolkit->SetBackgroundColor (backgroundColor, SPACE_32_BITS_RGB);
721
722 return err;
723 }
724
725
726 // ----------------------------------------------------------------------------
727 // Write any tiles whose pixels have been modified out to the file.
FlushModifiedTiles()728 FPXStatus PFileFlashPixIO::FlushModifiedTiles ( )
729 {
730 int i;
731 FPXStatus mostRecentStatus, status = FPX_OK;
732
733 for ( i = 0; i < nbSubImages; i++) {
734 mostRecentStatus = ((PResolutionFlashPix *)subImages[i])->FlushModifiedTiles();
735 if (mostRecentStatus != FPX_OK)
736 status = mostRecentStatus;
737 }
738 return status;
739 }
740
741
742 // ----------------------------------------------------------------------------
743 // Read the tile data from the file without decompression
ReadRawTile(unsigned long resolution,unsigned long whichTile,FPXCompressionOption * compressOption,unsigned char * compressQuality,long * compressSubtype,unsigned int * dataLength,void ** data)744 FPXStatus PFileFlashPixIO::ReadRawTile (
745 unsigned long resolution,
746 unsigned long whichTile,
747 FPXCompressionOption* compressOption,
748 unsigned char* compressQuality,
749 long* compressSubtype,
750 unsigned int* dataLength,
751 void** data)
752 {
753 FPXStatus status = FPX_OK;
754
755 if (resolution >= (unsigned long) nbSubImages)
756 status = FPX_INVALID_RESOLUTION;
757 else
758 status = ((PResolutionFlashPix*)(subImages[resolution]))->ReadRawTile (whichTile, compressOption, compressQuality, compressSubtype, dataLength, data);
759
760 return status;
761 }
762
763
764 // ----------------------------------------------------------------------------
765 // Write the tile data in the file without compression
WriteRawTile(unsigned long resolution,unsigned long whichTile,FPXCompressionOption compressOption,unsigned char compressQuality,long compressSubtype,unsigned int dataLength,void * data)766 FPXStatus PFileFlashPixIO::WriteRawTile (
767 unsigned long resolution,
768 unsigned long whichTile,
769 FPXCompressionOption compressOption,
770 unsigned char compressQuality,
771 long compressSubtype,
772 unsigned int dataLength,
773 void* data)
774 {
775 FPXStatus status = FPX_OK;
776
777 if (resolution >= (unsigned long) nbSubImages)
778 status = FPX_INVALID_RESOLUTION;
779 else
780 status = ((PResolutionFlashPix*)(subImages[resolution]))->WriteRawTile (whichTile, compressOption, compressQuality, compressSubtype, dataLength, data);
781
782 return status;
783 }
784
785
786 // ----------------------------------------------------------------------------
787 // Read path from the FPX file
788 // return noErr if everything fine (even if no path)
789 // path is allocated here with the correct size. It MUST be freed by the caller.
ReadPaths(data_Record ** thePath,int * nbRecords,int * theClipPathNum)790 OSErr PFileFlashPixIO::ReadPaths (data_Record** thePath, int* nbRecords, int* theClipPathNum)
791 {
792 // Call the parent: returns noErr if the path is already cached.
793 OSErr err = PHierarchicalImage::ReadPaths (thePath, nbRecords, theClipPathNum);
794 if (err == noErr)
795 return err;
796
797 // Path not implemented yet in FlashPix
798 path = NULL;
799 nbPaths = 0;
800 clipPathNum = 0;
801
802 // Update the path parameters, whatever has been done...
803 PHierarchicalImage::ReadPaths (thePath, nbRecords, theClipPathNum);
804
805 return noErr;
806 }
807
808
809 // ----------------------------------------------------------------------------
810 // Write the path in the FPX file
811 // return noErr if everything fine
WritePaths(data_Record * thePath,int nbRecords,int theClipPathNum)812 OSErr PFileFlashPixIO::WritePaths (data_Record* thePath, int nbRecords, int theClipPathNum)
813 {
814 // Store the path in the cached buffer. Return an error if memory problem.
815 OSErr err = PHierarchicalImage::WritePaths (thePath, nbRecords, theClipPathNum);
816 if (err != noErr)
817 goto end;
818
819 // Do nothing if no path (or absurd negative value)
820 if (nbPaths <= 0)
821 goto end;
822
823 // Path not implemented yet in FlashPix
824
825 end:
826 return err;
827 }
828
829
830 // ----------------------------------------------------------------------------
GetResolutionSize(short resolution,int * width,int * height)831 void PFileFlashPixIO::GetResolutionSize (short resolution, int* width, int* height)
832 {
833 int nbTilesWidth, nbTilesHeight;
834 subImages[resolution]->GetResolutionSizeInfo (width, height, &nbTilesWidth, &nbTilesHeight);
835 }
836
837
838 // ----------------------------------------------------------------------------
GetResolutionTileSize(short resolution,int * nbTilesWidth,int * nbTilesHeight)839 void PFileFlashPixIO::GetResolutionTileSize (short resolution, int* nbTilesWidth, int* nbTilesHeight)
840 {
841 int width, height;
842 subImages[resolution]->GetResolutionSizeInfo (&width, &height, nbTilesWidth, nbTilesHeight);
843 }
844
845
846 // ----------------------------------------------------------------------------
GetTileWidth()847 int PFileFlashPixIO::GetTileWidth()
848 {
849 return tileWidth;
850 }
851
852
853 // ----------------------------------------------------------------------------
SetCompressionSubType(long theCompressionSubType)854 void PFileFlashPixIO::SetCompressionSubType (long theCompressionSubType)
855 {
856 FPXCompressionSubType = theCompressionSubType;
857
858 // Set the compression subtype for each resolution
859 for ( int i = 0; i< nbSubImages; i++ ) {
860 ((PResolutionFlashPix *)subImages[i])->compressionSubtype = SET_JPEGTablesIndex(FPXCompressionSubType,
861 ((PResolutionFlashPix*)subImages[i])->compressTableGroup);
862 }
863 }
864
865
866 // ----------------------------------------------------------------------------
SetCompressTableGroup(long theCompressTableGroup)867 void PFileFlashPixIO::SetCompressTableGroup (long theCompressTableGroup)
868 {
869 // Set the jpeg table index for each resolution
870 for ( int i = 0; i< nbSubImages; i++ ) {
871 ((PResolutionFlashPix *)subImages[i])->compressTableGroup = (unsigned char) theCompressTableGroup;
872 ((PResolutionFlashPix *)subImages[i])->compressionSubtype = SET_JPEGTablesIndex(FPXCompressionSubType,
873 ((PResolutionFlashPix*)subImages[i])->compressTableGroup);
874 }
875 }
876
877
878 // ----------------------------------------------------------------------------
SetQualityFactor(unsigned char theQualityFactor)879 void PFileFlashPixIO::SetQualityFactor(unsigned char theQualityFactor)
880 {
881 FPXQualityFactor = theQualityFactor;
882
883 // Set the quality factor for each resolution
884 for ( int i = 0; i< nbSubImages; i++ )
885 ((PResolutionFlashPix *)subImages[i])->qualityFactor = FPXQualityFactor;
886
887 }
888
889
890 // ----------------------------------------------------------------------------
GetResolutionInfo(FPXResolution * FPXResoInfo,Boolean createdOnly)891 void PFileFlashPixIO::GetResolutionInfo(FPXResolution* FPXResoInfo, Boolean createdOnly)
892 {
893 if (createdOnly && nbCreatedResolutions != 0)
894 FPXResoInfo->numberOfResolutions = (short)nbCreatedResolutions;
895 else
896 FPXResoInfo->numberOfResolutions = (short)nbSubImages;
897
898 if ( FPXResoInfo->numberOfResolutions >= FPXMAXRESOLUTIONS )
899 FPXResoInfo->numberOfResolutions = FPXMAXRESOLUTIONS;
900
901 // Get the resolution info for each subimage
902 for ( int i = 0; i < FPXResoInfo->numberOfResolutions; i++ ) {
903 FPXResoInfo->compressionControl[i].compressOption = ((PResolutionFlashPix*)subImages[FPXResoInfo->numberOfResolutions - 1 - i])->compression;
904
905 // Convert the JPEG's quality factor to Kodak's
906 unsigned char qualityFactor = (unsigned char) ((255 - ((PResolutionFlashPix*)subImages[FPXResoInfo->numberOfResolutions - 1 - i])->qualityFactor) / 2.55);
907 FPXResoInfo->compressionControl[i].compressQuality = qualityFactor;
908 FPXResoInfo->compressionControl[i].compressTableGroup = ((PResolutionFlashPix*)subImages[FPXResoInfo->numberOfResolutions - 1 - i])->compressTableGroup;
909 }
910 }
911
912
913 // ----------------------------------------------------------------------------
SetResolutionInfo(FPXResolution * FPXResoInfo)914 void PFileFlashPixIO::SetResolutionInfo(FPXResolution* FPXResoInfo)
915 {
916 FPXResoInfo->numberOfResolutions = (FPXResoInfo->numberOfResolutions <= nbSubImages) ?
917 FPXResoInfo->numberOfResolutions : (short)nbSubImages;
918
919 // Set the resolution info for each subimage
920 for ( int i = 0; i< FPXResoInfo->numberOfResolutions; i++ ) {
921 ((PResolutionFlashPix*)subImages[i])->compression = FPXResoInfo->compressionControl[nbSubImages - 1 - i].compressOption;
922
923 // Convert the Kodak's quality factor to JPEG's
924 unsigned char qualityFactor = (unsigned char) (2.55 * (100 - FPXResoInfo->compressionControl[nbSubImages - 1 - i].compressQuality));
925 ((PResolutionFlashPix*)subImages[i])->qualityFactor = qualityFactor;
926 ((PResolutionFlashPix*)subImages[i])->compressTableGroup = FPXResoInfo->compressionControl[nbSubImages - 1 - i].compressTableGroup;
927
928 // Set compression subtype according to table index
929 ((PResolutionFlashPix*)subImages[i])->compressionSubtype = SET_JPEGTablesIndex(((PResolutionFlashPix*)subImages[i])->compressionSubtype,
930 ((PResolutionFlashPix*)subImages[i])->compressTableGroup);
931 }
932 }
933