]> granicus.if.org Git - imagemagick/blob - coders/dpx.c
(no commit message)
[imagemagick] / coders / dpx.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                            DDDD   PPPP   X   X                              %
7 %                            D   D  P   P   X X                               %
8 %                            D   D  PPPP    XXX                               %
9 %                            D   D  P       X X                               %
10 %                            DDDD   P      X   X                              %
11 %                                                                             %
12 %                                                                             %
13 %                     Read/Write SMTPE DPX Image Format                       %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                March 2001                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/blob-private.h"
45 #include "magick/cache.h"
46 #include "magick/colorspace.h"
47 #include "magick/exception.h"
48 #include "magick/exception-private.h"
49 #include "magick/geometry.h"
50 #include "magick/image.h"
51 #include "magick/image-private.h"
52 #include "magick/list.h"
53 #include "magick/magick.h"
54 #include "magick/memory_.h"
55 #include "magick/module.h"
56 #include "magick/monitor.h"
57 #include "magick/monitor-private.h"
58 #include "magick/option.h"
59 #include "magick/profile.h"
60 #include "magick/property.h"
61 #include "magick/quantum-private.h"
62 #include "magick/static.h"
63 #include "magick/string_.h"
64 #include "magick/string-private.h"
65 \f
66 /*
67   Typedef declaration.
68 */
69 typedef enum
70 {
71   UserDefinedColorimetric = 0,
72   PrintingDensityColorimetric = 1,
73   LinearColorimetric = 2,
74   LogarithmicColorimetric = 3,
75   UnspecifiedVideoColorimetric = 4,
76   SMTPE_274MColorimetric = 5,
77   ITU_R709Colorimetric = 6,
78   ITU_R601_625LColorimetric = 7,
79   ITU_R601_525LColorimetric = 8,
80   NTSCCompositeVideoColorimetric = 9,
81   PALCompositeVideoColorimetric = 10,
82   ZDepthLinearColorimetric = 11,
83   DepthHomogeneousColorimetric = 12
84 } DPXColorimetric;
85
86 typedef enum
87 {
88   UndefinedComponentType = 0,
89   RedComponentType = 1,
90   GreenComponentType = 2,
91   BlueComponentType = 3,
92   AlphaComponentType = 4,
93   LumaComponentType = 6,
94   ColorDifferenceCbCrComponentType = 7,
95   DepthComponentType = 8,
96   CompositeVideoComponentType = 9,
97   RGBComponentType = 50,
98   RGBAComponentType = 51,
99   ABGRComponentType = 52,
100   CbYCrY422ComponentType = 100,
101   CbYACrYA4224ComponentType = 101,
102   CbYCr444ComponentType = 102,
103   CbYCrA4444ComponentType = 103,
104   UserDef2ElementComponentType = 150,
105   UserDef3ElementComponentType = 151,
106   UserDef4ElementComponentType = 152,
107   UserDef5ElementComponentType = 153,
108   UserDef6ElementComponentType = 154,
109   UserDef7ElementComponentType = 155,
110   UserDef8ElementComponentType = 156
111 } DPXComponentType;
112
113 typedef struct _DPXFileInfo
114 {
115   unsigned int
116     magic,
117     image_offset;
118
119   char
120     version[8];
121
122   unsigned int
123     file_size,
124     ditto_key,
125     generic_size,
126     industry_size,
127     user_size;
128
129   char
130     filename[100],
131     timestamp[24],
132     creator[100],
133     project[200],
134     copyright[200];
135
136   unsigned int
137     encrypt_key;
138
139   char
140     reserve[104];
141 } DPXFileInfo;
142
143 typedef struct _DPXFilmInfo
144 {
145   char
146     id[2],
147     type[2],
148     offset[2],
149     prefix[6],
150     count[4],
151     format[32];
152
153   unsigned int
154     frame_position,
155     sequence_extent,
156     held_count;
157
158   float
159     frame_rate,
160     shutter_angle;
161
162   char
163     frame_id[32],
164     slate[100],
165     reserve[56];
166 } DPXFilmInfo;
167
168 typedef struct _DPXImageElement
169 {
170   unsigned int
171     data_sign,
172     low_data;
173
174   float
175     low_quantity;
176
177   unsigned int
178     high_data;
179
180   float
181     high_quantity;
182
183   unsigned char
184     descriptor,
185     transfer,
186     colorimetric,
187     bit_size;
188
189   unsigned short
190     packing,
191     encoding;
192
193   unsigned int
194     data_offset,
195     end_of_line_padding,
196     end_of_image_padding;
197
198   unsigned char
199     description[32];
200 } DPXImageElement;
201
202 typedef struct _DPXImageInfo
203 {
204   unsigned short
205     orientation,
206     number_elements;
207
208   unsigned int
209     pixels_per_line,
210     lines_per_element;
211
212   DPXImageElement
213     image_element[8];
214
215   unsigned char
216     reserve[52];
217 } DPXImageInfo;
218
219 typedef struct _DPXOrientationInfo
220 {
221   unsigned int
222     x_offset,
223     y_offset;
224
225   float
226     x_center,
227     y_center;
228
229   unsigned int
230     x_size,
231     y_size;
232
233   char
234     filename[100],
235     timestamp[24],
236     device[32],
237     serial[32];
238
239   unsigned short
240     border[4];
241
242   unsigned int
243     aspect_ratio[2];
244
245   unsigned char
246     reserve[28];
247 } DPXOrientationInfo;
248
249 typedef struct _DPXTelevisionInfo
250 {
251   unsigned int
252     time_code,
253     user_bits;
254
255   unsigned char
256     interlace,
257     field_number,
258     video_signal,
259     padding;
260
261   float
262     horizontal_sample_rate,
263     vertical_sample_rate,
264     frame_rate,
265     time_offset,
266     gamma,
267     black_level,
268     black_gain,
269     break_point,
270     white_level,
271     integration_times;
272
273   char
274     reserve[76];
275 } DPXTelevisionInfo;
276
277 typedef struct _DPXUserInfo
278 {
279   char
280     id[32];
281 } DPXUserInfo;
282
283 typedef struct DPXInfo
284 {
285   DPXFileInfo
286     file;
287
288   DPXImageInfo
289     image;
290
291   DPXOrientationInfo
292     orientation;
293
294   DPXFilmInfo
295     film;
296
297   DPXTelevisionInfo
298     television;
299
300   DPXUserInfo
301     user;
302 } DPXInfo;
303 \f
304 /*
305   Forward declaractions.
306 */
307 static MagickBooleanType
308   WriteDPXImage(const ImageInfo *,Image *);
309 \f
310 /*
311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
312 %                                                                             %
313 %                                                                             %
314 %                                                                             %
315 %   I s D P X                                                                 %
316 %                                                                             %
317 %                                                                             %
318 %                                                                             %
319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
320 %
321 %  IsDPX() returns MagickTrue if the image format type, identified by the
322 %  magick string, is DPX.
323 %
324 %  The format of the IsDPX method is:
325 %
326 %      MagickBooleanType IsDPX(const unsigned char *magick,const size_t extent)
327 %
328 %  A description of each parameter follows:
329 %
330 %    o magick: compare image format pattern against these bytes.
331 %
332 %    o extent: Specifies the extent of the magick string.
333 %
334 */
335 static MagickBooleanType IsDPX(const unsigned char *magick,const size_t extent)
336 {
337   if (extent < 4)
338     return(MagickFalse);
339   if (memcmp(magick,"SDPX",4) == 0)
340     return(MagickTrue);
341   if (memcmp(magick,"XPDS",4) == 0)
342     return(MagickTrue);
343   return(MagickFalse);
344 }
345 \f
346 /*
347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
348 %                                                                             %
349 %                                                                             %
350 %                                                                             %
351 %   R e a d D P X I m a g e                                                   %
352 %                                                                             %
353 %                                                                             %
354 %                                                                             %
355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
356 %
357 %  ReadDPXImage() reads an DPX X image file and returns it.  It
358 %  allocates the memory necessary for the new Image structure and returns a
359 %  pointer to the new image.
360 %
361 %  The format of the ReadDPXImage method is:
362 %
363 %      Image *ReadDPXImage(const ImageInfo *image_info,ExceptionInfo *exception)
364 %
365 %  A description of each parameter follows:
366 %
367 %    o image_info: the image info.
368 %
369 %    o exception: return any errors or warnings in this structure.
370 %
371 */
372
373 static size_t GetBytesPerRow(unsigned long columns,
374   unsigned long samples_per_pixel,unsigned long bits_per_pixel,
375   MagickBooleanType pad)
376 {
377   size_t
378     bytes_per_row;
379
380   switch (bits_per_pixel)
381   {
382     case 1:
383     {
384       bytes_per_row=4*(((size_t) samples_per_pixel*columns*
385         bits_per_pixel+31)/32);
386       break;
387     }
388     case 8:
389     default:
390     {
391       bytes_per_row=4*(((size_t) samples_per_pixel*columns*
392         bits_per_pixel+31)/32);
393       break;
394     }
395     case 10:
396     {
397       if (pad == MagickFalse)
398         {
399           bytes_per_row=4*(((size_t) samples_per_pixel*columns*
400             bits_per_pixel+31)/32);
401           break;
402         }
403       bytes_per_row=4*(((size_t) (32*((samples_per_pixel*columns+2)/3))+31)/32);
404       break;
405     }
406     case 12:
407     {
408       if (pad == MagickFalse)
409         {
410           bytes_per_row=4*(((size_t) samples_per_pixel*columns*
411             bits_per_pixel+31)/32);
412           break;
413         }
414       bytes_per_row=2*(((size_t) (16*samples_per_pixel*columns)+15)/16);
415       break;
416     }
417     case 16:
418     {
419       bytes_per_row=2*(((size_t) samples_per_pixel*columns*
420         bits_per_pixel+8)/16);
421       break;
422     }
423     case 32:
424     {
425       bytes_per_row=4*(((size_t) samples_per_pixel*columns*
426         bits_per_pixel+31)/32);
427       break;
428     }
429     case 64:
430     {
431       bytes_per_row=8*(((size_t) samples_per_pixel*columns*
432         bits_per_pixel+63)/64);
433       break;
434     }
435   }
436   return(bytes_per_row);
437 }
438
439 static inline MagickBooleanType IsFloatDefined(const float value)
440 {
441   union
442   {
443     unsigned int
444       unsigned_value;
445
446     float
447       float_value;
448   } quantum;
449
450   quantum.unsigned_value=0U;
451   quantum.float_value=(double) value;
452   if (quantum.unsigned_value == 0U)
453     return(MagickFalse);
454   return(MagickTrue);
455 }
456
457 static void SetPrimaryChromaticity(const DPXColorimetric colorimetric,
458   ChromaticityInfo *chromaticity_info)
459 {
460   switch(colorimetric)
461   {
462     case SMTPE_274MColorimetric:
463     case ITU_R709Colorimetric:
464     {
465       chromaticity_info->red_primary.x=0.640;
466       chromaticity_info->red_primary.y=0.330;
467       chromaticity_info->red_primary.z=0.030;
468       chromaticity_info->green_primary.x=0.300;
469       chromaticity_info->green_primary.y=0.600;
470       chromaticity_info->green_primary.z=0.100;
471       chromaticity_info->blue_primary.x=0.150;
472       chromaticity_info->blue_primary.y=0.060;
473       chromaticity_info->blue_primary.z=0.790;
474       chromaticity_info->white_point.x=0.3127;
475       chromaticity_info->white_point.y=0.3290;
476       chromaticity_info->white_point.z=0.3582;
477       break;
478     }
479     case NTSCCompositeVideoColorimetric:
480     {
481       chromaticity_info->red_primary.x=0.67;
482       chromaticity_info->red_primary.y=0.33;
483       chromaticity_info->red_primary.z=0.00;
484       chromaticity_info->green_primary.x=0.21;
485       chromaticity_info->green_primary.y=0.71;
486       chromaticity_info->green_primary.z=0.08;
487       chromaticity_info->blue_primary.x=0.14;
488       chromaticity_info->blue_primary.y=0.08;
489       chromaticity_info->blue_primary.z=0.78;
490       chromaticity_info->white_point.x=0.310;
491       chromaticity_info->white_point.y=0.316;
492       chromaticity_info->white_point.z=0.374;
493       break;
494     }
495     case PALCompositeVideoColorimetric:
496     {
497       chromaticity_info->red_primary.x=0.640;
498       chromaticity_info->red_primary.y=0.330;
499       chromaticity_info->red_primary.z=0.030;
500       chromaticity_info->green_primary.x=0.290;
501       chromaticity_info->green_primary.y=0.600;
502       chromaticity_info->green_primary.z=0.110;
503       chromaticity_info->blue_primary.x=0.150;
504       chromaticity_info->blue_primary.y=0.060;
505       chromaticity_info->blue_primary.z=0.790;
506       chromaticity_info->white_point.x=0.3127;
507       chromaticity_info->white_point.y=0.3290;
508       chromaticity_info->white_point.z=0.3582;
509       break;
510     }
511     default:
512       break;
513   }
514 }
515
516 static void TimeCodeToString(const unsigned long timestamp,char *code)
517 {
518 #define TimeFields  7
519
520   unsigned int
521     shift;
522
523   register long
524     i;
525
526   *code='\0';
527   shift=4*TimeFields;
528   for (i=0; i <= TimeFields; i++)
529   {
530     (void) FormatMagickString(code,MaxTextExtent-strlen(code),"%x",
531       (unsigned int) ((timestamp >> shift) & 0x0fU));
532     code++;
533     if (((i % 2) != 0) && (i < TimeFields))
534       *code++=':';
535     shift-=4;
536     *code='\0';
537   }
538 }
539
540 static Image *ReadDPXImage(const ImageInfo *image_info,ExceptionInfo *exception)
541 {
542   char
543     magick[4],
544     value[MaxTextExtent];
545
546   DPXInfo
547     dpx;
548
549   Image
550     *image;
551
552   long
553     row,
554     y;
555
556   MagickBooleanType
557     status;
558
559   MagickOffsetType
560     offset;
561
562   QuantumInfo
563     *quantum_info;
564
565   QuantumType
566     quantum_type;
567
568   register long
569     i;
570
571   ssize_t
572     count;
573
574   size_t
575     extent;
576
577   unsigned char
578     component_type;
579
580   unsigned long
581     samples_per_pixel;
582
583   /*
584     Open image file.
585   */
586   assert(image_info != (const ImageInfo *) NULL);
587   assert(image_info->signature == MagickSignature);
588   if (image_info->debug != MagickFalse)
589     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
590       image_info->filename);
591   assert(exception != (ExceptionInfo *) NULL);
592   assert(exception->signature == MagickSignature);
593   image=AcquireImage(image_info);
594   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
595   if (status == MagickFalse)
596     {
597       image=DestroyImageList(image);
598       return((Image *) NULL);
599     }
600   /*
601     Read DPX file header.
602   */
603   offset=0;
604   count=ReadBlob(image,4,(unsigned char *) magick);
605   offset+=count;
606   if ((count != 4) || ((LocaleNCompare(magick,"SDPX",4) != 0) &&
607       (LocaleNCompare((char *) magick,"XPDS",4) != 0)))
608     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
609   image->endian=LSBEndian;
610   if (LocaleNCompare(magick,"SDPX",4) == 0)
611     image->endian=MSBEndian;
612   (void) ResetMagickMemory(&dpx,0,sizeof(dpx));
613   dpx.file.image_offset=ReadBlobLong(image);
614   offset+=4;
615   offset+=ReadBlob(image,sizeof(dpx.file.version),(unsigned char *)
616     dpx.file.version);
617   (void) FormatImageProperty(image,"dpx:file.version","%.8s",dpx.file.version);
618   dpx.file.file_size=ReadBlobLong(image);
619   offset+=4;
620   dpx.file.ditto_key=ReadBlobLong(image);
621   offset+=4;
622   if (dpx.file.ditto_key != ~0U)
623     (void) FormatImageProperty(image,"dpx:file.ditto.key","%u",
624       dpx.file.ditto_key);
625   dpx.file.generic_size=ReadBlobLong(image);
626   offset+=4;
627   dpx.file.industry_size=ReadBlobLong(image);
628   offset+=4;
629   dpx.file.user_size=ReadBlobLong(image);
630   offset+=4;
631   offset+=ReadBlob(image,sizeof(dpx.file.filename),(unsigned char *)
632     dpx.file.filename);
633   (void) FormatImageProperty(image,"dpx:file.filename","%.100s",
634     dpx.file.filename);
635   (void) FormatImageProperty(image,"document","%.100s",dpx.file.filename);
636   offset+=ReadBlob(image,sizeof(dpx.file.timestamp),(unsigned char *)
637     dpx.file.timestamp);
638   if (*dpx.file.timestamp != '\0')
639     (void) FormatImageProperty(image,"dpx:file.timestamp","%.24s",
640       dpx.file.timestamp);
641   offset+=ReadBlob(image,sizeof(dpx.file.creator),(unsigned char *)
642     dpx.file.creator);
643   if (*dpx.file.creator != '\0')
644     {
645       (void) FormatImageProperty(image,"dpx:file.creator","%.100s",
646         dpx.file.creator);
647       (void) FormatImageProperty(image,"software","%.100s",dpx.file.creator);
648     }
649   offset+=ReadBlob(image,sizeof(dpx.file.project),(unsigned char *)
650     dpx.file.project);
651   if (*dpx.file.project != '\0')
652     {
653       (void) FormatImageProperty(image,"dpx:file.project","%.200s",
654         dpx.file.project);
655       (void) FormatImageProperty(image,"comment","%.100s",dpx.file.project);
656     }
657   offset+=ReadBlob(image,sizeof(dpx.file.copyright),(unsigned char *)
658     dpx.file.copyright);
659   if (*dpx.file.copyright != '\0')
660     {
661       (void) FormatImageProperty(image,"dpx:file.copyright","%.200s",
662         dpx.file.copyright);
663       (void) FormatImageProperty(image,"copyright","%.100s",
664         dpx.file.copyright);
665     }
666   dpx.file.encrypt_key=ReadBlobLong(image);
667   offset+=4;
668   if (dpx.file.encrypt_key != ~0U)
669     (void) FormatImageProperty(image,"dpx:file.encrypt_key","%u",
670       dpx.file.encrypt_key);
671   offset+=ReadBlob(image,sizeof(dpx.file.reserve),(unsigned char *)
672     dpx.file.reserve);
673   /*
674     Read DPX image header.
675   */
676   dpx.image.orientation=ReadBlobShort(image);
677   offset+=2;
678   if (dpx.image.orientation != (unsigned short) (~0U))
679     (void) FormatImageProperty(image,"dpx:image.orientation","%d",
680       dpx.image.orientation);
681   switch (dpx.image.orientation)
682   {
683     default:
684     case 0:  image->orientation=TopLeftOrientation; break;
685     case 1:  image->orientation=TopRightOrientation; break;
686     case 2:  image->orientation=BottomLeftOrientation; break;
687     case 3:  image->orientation=BottomRightOrientation; break;
688     case 4:  image->orientation=LeftTopOrientation; break;
689     case 5:  image->orientation=RightTopOrientation; break;
690     case 6:  image->orientation=LeftBottomOrientation; break;
691     case 7:  image->orientation=RightBottomOrientation; break;
692   }
693   dpx.image.number_elements=ReadBlobShort(image);
694   offset+=2;
695   dpx.image.pixels_per_line=ReadBlobLong(image);
696   offset+=4;
697   image->columns=dpx.image.pixels_per_line;
698   dpx.image.lines_per_element=ReadBlobLong(image);
699   offset+=4;
700   image->rows=dpx.image.lines_per_element;
701   for (i=0; i < 8; i++)
702   {
703     dpx.image.image_element[i].data_sign=ReadBlobLong(image);
704     offset+=4;
705     dpx.image.image_element[i].low_data=ReadBlobLong(image);
706     offset+=4;
707     dpx.image.image_element[i].low_quantity=ReadBlobFloat(image);
708     offset+=4;
709     dpx.image.image_element[i].high_data=ReadBlobLong(image);
710     offset+=4;
711     dpx.image.image_element[i].high_quantity=ReadBlobFloat(image);
712     offset+=4;
713     dpx.image.image_element[i].descriptor=(unsigned char) ReadBlobByte(image);
714     offset++;
715     dpx.image.image_element[i].transfer=(unsigned char) ReadBlobByte(image);
716     offset++;
717     dpx.image.image_element[i].colorimetric=(unsigned char) ReadBlobByte(image);
718     offset++;
719     dpx.image.image_element[i].bit_size=(unsigned char) ReadBlobByte(image);
720     offset++;
721     dpx.image.image_element[i].packing=ReadBlobShort(image);
722     offset+=2;
723     dpx.image.image_element[i].encoding=ReadBlobShort(image);
724     offset+=2;
725     dpx.image.image_element[i].data_offset=ReadBlobLong(image);
726     offset+=4;
727     dpx.image.image_element[i].end_of_line_padding=ReadBlobLong(image);
728     offset+=4;
729     dpx.image.image_element[i].end_of_image_padding=ReadBlobLong(image);
730     offset+=4;
731     offset+=ReadBlob(image,sizeof(dpx.image.image_element[i].description),
732       (unsigned char *) dpx.image.image_element[i].description);
733   }
734   SetPrimaryChromaticity((DPXColorimetric)
735     dpx.image.image_element[0].colorimetric,&image->chromaticity);
736   offset+=ReadBlob(image,sizeof(dpx.image.reserve),(unsigned char *)
737     dpx.image.reserve);
738   component_type=dpx.image.image_element[0].descriptor;
739   image->depth=dpx.image.image_element[0].bit_size;
740   if (dpx.file.image_offset >= 1664U)
741     {
742       /*
743         Read DPX orientation header.
744       */
745       dpx.orientation.x_offset=ReadBlobLong(image);
746       offset+=4;
747       if (dpx.orientation.x_offset != ~0U)
748         (void) FormatImageProperty(image,"dpx:orientation.x_offset","%u",
749           dpx.orientation.x_offset);
750       dpx.orientation.y_offset=ReadBlobLong(image);
751       offset+=4;
752       if (dpx.orientation.y_offset != ~0U)
753         (void) FormatImageProperty(image,"dpx:orientation.y_offset","%u",
754           dpx.orientation.y_offset);
755       dpx.orientation.x_center=ReadBlobFloat(image);
756       offset+=4;
757       if (IsFloatDefined(dpx.orientation.x_center) != MagickFalse)
758         (void) FormatImageProperty(image,"dpx:orientation.x_center","%g",
759           dpx.orientation.x_center);
760       dpx.orientation.y_center=ReadBlobFloat(image);
761       offset+=4;
762       if (IsFloatDefined(dpx.orientation.y_center) != MagickFalse)
763         (void) FormatImageProperty(image,"dpx:orientation.y_center","%g",
764           dpx.orientation.y_center);
765       dpx.orientation.x_size=ReadBlobLong(image);
766       offset+=4;
767       if (dpx.orientation.x_size != ~0U)
768         (void) FormatImageProperty(image,"dpx:orientation.x_size","%u",
769           dpx.orientation.x_size);
770       dpx.orientation.y_size=ReadBlobLong(image);
771       offset+=4;
772       if (dpx.orientation.y_size != ~0U)
773         (void) FormatImageProperty(image,"dpx:orientation.y_size","%u",
774           dpx.orientation.y_size);
775       offset+=ReadBlob(image,sizeof(dpx.orientation.filename),(unsigned char *)
776         dpx.orientation.filename);
777       if (*dpx.orientation.filename != '\0')
778         (void) FormatImageProperty(image,"dpx:orientation.filename","%.100s",
779           dpx.orientation.filename);
780       offset+=ReadBlob(image,sizeof(dpx.orientation.timestamp),(unsigned char *)
781         dpx.orientation.timestamp);
782       if (*dpx.orientation.timestamp != '\0')
783         (void) FormatImageProperty(image,"dpx:orientation.timestamp","%.24s",
784           dpx.orientation.timestamp);
785       offset+=ReadBlob(image,sizeof(dpx.orientation.device),(unsigned char *)
786         dpx.orientation.device);
787       if (*dpx.orientation.device != '\0')
788         (void) FormatImageProperty(image,"dpx:orientation.device","%.32s",
789           dpx.orientation.device);
790       offset+=ReadBlob(image,sizeof(dpx.orientation.serial),(unsigned char *)
791         dpx.orientation.serial);
792       if (*dpx.orientation.serial != '\0')
793         (void) FormatImageProperty(image,"dpx:orientation.serial","%.32s",
794           dpx.orientation.serial);
795       for (i=0; i < 4; i++)
796       {
797         dpx.orientation.border[i]=ReadBlobShort(image);
798         offset+=2;
799       }
800       if ((dpx.orientation.border[0] != (unsigned short) (~0U)) &&
801           (dpx.orientation.border[1] != (unsigned short) (~0U)))
802         (void) FormatImageProperty(image,"dpx:orientation.border","%dx%d%+d%+d",          dpx.orientation.border[0],dpx.orientation.border[1],
803           dpx.orientation.border[2],dpx.orientation.border[3]);
804       for (i=0; i < 2; i++)
805       {
806         dpx.orientation.aspect_ratio[i]=ReadBlobLong(image);
807         offset+=4;
808       }
809       if ((dpx.orientation.aspect_ratio[0] != ~0U) &&
810           (dpx.orientation.aspect_ratio[1] != ~0U))
811         (void) FormatImageProperty(image,"dpx:orientation.aspect_ratio",
812           "%ux%u",dpx.orientation.aspect_ratio[0],
813           dpx.orientation.aspect_ratio[1]);
814       offset+=ReadBlob(image,sizeof(dpx.orientation.reserve),(unsigned char *)
815         dpx.orientation.reserve);
816     }
817   if (dpx.file.image_offset >= 1920U)
818     {
819       /*
820         Read DPX film header.
821       */
822       offset+=ReadBlob(image,sizeof(dpx.film.id),(unsigned char *) dpx.film.id);
823       if (*dpx.film.type != '\0')
824         (void) FormatImageProperty(image,"dpx:film.id","%.2s",dpx.film.id);
825       offset+=ReadBlob(image,sizeof(dpx.film.type),(unsigned char *)
826         dpx.film.type);
827       if (*dpx.film.type != '\0')
828         (void) FormatImageProperty(image,"dpx:film.type","%.2s",dpx.film.type);
829       offset+=ReadBlob(image,sizeof(dpx.film.offset),(unsigned char *)
830         dpx.film.offset);
831       if (*dpx.film.offset != '\0')
832         (void) FormatImageProperty(image,"dpx:film.offset","%.2s",
833           dpx.film.offset);
834       offset+=ReadBlob(image,sizeof(dpx.film.prefix),(unsigned char *)
835         dpx.film.prefix);
836       if (*dpx.film.prefix != '\0')
837         (void) FormatImageProperty(image,"dpx:film.prefix","%.6s",
838           dpx.film.prefix);
839       offset+=ReadBlob(image,sizeof(dpx.film.count),(unsigned char *)
840         dpx.film.count);
841       if (*dpx.film.count != '\0')
842         (void) FormatImageProperty(image,"dpx:film.count","%.4s",
843           dpx.film.count);
844       offset+=ReadBlob(image,sizeof(dpx.film.format),(unsigned char *)
845         dpx.film.format);
846       if (*dpx.film.format != '\0')
847         (void) FormatImageProperty(image,"dpx:film.format","%.4s",
848           dpx.film.format);
849       dpx.film.frame_position=ReadBlobLong(image);
850       offset+=4;
851       if (dpx.film.frame_position != ~0U)
852         (void) FormatImageProperty(image,"dpx:film.frame_position","%u",
853           dpx.film.frame_position);
854       dpx.film.sequence_extent=ReadBlobLong(image);
855       offset+=4;
856       if (dpx.film.sequence_extent != ~0U)
857         (void) FormatImageProperty(image,"dpx:film.sequence_extent","%u",
858           dpx.film.sequence_extent);
859       dpx.film.held_count=ReadBlobLong(image);
860       offset+=4;
861       if (dpx.film.held_count != ~0U)
862         (void) FormatImageProperty(image,"dpx:film.held_count","%u",
863           dpx.film.held_count);
864       dpx.film.frame_rate=ReadBlobFloat(image);
865       offset+=4;
866       if (IsFloatDefined(dpx.film.frame_rate) != MagickFalse)
867         (void) FormatImageProperty(image,"dpx:film.frame_rate","%g",
868           dpx.film.frame_rate);
869       dpx.film.shutter_angle=ReadBlobFloat(image);
870       offset+=4;
871       if (IsFloatDefined(dpx.film.shutter_angle) != MagickFalse)
872         (void) FormatImageProperty(image,"dpx:film.shutter_angle","%g",
873           dpx.film.shutter_angle);
874       offset+=ReadBlob(image,sizeof(dpx.film.frame_id),(unsigned char *)
875         dpx.film.frame_id);
876       if (*dpx.film.frame_id != '\0')
877         (void) FormatImageProperty(image,"dpx:film.frame_id","%.32s",
878           dpx.film.frame_id);
879       offset+=ReadBlob(image,sizeof(dpx.film.slate),(unsigned char *)
880         dpx.film.slate);
881       if (*dpx.film.slate != '\0')
882         (void) FormatImageProperty(image,"dpx:film.slate","%.100s",
883           dpx.film.slate);
884       offset+=ReadBlob(image,sizeof(dpx.film.reserve),(unsigned char *)
885         dpx.film.reserve);
886     }
887   if (dpx.file.image_offset >= 2048U)
888     {
889       /*
890         Read DPX television header.
891       */
892       dpx.television.time_code=(unsigned int) ReadBlobLong(image);
893       offset+=4;
894       TimeCodeToString(dpx.television.time_code,value);
895       (void) SetImageProperty(image,"dpx:television.time.code",value);
896       dpx.television.user_bits=(unsigned int) ReadBlobLong(image);
897       offset+=4;
898       TimeCodeToString(dpx.television.user_bits,value);
899       (void) SetImageProperty(image,"dpx:television.user.bits",value);
900       dpx.television.interlace=(unsigned char) ReadBlobByte(image);
901       offset++;
902       if (dpx.television.interlace != 0)
903         (void) FormatImageProperty(image,"dpx:television.interlace","%ld",(long)
904           dpx.television.interlace);
905       dpx.television.field_number=(unsigned char) ReadBlobByte(image);
906       offset++;
907       if (dpx.television.field_number != 0)
908         (void) FormatImageProperty(image,"dpx:television.field_number","%ld",
909           (long) dpx.television.field_number);
910       dpx.television.video_signal=(unsigned char) ReadBlobByte(image);
911       offset++;
912       if (dpx.television.video_signal != 0)
913         (void) FormatImageProperty(image,"dpx:television.video_signal","%ld",
914           (long) dpx.television.video_signal);
915       dpx.television.padding=(unsigned char) ReadBlobByte(image);
916       offset++;
917       if (dpx.television.padding != 0)
918         (void) FormatImageProperty(image,"dpx:television.padding","%d",
919           dpx.television.padding);
920       dpx.television.horizontal_sample_rate=ReadBlobFloat(image);
921       offset+=4;
922       if (IsFloatDefined(dpx.television.horizontal_sample_rate) != MagickFalse)
923         (void) FormatImageProperty(image,
924           "dpx:television.horizontal_sample_rate","%g",
925           dpx.television.horizontal_sample_rate);
926       dpx.television.vertical_sample_rate=ReadBlobFloat(image);
927       offset+=4;
928       if (IsFloatDefined(dpx.television.vertical_sample_rate) != MagickFalse)
929         (void) FormatImageProperty(image,"dpx:television.vertical_sample_rate",
930           "%g",dpx.television.vertical_sample_rate);
931       dpx.television.frame_rate=ReadBlobFloat(image);
932       offset+=4;
933       if (IsFloatDefined(dpx.television.frame_rate) != MagickFalse)
934         (void) FormatImageProperty(image,"dpx:television.frame_rate","%g",
935           dpx.television.frame_rate);
936       dpx.television.time_offset=ReadBlobFloat(image);
937       offset+=4;
938       if (IsFloatDefined(dpx.television.time_offset) != MagickFalse)
939         (void) FormatImageProperty(image,"dpx:television.time_offset","%g",
940           dpx.television.time_offset);
941       dpx.television.gamma=ReadBlobFloat(image);
942       offset+=4;
943       if (IsFloatDefined(dpx.television.gamma) != MagickFalse)
944         (void) FormatImageProperty(image,"dpx:television.gamma","%g",
945           dpx.television.gamma);
946       dpx.television.black_level=ReadBlobFloat(image);
947       offset+=4;
948       if (IsFloatDefined(dpx.television.black_level) != MagickFalse)
949         (void) FormatImageProperty(image,"dpx:television.black_level","%g",
950           dpx.television.black_level);
951       dpx.television.black_gain=ReadBlobFloat(image);
952       offset+=4;
953       if (IsFloatDefined(dpx.television.black_gain) != MagickFalse)
954         (void) FormatImageProperty(image,"dpx:television.black_gain","%g",
955           dpx.television.black_gain);
956       dpx.television.break_point=ReadBlobFloat(image);
957       offset+=4;
958       if (IsFloatDefined(dpx.television.break_point) != MagickFalse)
959         (void) FormatImageProperty(image,"dpx:television.break_point","%g",
960           dpx.television.break_point);
961       dpx.television.white_level=ReadBlobFloat(image);
962       offset+=4;
963       if (IsFloatDefined(dpx.television.white_level) != MagickFalse)
964         (void) FormatImageProperty(image,"dpx:television.white_level","%g",
965           dpx.television.white_level);
966       dpx.television.integration_times=ReadBlobFloat(image);
967       offset+=4;
968       if (IsFloatDefined(dpx.television.integration_times) != MagickFalse)
969         (void) FormatImageProperty(image,"dpx:television.integration_times",
970           "%g",dpx.television.integration_times);
971       offset+=ReadBlob(image,sizeof(dpx.television.reserve),(unsigned char *)
972         dpx.television.reserve);
973     }
974   if (dpx.file.image_offset > 2080U)
975     {
976       /*
977         Read DPX user header.
978       */
979       offset+=ReadBlob(image,sizeof(dpx.user.id),(unsigned char *) dpx.user.id);
980       if (*dpx.user.id != '\0')
981         (void) FormatImageProperty(image,"dpx:user.id","%.32s",dpx.user.id);
982       if ((dpx.file.user_size != ~0U) &&
983           ((size_t) dpx.file.user_size > sizeof(dpx.user.id)))
984         {
985           StringInfo
986             *profile;
987
988            profile=AcquireStringInfo(dpx.file.user_size);
989            offset+=ReadBlob(image,GetStringInfoLength(profile),
990              GetStringInfoDatum(profile));
991            (void) SetImageProfile(image,"dpx",profile);
992            profile=DestroyStringInfo(profile);
993         }
994     }
995   for ( ; offset < (long) dpx.file.image_offset; offset++)
996     (void) ReadBlobByte(image);
997   /*
998     Read DPX image header.
999   */
1000   if (image_info->ping != MagickFalse)
1001     {
1002       (void) CloseBlob(image);
1003       return(GetFirstImageInList(image));
1004     }
1005   /*
1006     Convert DPX raster image to pixel packets.
1007   */
1008   samples_per_pixel=1;
1009   quantum_type=GrayQuantum;
1010   switch (component_type)
1011   {
1012     case CbYCrY422ComponentType:
1013     {
1014       samples_per_pixel=2;
1015       quantum_type=CbYCrYQuantum;
1016       break;
1017     }
1018     case CbYACrYA4224ComponentType:
1019     case CbYCr444ComponentType:
1020     {
1021       samples_per_pixel=3;
1022       quantum_type=CbYCrQuantum;
1023       break;
1024     }
1025     case RGBComponentType:
1026     {
1027       samples_per_pixel=3;
1028       quantum_type=RGBQuantum;
1029       break;
1030     }
1031     case ABGRComponentType:
1032     case RGBAComponentType:
1033     {
1034       image->matte=MagickTrue;
1035       samples_per_pixel=4;
1036       quantum_type=RGBAQuantum;
1037       break;
1038     }
1039     default:
1040       break;
1041   }
1042   switch (component_type)
1043   {
1044     case CbYCrY422ComponentType:
1045     case CbYACrYA4224ComponentType:
1046     case CbYCr444ComponentType:
1047     {
1048       image->colorspace=Rec709YCbCrColorspace;
1049       break;
1050     }
1051     case LumaComponentType:
1052     {
1053       image->colorspace=RGBColorspace;
1054       break;
1055     }
1056     default:
1057     {
1058       image->colorspace=RGBColorspace;
1059       if (dpx.image.image_element[0].transfer == LogarithmicColorimetric)
1060         image->colorspace=LogColorspace;
1061       if (dpx.image.image_element[0].transfer == PrintingDensityColorimetric)
1062         image->colorspace=LogColorspace;
1063       break;
1064     }
1065   }
1066   extent=GetBytesPerRow(image->columns,samples_per_pixel,image->depth,
1067     dpx.image.image_element[0].packing == 0 ? MagickFalse : MagickTrue);
1068   /*
1069     DPX any-bit pixel format.
1070   */
1071   status=MagickTrue;
1072   row=0;
1073   quantum_info=AcquireQuantumInfo(image_info,image);
1074   if (quantum_info == (QuantumInfo *) NULL)
1075     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1076   SetQuantumQuantum(quantum_info,32);
1077   SetQuantumPack(quantum_info,dpx.image.image_element[0].packing == 0 ?
1078     MagickTrue : MagickFalse);
1079   for (y=0; y < (long) image->rows; y++)
1080   {
1081     long
1082       offset;
1083
1084     MagickBooleanType
1085       sync;
1086
1087     register PixelPacket
1088       *q;
1089
1090     ssize_t
1091       count;
1092
1093     size_t
1094       length;
1095
1096     unsigned char
1097       *pixels;
1098
1099     if (status == MagickFalse)
1100       continue;
1101     pixels=GetQuantumPixels(quantum_info);
1102     {
1103       count=ReadBlob(image,extent,pixels);
1104       if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1105           (image->previous == (Image *) NULL))
1106         {
1107           MagickBooleanType
1108             proceed;
1109
1110           proceed=SetImageProgress(image,LoadImageTag,row,image->rows);
1111           if (proceed == MagickFalse)
1112             status=MagickFalse;
1113         }
1114       offset=row++;
1115     }
1116     if (count != (ssize_t) extent)
1117       status=MagickFalse;
1118     q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
1119     if (q == (PixelPacket *) NULL)
1120       {
1121         status=MagickFalse;
1122         continue;
1123       }
1124     length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1125       quantum_type,pixels,exception);
1126     sync=SyncAuthenticPixels(image,exception);
1127     if (sync == MagickFalse)
1128       status=MagickFalse;
1129   }
1130   quantum_info=DestroyQuantumInfo(quantum_info);
1131   if (status == MagickFalse)
1132     ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1133   SetQuantumImageType(image,quantum_type);
1134   if (EOFBlob(image) != MagickFalse)
1135     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1136       image->filename);
1137   (void) CloseBlob(image);
1138   return(GetFirstImageInList(image));
1139 }
1140 \f
1141 /*
1142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1143 %                                                                             %
1144 %                                                                             %
1145 %                                                                             %
1146 %   R e g i s t e r D P X I m a g e                                           %
1147 %                                                                             %
1148 %                                                                             %
1149 %                                                                             %
1150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1151 %
1152 %  RegisterDPXImage() adds properties for the DPX image format to
1153 %  the list of supported formats.  The properties include the image format
1154 %  tag, a method to read and/or write the format, whether the format
1155 %  supports the saving of more than one frame to the same file or blob,
1156 %  whether the format supports native in-memory I/O, and a brief
1157 %  description of the format.
1158 %
1159 %  The format of the RegisterDPXImage method is:
1160 %
1161 %      unsigned long RegisterDPXImage(void)
1162 %
1163 */
1164 ModuleExport unsigned long RegisterDPXImage(void)
1165 {
1166   MagickInfo
1167     *entry;
1168
1169   static const char
1170     *DPXNote =
1171     {
1172       "Digital Moving Picture Exchange Bitmap, Version 2.0.\n"
1173       "See SMPTE 268M-2003 specification at http://www.smtpe.org\n"
1174     };
1175
1176   entry=SetMagickInfo("DPX");
1177   entry->decoder=(DecodeImageHandler *) ReadDPXImage;
1178   entry->encoder=(EncodeImageHandler *) WriteDPXImage;
1179   entry->magick=(IsImageFormatHandler *) IsDPX;
1180   entry->adjoin=MagickFalse;
1181   entry->description=ConstantString("SMPTE 268M-2003 (DPX 2.0)");
1182   entry->note=ConstantString(DPXNote);
1183   entry->module=ConstantString("DPX");
1184   (void) RegisterMagickInfo(entry);
1185   return(MagickImageCoderSignature);
1186 }
1187 \f
1188 /*
1189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1190 %                                                                             %
1191 %                                                                             %
1192 %                                                                             %
1193 %   U n r e g i s t e r D P X I m a g e                                       %
1194 %                                                                             %
1195 %                                                                             %
1196 %                                                                             %
1197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1198 %
1199 %  UnregisterDPXImage() removes format registrations made by the
1200 %  DPX module from the list of supported formats.
1201 %
1202 %  The format of the UnregisterDPXImage method is:
1203 %
1204 %      UnregisterDPXImage(void)
1205 %
1206 */
1207 ModuleExport void UnregisterDPXImage(void)
1208 {
1209   (void) UnregisterMagickInfo("DPX");
1210 }
1211 \f
1212 /*
1213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1214 %                                                                             %
1215 %                                                                             %
1216 %                                                                             %
1217 %   W r i t e D P X I m a g e                                                 %
1218 %                                                                             %
1219 %                                                                             %
1220 %                                                                             %
1221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1222 %
1223 %  WriteDPXImage() writes an image in DPX encoded image format.
1224 %
1225 %  The format of the WriteDPXImage method is:
1226 %
1227 %      MagickBooleanType WriteDPXImage(const ImageInfo *image_info,Image *image)
1228 %
1229 %  A description of each parameter follows.
1230 %
1231 %    o image_info: the image info.
1232 %
1233 %    o image:  The image.
1234 %
1235 */
1236
1237 static inline const char *GetDPXProperty(const ImageInfo *image_info,
1238   const Image *image,const char *property)
1239 {
1240   const char
1241     *value;
1242
1243   value=GetImageOption(image_info,property);
1244   if (value != (const char *) NULL)
1245     return(value);
1246   return(GetImageProperty(image,property));
1247 }
1248
1249 static unsigned int StringToTimeCode(const char *key)
1250 {
1251   char
1252     buffer[2];
1253
1254   register long
1255     i;
1256
1257   unsigned int
1258     shift,
1259     value;
1260
1261   value=0;
1262   shift=28;
1263   buffer[1]='\0';
1264   for (i=0; (*key != 0) && (i < 11); i++)
1265   {
1266     if (isxdigit((int) ((unsigned char) *key)) == 0)
1267       {
1268         key++;
1269         continue;
1270       }
1271     buffer[0]=(*key++);
1272     value|=(unsigned int) ((strtol(buffer,(char **) NULL,16)) << shift);
1273     shift-=4;
1274   }
1275   return(value);
1276 }
1277
1278 static MagickBooleanType WriteDPXImage(const ImageInfo *image_info,Image *image)
1279 {
1280   const char
1281     *value;
1282
1283   const StringInfo
1284     *profile;
1285
1286   DPXInfo
1287     dpx;
1288
1289   long
1290     horizontal_factor,
1291     vertical_factor,
1292     y;
1293
1294   MagickBooleanType
1295     status;
1296
1297   MagickOffsetType
1298     offset;
1299
1300   MagickStatusType
1301     flags;
1302
1303   GeometryInfo
1304     geometry_info;
1305
1306   QuantumInfo
1307     *quantum_info;
1308
1309   QuantumType
1310     quantum_type;
1311
1312   register const PixelPacket
1313     *p;
1314
1315   register long
1316     i;
1317
1318   size_t
1319     extent;
1320
1321   ssize_t
1322     count;
1323
1324   time_t
1325     seconds;
1326
1327   unsigned char
1328     *pixels;
1329
1330   /*
1331     Open output image file.
1332   */
1333   assert(image_info != (const ImageInfo *) NULL);
1334   assert(image_info->signature == MagickSignature);
1335   assert(image != (Image *) NULL);
1336   assert(image->signature == MagickSignature);
1337   if (image->debug != MagickFalse)
1338     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1339   horizontal_factor=4;
1340   vertical_factor=4;
1341   if (image_info->sampling_factor != (char *) NULL)
1342     {
1343       GeometryInfo
1344         geometry_info;
1345
1346       MagickStatusType
1347         flags;
1348
1349       flags=ParseGeometry(image_info->sampling_factor,&geometry_info);
1350       horizontal_factor=(long) geometry_info.rho;
1351       vertical_factor=(long) geometry_info.sigma;
1352       if ((flags & SigmaValue) == 0)
1353         vertical_factor=horizontal_factor;
1354       if ((horizontal_factor != 1) && (horizontal_factor != 2) &&
1355           (horizontal_factor != 4) && (vertical_factor != 1) &&
1356           (vertical_factor != 2) && (vertical_factor != 4))
1357         ThrowWriterException(CorruptImageError,"UnexpectedSamplingFactor");
1358     }
1359   if ((image->colorspace == YCbCrColorspace) &&
1360       ((horizontal_factor == 2) || (vertical_factor == 2)))
1361     if ((image->columns % 2) != 0)
1362       image->columns++;
1363   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1364   if (status == MagickFalse)
1365     return(status);
1366   /*
1367     Write file header.
1368   */
1369   (void) ResetMagickMemory(&dpx,0,sizeof(dpx));
1370   offset=0;
1371   dpx.file.magic=0x53445058U;
1372   offset+=WriteBlobLong(image,dpx.file.magic);
1373   dpx.file.image_offset=0x2000U;
1374   profile=GetImageProfile(image,"dpx");
1375   if (profile != (StringInfo *) NULL)
1376     {
1377       if (GetStringInfoLength(profile) > 1048576)
1378         ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1379       dpx.file.image_offset+=(unsigned int) GetStringInfoLength(profile);
1380       dpx.file.image_offset=(((dpx.file.image_offset+0x2000-1)/0x2000)*0x2000);
1381     }
1382   offset+=WriteBlobLong(image,dpx.file.image_offset);
1383   (void) strncpy(dpx.file.version,"V2.0",sizeof(dpx.file.version));
1384   offset+=WriteBlob(image,8,(unsigned char *) &dpx.file.version);
1385   dpx.file.file_size=(unsigned int) (4U*image->columns*image->rows+
1386     dpx.file.image_offset);
1387   offset+=WriteBlobLong(image,dpx.file.file_size);
1388   dpx.file.ditto_key=1U;  /* new frame */
1389   offset+=WriteBlobLong(image,dpx.file.ditto_key);
1390   dpx.file.generic_size=0x00000680U;
1391   offset+=WriteBlobLong(image,dpx.file.generic_size);
1392   dpx.file.industry_size=0x00000180U;
1393   offset+=WriteBlobLong(image,dpx.file.industry_size);
1394   dpx.file.user_size=0;
1395   if (profile != (StringInfo *) NULL)
1396     {
1397       dpx.file.user_size+=(unsigned int) GetStringInfoLength(profile);
1398       dpx.file.user_size=(((dpx.file.user_size+0x2000-1)/0x2000)*0x2000);
1399     }
1400   offset+=WriteBlobLong(image,dpx.file.user_size);
1401   value=GetDPXProperty(image_info,image,"dpx:file.filename");
1402   if (value != (const char *) NULL)
1403     (void) strncpy(dpx.file.filename,value,sizeof(dpx.file.filename));
1404   offset+=WriteBlob(image,sizeof(dpx.file.filename),(unsigned char *)
1405     dpx.file.filename);
1406   seconds=time((time_t *) NULL);
1407   (void) FormatMagickTime(seconds,sizeof(dpx.file.timestamp),
1408     dpx.file.timestamp);
1409   offset+=WriteBlob(image,sizeof(dpx.file.timestamp),(unsigned char *)
1410     dpx.file.timestamp);
1411   (void) strncpy(dpx.file.creator,GetMagickVersion((unsigned long *) NULL),
1412     sizeof(dpx.file.creator));
1413   value=GetDPXProperty(image_info,image,"dpx:file.creator");
1414   if (value != (const char *) NULL)
1415     (void) strncpy(dpx.file.creator,value,sizeof(dpx.file.creator));
1416   offset+=WriteBlob(image,sizeof(dpx.file.creator),(unsigned char *)
1417     dpx.file.creator);
1418   value=GetDPXProperty(image_info,image,"dpx:file.project");
1419   if (value != (const char *) NULL)
1420     (void) strncpy(dpx.file.project,value,sizeof(dpx.file.project));
1421   offset+=WriteBlob(image,sizeof(dpx.file.project),(unsigned char *)
1422     dpx.file.project);
1423   value=GetDPXProperty(image_info,image,"dpx:file.copyright");
1424   if (value != (const char *) NULL)
1425     (void) strncpy(dpx.file.copyright,value,
1426       sizeof(dpx.file.copyright));
1427   offset+=WriteBlob(image,sizeof(dpx.file.copyright),(unsigned char *)
1428     dpx.file.copyright);
1429   dpx.file.encrypt_key=(~0U);
1430   offset+=WriteBlobLong(image,dpx.file.encrypt_key);
1431   offset+=WriteBlob(image,sizeof(dpx.file.reserve),(unsigned char *)
1432     dpx.file.reserve);
1433   /*
1434     Write image header.
1435   */
1436   dpx.image.orientation=0x00;  /* left-to-right; top-to-bottom */
1437   offset+=WriteBlobShort(image,dpx.image.orientation);
1438   dpx.image.number_elements=1;
1439   offset+=WriteBlobShort(image,dpx.image.number_elements);
1440   if ((image->columns != (unsigned int) image->columns) ||
1441       (image->rows != (unsigned int) image->rows))
1442     ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1443   offset+=WriteBlobLong(image,(unsigned int) image->columns);
1444   offset+=WriteBlobLong(image,(unsigned int) image->rows);
1445   for (i=0; i < 8; i++)
1446   {
1447     dpx.image.image_element[i].data_sign=0U;
1448     offset+=WriteBlobLong(image,dpx.image.image_element[i].data_sign);
1449     dpx.image.image_element[i].low_data=0U;
1450     offset+=WriteBlobLong(image,dpx.image.image_element[i].low_data);
1451     dpx.image.image_element[i].low_quantity=0.0f;
1452     offset+=WriteBlobFloat(image,dpx.image.image_element[i].low_quantity);
1453     dpx.image.image_element[i].high_data=0U;
1454     offset+=WriteBlobLong(image,dpx.image.image_element[i].high_data);
1455     dpx.image.image_element[i].high_quantity=0.0f;
1456     offset+=WriteBlobFloat(image,dpx.image.image_element[i].high_quantity);
1457     dpx.image.image_element[i].descriptor=0;
1458     if (i == 0)
1459       switch (image->colorspace)
1460       {
1461         case Rec601YCbCrColorspace:
1462         case Rec709YCbCrColorspace:
1463         case YCbCrColorspace:
1464         {
1465           dpx.image.image_element[i].descriptor=CbYCr444ComponentType;
1466           if (image->matte != MagickFalse)
1467             dpx.image.image_element[i].descriptor=CbYCrA4444ComponentType;
1468           break;
1469         }
1470         default:
1471         {
1472           dpx.image.image_element[i].descriptor=RGBComponentType;
1473           if (image->matte != MagickFalse)
1474             dpx.image.image_element[i].descriptor=RGBAComponentType;
1475           if ((image_info->type != TrueColorType) &&
1476               (image->matte == MagickFalse) &&
1477               (IsGrayImage(image,&image->exception) != MagickFalse))
1478             dpx.image.image_element[i].descriptor=LumaComponentType;
1479           break;
1480         }
1481       }
1482     offset+=WriteBlobByte(image,dpx.image.image_element[i].descriptor);
1483     dpx.image.image_element[i].transfer=0;
1484     if (image->colorspace == LogColorspace)
1485       dpx.image.image_element[0].transfer=PrintingDensityColorimetric;
1486     offset+=WriteBlobByte(image,dpx.image.image_element[i].transfer);
1487     dpx.image.image_element[i].colorimetric=0;
1488     offset+=WriteBlobByte(image,dpx.image.image_element[i].colorimetric);
1489     dpx.image.image_element[i].bit_size=0;
1490     if (i == 0)
1491       dpx.image.image_element[i].bit_size=(unsigned char) image->depth;
1492     offset+=WriteBlobByte(image,dpx.image.image_element[i].bit_size);
1493     dpx.image.image_element[i].packing=0;
1494     if ((image->depth == 10) || (image->depth == 12))
1495       dpx.image.image_element[i].packing=1;
1496     offset+=WriteBlobShort(image,dpx.image.image_element[i].packing);
1497     dpx.image.image_element[i].encoding=0;
1498     offset+=WriteBlobShort(image,dpx.image.image_element[i].encoding);
1499     dpx.image.image_element[i].data_offset=0U;
1500     if (i == 0)
1501       dpx.image.image_element[i].data_offset=dpx.file.image_offset;
1502     offset+=WriteBlobLong(image,dpx.image.image_element[i].data_offset);
1503     dpx.image.image_element[i].end_of_line_padding=0U;
1504     offset+=WriteBlobLong(image,dpx.image.image_element[i].end_of_line_padding);
1505     offset+=WriteBlobLong(image,
1506       dpx.image.image_element[i].end_of_image_padding);
1507     offset+=WriteBlob(image,sizeof(dpx.image.image_element[i].description),
1508       (unsigned char *) dpx.image.image_element[i].description);
1509   }
1510   offset+=WriteBlob(image,sizeof(dpx.image.reserve),(unsigned char *)
1511     dpx.image.reserve);
1512   /*
1513     Write orientation header.
1514   */
1515   if ((image->rows != image->magick_rows) ||
1516       (image->columns != image->magick_columns))
1517     {
1518       /*
1519         These properties are not valid if image size changed.
1520       */
1521       (void) DeleteImageProperty(image,"dpx:orientation.x_offset");
1522       (void) DeleteImageProperty(image,"dpx:orientation.y_offset");
1523       (void) DeleteImageProperty(image,"dpx:orientation.x_center");
1524       (void) DeleteImageProperty(image,"dpx:orientation.y_center");
1525       (void) DeleteImageProperty(image,"dpx:orientation.x_size");
1526       (void) DeleteImageProperty(image,"dpx:orientation.y_size");
1527     }
1528   dpx.orientation.x_offset=0U;
1529   value=GetDPXProperty(image_info,image,"dpx:orientation.x_offset");
1530   if (value != (const char *) NULL)
1531     dpx.orientation.x_offset=(unsigned int) StringToUnsignedLong(value);
1532   offset+=WriteBlobLong(image,dpx.orientation.x_offset);
1533   dpx.orientation.y_offset=0U;
1534   value=GetDPXProperty(image_info,image,"dpx:orientation.y_offset");
1535   if (value != (const char *) NULL)
1536     dpx.orientation.y_offset=(unsigned int) StringToUnsignedLong(value);
1537   offset+=WriteBlobLong(image,dpx.orientation.y_offset);
1538   dpx.orientation.x_center=0.0f;
1539   value=GetDPXProperty(image_info,image,"dpx:orientation.x_center");
1540   if (value != (const char *) NULL)
1541     dpx.orientation.x_center=StringToDouble(value);
1542   offset+=WriteBlobFloat(image,dpx.orientation.x_center);
1543   dpx.orientation.y_center=0.0f;
1544   value=GetDPXProperty(image_info,image,"dpx:orientation.y_center");
1545   if (value != (const char *) NULL)
1546     dpx.orientation.y_center=StringToDouble(value);
1547   offset+=WriteBlobFloat(image,dpx.orientation.y_center);
1548   dpx.orientation.x_size=0U;
1549   value=GetDPXProperty(image_info,image,"dpx:orientation.x_size");
1550   if (value != (const char *) NULL)
1551     dpx.orientation.x_size=(unsigned int) StringToUnsignedLong(value);
1552   offset+=WriteBlobLong(image,dpx.orientation.x_size);
1553   dpx.orientation.y_size=0U;
1554   value=GetDPXProperty(image_info,image,"dpx:orientation.y_size");
1555   if (value != (const char *) NULL)
1556     dpx.orientation.y_size=(unsigned int) StringToUnsignedLong(value);
1557   offset+=WriteBlobLong(image,dpx.orientation.y_size);
1558   value=GetDPXProperty(image_info,image,"dpx:orientation.filename");
1559   if (value != (const char *) NULL)
1560     (void) strncpy(dpx.orientation.filename,value,
1561       sizeof(dpx.orientation.filename));
1562   offset+=WriteBlob(image,sizeof(dpx.orientation.filename),(unsigned char *)
1563     dpx.orientation.filename);
1564   offset+=WriteBlob(image,sizeof(dpx.orientation.timestamp),(unsigned char *)
1565     dpx.orientation.timestamp);
1566   value=GetDPXProperty(image_info,image,"dpx:orientation.device");
1567   if (value != (const char *) NULL)
1568     (void) strncpy(dpx.orientation.device,value,sizeof(dpx.orientation.device));
1569   offset+=WriteBlob(image,sizeof(dpx.orientation.device),(unsigned char *)
1570     dpx.orientation.device);
1571   value=GetDPXProperty(image_info,image,"dpx:orientation.serial");
1572   if (value != (const char *) NULL)
1573     (void) strncpy(dpx.orientation.serial,value,sizeof(dpx.orientation.serial));
1574   offset+=WriteBlob(image,sizeof(dpx.orientation.serial),(unsigned char *)
1575     dpx.orientation.serial);
1576   for (i=0; i < 4; i++)
1577     dpx.orientation.border[i]=0;
1578   value=GetDPXProperty(image_info,image,"dpx:orientation.border");
1579   if (value != (const char *) NULL)
1580     {
1581       flags=ParseGeometry(value,&geometry_info);
1582       if ((flags & SigmaValue) == 0)
1583         geometry_info.sigma=geometry_info.rho;
1584       dpx.orientation.border[0]=(unsigned short) (geometry_info.rho+0.5);
1585       dpx.orientation.border[1]=(unsigned short) (geometry_info.sigma+0.5);
1586       dpx.orientation.border[2]=(unsigned short) (geometry_info.xi+0.5);
1587       dpx.orientation.border[3]=(unsigned short) (geometry_info.psi+0.5);
1588     }
1589   for (i=0; i < 4; i++)
1590     offset+=WriteBlobShort(image,dpx.orientation.border[i]);
1591   for (i=0; i < 2; i++)
1592     dpx.orientation.aspect_ratio[i]=0U;
1593   value=GetDPXProperty(image_info,image,"dpx:orientation.aspect_ratio");
1594   if (value != (const char *) NULL)
1595     {
1596       flags=ParseGeometry(value,&geometry_info);
1597       if ((flags & SigmaValue) == 0)
1598         geometry_info.sigma=geometry_info.rho;
1599       dpx.orientation.aspect_ratio[0]=(unsigned int) (geometry_info.rho+0.5);
1600       dpx.orientation.aspect_ratio[1]=(unsigned int) (geometry_info.sigma+0.5);
1601     }
1602   for (i=0; i < 2; i++)
1603     offset+=WriteBlobLong(image,dpx.orientation.aspect_ratio[i]);
1604   offset+=WriteBlob(image,sizeof(dpx.orientation.reserve),(unsigned char *)
1605     dpx.orientation.reserve);
1606   /*
1607     Write film header.
1608   */
1609   *dpx.film.id='\0';
1610   value=GetDPXProperty(image_info,image,"dpx:film.id");
1611   if (value != (const char *) NULL)
1612     (void) strncpy(dpx.film.id,value,sizeof(dpx.film.id));
1613   offset+=WriteBlob(image,sizeof(dpx.film.id),(unsigned char *) dpx.film.id);
1614   *dpx.film.type='\0';
1615   value=GetDPXProperty(image_info,image,"dpx:film.type");
1616   if (value != (const char *) NULL)
1617     (void) strncpy(dpx.film.type,value,sizeof(dpx.film.type));
1618   offset+=WriteBlob(image,sizeof(dpx.film.type),(unsigned char *)
1619     dpx.film.type);
1620   *dpx.film.offset='\0';
1621   value=GetDPXProperty(image_info,image,"dpx:film.offset");
1622   if (value != (const char *) NULL)
1623     (void) strncpy(dpx.film.offset,value,sizeof(dpx.film.offset));
1624   offset+=WriteBlob(image,sizeof(dpx.film.offset),(unsigned char *)
1625     dpx.film.offset);
1626   *dpx.film.prefix='\0';
1627   value=GetDPXProperty(image_info,image,"dpx:film.prefix");
1628   if (value != (const char *) NULL)
1629     (void) strncpy(dpx.film.prefix,value,sizeof(dpx.film.prefix));
1630   offset+=WriteBlob(image,sizeof(dpx.film.prefix),(unsigned char *)
1631     dpx.film.prefix);
1632   *dpx.film.count='\0';
1633   value=GetDPXProperty(image_info,image,"dpx:film.count");
1634   if (value != (const char *) NULL)
1635     (void) strncpy(dpx.film.count,value,sizeof(dpx.film.count));
1636   offset+=WriteBlob(image,sizeof(dpx.film.count),(unsigned char *)
1637     dpx.film.count);
1638   *dpx.film.format='\0';
1639   value=GetDPXProperty(image_info,image,"dpx:film.format");
1640   if (value != (const char *) NULL)
1641     (void) strncpy(dpx.film.format,value,sizeof(dpx.film.format));
1642   offset+=WriteBlob(image,sizeof(dpx.film.format),(unsigned char *)
1643     dpx.film.format);
1644   dpx.film.frame_position=0U;
1645   value=GetDPXProperty(image_info,image,"dpx:film.frame_position");
1646   if (value != (const char *) NULL)
1647     dpx.film.frame_position=(unsigned int) StringToUnsignedLong(value);
1648   offset+=WriteBlobLong(image,dpx.film.frame_position);
1649   dpx.film.sequence_extent=0U;
1650   value=GetDPXProperty(image_info,image,"dpx:film.sequence_extent");
1651   if (value != (const char *) NULL)
1652     dpx.film.sequence_extent=(unsigned int) StringToUnsignedLong(value);
1653   offset+=WriteBlobLong(image,dpx.film.sequence_extent);
1654   dpx.film.held_count=0U;
1655   value=GetDPXProperty(image_info,image,"dpx:film.held_count");
1656   if (value != (const char *) NULL)
1657     dpx.film.held_count=(unsigned int) StringToUnsignedLong(value);
1658   offset+=WriteBlobLong(image,dpx.film.held_count);
1659   dpx.film.frame_rate=0.0f;
1660   value=GetDPXProperty(image_info,image,"dpx:film.frame_rate");
1661   if (value != (const char *) NULL)
1662     dpx.film.frame_rate=StringToDouble(value);
1663   offset+=WriteBlobFloat(image,dpx.film.frame_rate);
1664   dpx.film.shutter_angle=0.0f;
1665   value=GetDPXProperty(image_info,image,"dpx:film.shutter_angle");
1666   if (value != (const char *) NULL)
1667     dpx.film.shutter_angle=StringToDouble(value);
1668   offset+=WriteBlobFloat(image,dpx.film.shutter_angle);
1669   *dpx.film.frame_id='\0';
1670   value=GetDPXProperty(image_info,image,"dpx:film.frame_id");
1671   if (value != (const char *) NULL)
1672     (void) strncpy(dpx.film.frame_id,value,sizeof(dpx.film.frame_id));
1673   offset+=WriteBlob(image,sizeof(dpx.film.frame_id),(unsigned char *)
1674     dpx.film.frame_id);
1675   value=GetDPXProperty(image_info,image,"dpx:film.slate");
1676   if (value != (const char *) NULL)
1677     (void) strncpy(dpx.film.slate,value,sizeof(dpx.film.slate));
1678   offset+=WriteBlob(image,sizeof(dpx.film.slate),(unsigned char *)
1679     dpx.film.slate);
1680   offset+=WriteBlob(image,sizeof(dpx.film.reserve),(unsigned char *)
1681     dpx.film.reserve);
1682   /*
1683     Write television header.
1684   */
1685   value=GetDPXProperty(image_info,image,"dpx:television.time.code");
1686   if (value != (const char *) NULL)
1687     dpx.television.time_code=StringToTimeCode(value);
1688   offset+=WriteBlobLong(image,dpx.television.time_code);
1689   value=GetDPXProperty(image_info,image,"dpx:television.user.bits");
1690   if (value != (const char *) NULL)
1691     dpx.television.user_bits=StringToTimeCode(value);
1692   offset+=WriteBlobLong(image,dpx.television.user_bits);
1693   value=GetDPXProperty(image_info,image,"dpx:television.interlace");
1694   if (value != (const char *) NULL)
1695     dpx.television.interlace=(unsigned char) StringToLong(value);
1696   offset+=WriteBlobByte(image,dpx.television.interlace);
1697   value=GetDPXProperty(image_info,image,"dpx:television.field_number");
1698   if (value != (const char *) NULL)
1699     dpx.television.field_number=(unsigned char) StringToLong(value);
1700   offset+=WriteBlobByte(image,dpx.television.field_number);
1701   dpx.television.video_signal=0;
1702   value=GetDPXProperty(image_info,image,"dpx:television.video_signal");
1703   if (value != (const char *) NULL)
1704     dpx.television.video_signal=(unsigned char) StringToLong(value);
1705   offset+=WriteBlobByte(image,dpx.television.video_signal);
1706   dpx.television.padding=0;
1707   value=GetDPXProperty(image_info,image,"dpx:television.padding");
1708   if (value != (const char *) NULL)
1709     dpx.television.padding=(unsigned char) StringToLong(value);
1710   offset+=WriteBlobByte(image,dpx.television.padding);
1711   dpx.television.horizontal_sample_rate=0.0f;
1712   value=GetDPXProperty(image_info,image,
1713     "dpx:television.horizontal_sample_rate");
1714   if (value != (const char *) NULL)
1715     dpx.television.horizontal_sample_rate=StringToDouble(value);
1716   offset+=WriteBlobFloat(image,dpx.television.horizontal_sample_rate);
1717   dpx.television.vertical_sample_rate=0.0f;
1718   value=GetDPXProperty(image_info,image,"dpx:television.vertical_sample_rate");
1719   if (value != (const char *) NULL)
1720     dpx.television.vertical_sample_rate=StringToDouble(value);
1721   offset+=WriteBlobFloat(image,dpx.television.vertical_sample_rate);
1722   dpx.television.frame_rate=0.0f;
1723   value=GetDPXProperty(image_info,image,"dpx:television.frame_rate");
1724   if (value != (const char *) NULL)
1725     dpx.television.frame_rate=StringToDouble(value);
1726   offset+=WriteBlobFloat(image,dpx.television.frame_rate);
1727   dpx.television.time_offset=0.0f;
1728   value=GetDPXProperty(image_info,image,"dpx:television.time_offset");
1729   if (value != (const char *) NULL)
1730     dpx.television.time_offset=StringToDouble(value);
1731   offset+=WriteBlobFloat(image,dpx.television.time_offset);
1732   dpx.television.gamma=0.0f;
1733   value=GetDPXProperty(image_info,image,"dpx:television.gamma");
1734   if (value != (const char *) NULL)
1735     dpx.television.gamma=StringToDouble(value);
1736   offset+=WriteBlobFloat(image,dpx.television.gamma);
1737   dpx.television.black_level=0.0f;
1738   value=GetDPXProperty(image_info,image,"dpx:television.black_level");
1739   if (value != (const char *) NULL)
1740     dpx.television.black_level=StringToDouble(value);
1741   offset+=WriteBlobFloat(image,dpx.television.black_level);
1742   dpx.television.black_gain=0.0f;
1743   value=GetDPXProperty(image_info,image,"dpx:television.black_gain");
1744   if (value != (const char *) NULL)
1745     dpx.television.black_gain=StringToDouble(value);
1746   offset+=WriteBlobFloat(image,dpx.television.black_gain);
1747   dpx.television.break_point=0.0f;
1748   value=GetDPXProperty(image_info,image,"dpx:television.break_point");
1749   if (value != (const char *) NULL)
1750     dpx.television.break_point=StringToDouble(value);
1751   offset+=WriteBlobFloat(image,dpx.television.break_point);
1752   dpx.television.white_level=0.0f;
1753   value=GetDPXProperty(image_info,image,"dpx:television.white_level");
1754   if (value != (const char *) NULL)
1755     dpx.television.white_level=StringToDouble(value);
1756   offset+=WriteBlobFloat(image,dpx.television.white_level);
1757   dpx.television.integration_times=0.0f;
1758   value=GetDPXProperty(image_info,image,"dpx:television.integration_times");
1759   if (value != (const char *) NULL)
1760     dpx.television.integration_times=StringToDouble(value);
1761   offset+=WriteBlobFloat(image,dpx.television.integration_times);
1762   offset+=WriteBlob(image,sizeof(dpx.television.reserve),(unsigned char *)
1763     dpx.television.reserve);
1764   /*
1765     Write user header.
1766   */
1767   value=GetDPXProperty(image_info,image,"dpx:user.id");
1768   if (value != (const char *) NULL)
1769     (void) strncpy(dpx.user.id,value,sizeof(dpx.user.id));
1770   offset+=WriteBlob(image,sizeof(dpx.user.id),(unsigned char *) dpx.user.id);
1771   if (profile != (StringInfo *) NULL)
1772     offset+=WriteBlob(image,GetStringInfoLength(profile),
1773       GetStringInfoDatum(profile));
1774   while (offset < (MagickOffsetType) dpx.image.image_element[0].data_offset)
1775   {
1776     count=WriteBlobByte(image,0x00);
1777     if (count != 1)
1778       {
1779         ThrowFileException(&image->exception,FileOpenError,"UnableToWriteFile",
1780           image->filename);
1781         break;
1782       }
1783     offset+=count;
1784   }
1785   /*
1786     Convert pixel packets to DPX raster image.
1787   */
1788   quantum_info=AcquireQuantumInfo(image_info,image);
1789   SetQuantumQuantum(quantum_info,32);
1790   SetQuantumPack(quantum_info,dpx.image.image_element[0].packing == 0 ?
1791     MagickTrue : MagickFalse);
1792   quantum_type=RGBQuantum;
1793   if (image->matte != MagickFalse)
1794     quantum_type=RGBAQuantum;
1795   if (image->colorspace == YCbCrColorspace)
1796     {
1797       quantum_type=CbYCrQuantum;
1798       if (image->matte != MagickFalse)
1799         quantum_type=CbYCrAQuantum;
1800       if ((horizontal_factor == 2) || (vertical_factor == 2))
1801         quantum_type=CbYCrYQuantum;
1802     }
1803   extent=GetBytesPerRow(image->columns,image->matte != MagickFalse ? 4UL : 3UL,
1804     image->depth,MagickTrue);
1805   if ((image_info->type != TrueColorType) && (image->matte == MagickFalse) &&
1806       (IsGrayImage(image,&image->exception) != MagickFalse))
1807     {
1808       quantum_type=GrayQuantum;
1809       extent=GetBytesPerRow(image->columns,1UL,image->depth,MagickTrue);
1810     }
1811   pixels=GetQuantumPixels(quantum_info);
1812   for (y=0; y < (long) image->rows; y++)
1813   {
1814     p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1815     if (p == (const PixelPacket *) NULL)
1816       break;
1817     (void) ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1818       quantum_type,pixels,&image->exception);
1819     count=WriteBlob(image,extent,pixels);
1820     if (count != (ssize_t) extent)
1821       break;
1822     status=SetImageProgress(image,SaveImageTag,y,image->rows);
1823     if (status == MagickFalse)
1824       break;
1825   }
1826   quantum_info=DestroyQuantumInfo(quantum_info);
1827   (void) CloseBlob(image);
1828   return(status);
1829 }