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