]> 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(size_t columns,
374   size_t samples_per_pixel,size_t 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 size_t timestamp,char *code)
517 {
518 #define TimeFields  7
519
520   unsigned int
521     shift;
522
523   register ssize_t
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   ssize_t
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 ssize_t
569     i;
570
571   ssize_t
572     count;
573
574   size_t
575     extent;
576
577   unsigned char
578     component_type;
579
580   size_t
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",
904           (long) 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 < (ssize_t) 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 < (ssize_t) image->rows; y++)
1080   {
1081     ssize_t
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,(MagickOffsetType) row,
1111                 image->rows);
1112           if (proceed == MagickFalse)
1113             status=MagickFalse;
1114         }
1115       offset=row++;
1116     }
1117     if (count != (ssize_t) extent)
1118       status=MagickFalse;
1119     q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
1120     if (q == (PixelPacket *) NULL)
1121       {
1122         status=MagickFalse;
1123         continue;
1124       }
1125     length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1126       quantum_type,pixels,exception);
1127     sync=SyncAuthenticPixels(image,exception);
1128     if (sync == MagickFalse)
1129       status=MagickFalse;
1130   }
1131   quantum_info=DestroyQuantumInfo(quantum_info);
1132   if (status == MagickFalse)
1133     ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1134   SetQuantumImageType(image,quantum_type);
1135   if (EOFBlob(image) != MagickFalse)
1136     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1137       image->filename);
1138   (void) CloseBlob(image);
1139   return(GetFirstImageInList(image));
1140 }
1141 \f
1142 /*
1143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1144 %                                                                             %
1145 %                                                                             %
1146 %                                                                             %
1147 %   R e g i s t e r D P X I m a g e                                           %
1148 %                                                                             %
1149 %                                                                             %
1150 %                                                                             %
1151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1152 %
1153 %  RegisterDPXImage() adds properties for the DPX image format to
1154 %  the list of supported formats.  The properties include the image format
1155 %  tag, a method to read and/or write the format, whether the format
1156 %  supports the saving of more than one frame to the same file or blob,
1157 %  whether the format supports native in-memory I/O, and a brief
1158 %  description of the format.
1159 %
1160 %  The format of the RegisterDPXImage method is:
1161 %
1162 %      size_t RegisterDPXImage(void)
1163 %
1164 */
1165 ModuleExport size_t RegisterDPXImage(void)
1166 {
1167   MagickInfo
1168     *entry;
1169
1170   static const char
1171     *DPXNote =
1172     {
1173       "Digital Moving Picture Exchange Bitmap, Version 2.0.\n"
1174       "See SMPTE 268M-2003 specification at http://www.smtpe.org\n"
1175     };
1176
1177   entry=SetMagickInfo("DPX");
1178   entry->decoder=(DecodeImageHandler *) ReadDPXImage;
1179   entry->encoder=(EncodeImageHandler *) WriteDPXImage;
1180   entry->magick=(IsImageFormatHandler *) IsDPX;
1181   entry->adjoin=MagickFalse;
1182   entry->description=ConstantString("SMPTE 268M-2003 (DPX 2.0)");
1183   entry->note=ConstantString(DPXNote);
1184   entry->module=ConstantString("DPX");
1185   (void) RegisterMagickInfo(entry);
1186   return(MagickImageCoderSignature);
1187 }
1188 \f
1189 /*
1190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1191 %                                                                             %
1192 %                                                                             %
1193 %                                                                             %
1194 %   U n r e g i s t e r D P X I m a g e                                       %
1195 %                                                                             %
1196 %                                                                             %
1197 %                                                                             %
1198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1199 %
1200 %  UnregisterDPXImage() removes format registrations made by the
1201 %  DPX module from the list of supported formats.
1202 %
1203 %  The format of the UnregisterDPXImage method is:
1204 %
1205 %      UnregisterDPXImage(void)
1206 %
1207 */
1208 ModuleExport void UnregisterDPXImage(void)
1209 {
1210   (void) UnregisterMagickInfo("DPX");
1211 }
1212 \f
1213 /*
1214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1215 %                                                                             %
1216 %                                                                             %
1217 %                                                                             %
1218 %   W r i t e D P X I m a g e                                                 %
1219 %                                                                             %
1220 %                                                                             %
1221 %                                                                             %
1222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1223 %
1224 %  WriteDPXImage() writes an image in DPX encoded image format.
1225 %
1226 %  The format of the WriteDPXImage method is:
1227 %
1228 %      MagickBooleanType WriteDPXImage(const ImageInfo *image_info,Image *image)
1229 %
1230 %  A description of each parameter follows.
1231 %
1232 %    o image_info: the image info.
1233 %
1234 %    o image:  The image.
1235 %
1236 */
1237
1238 static inline const char *GetDPXProperty(const ImageInfo *image_info,
1239   const Image *image,const char *property)
1240 {
1241   const char
1242     *value;
1243
1244   value=GetImageOption(image_info,property);
1245   if (value != (const char *) NULL)
1246     return(value);
1247   return(GetImageProperty(image,property));
1248 }
1249
1250 static unsigned int StringToTimeCode(const char *key)
1251 {
1252   char
1253     buffer[2];
1254
1255   register ssize_t
1256     i;
1257
1258   unsigned int
1259     shift,
1260     value;
1261
1262   value=0;
1263   shift=28;
1264   buffer[1]='\0';
1265   for (i=0; (*key != 0) && (i < 11); i++)
1266   {
1267     if (isxdigit((int) ((unsigned char) *key)) == 0)
1268       {
1269         key++;
1270         continue;
1271       }
1272     buffer[0]=(*key++);
1273     value|=(unsigned int) ((strtol(buffer,(char **) NULL,16)) << shift);
1274     shift-=4;
1275   }
1276   return(value);
1277 }
1278
1279 static MagickBooleanType WriteDPXImage(const ImageInfo *image_info,Image *image)
1280 {
1281   const char
1282     *value;
1283
1284   const StringInfo
1285     *profile;
1286
1287   DPXInfo
1288     dpx;
1289
1290   ssize_t
1291     horizontal_factor,
1292     vertical_factor,
1293     y;
1294
1295   MagickBooleanType
1296     status;
1297
1298   MagickOffsetType
1299     offset;
1300
1301   MagickStatusType
1302     flags;
1303
1304   GeometryInfo
1305     geometry_info;
1306
1307   QuantumInfo
1308     *quantum_info;
1309
1310   QuantumType
1311     quantum_type;
1312
1313   register const PixelPacket
1314     *p;
1315
1316   register ssize_t
1317     i;
1318
1319   size_t
1320     extent;
1321
1322   ssize_t
1323     count;
1324
1325   time_t
1326     seconds;
1327
1328   unsigned char
1329     *pixels;
1330
1331   /*
1332     Open output image file.
1333   */
1334   assert(image_info != (const ImageInfo *) NULL);
1335   assert(image_info->signature == MagickSignature);
1336   assert(image != (Image *) NULL);
1337   assert(image->signature == MagickSignature);
1338   if (image->debug != MagickFalse)
1339     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1340   horizontal_factor=4;
1341   vertical_factor=4;
1342   if (image_info->sampling_factor != (char *) NULL)
1343     {
1344       GeometryInfo
1345         geometry_info;
1346
1347       MagickStatusType
1348         flags;
1349
1350       flags=ParseGeometry(image_info->sampling_factor,&geometry_info);
1351       horizontal_factor=(ssize_t) geometry_info.rho;
1352       vertical_factor=(ssize_t) geometry_info.sigma;
1353       if ((flags & SigmaValue) == 0)
1354         vertical_factor=horizontal_factor;
1355       if ((horizontal_factor != 1) && (horizontal_factor != 2) &&
1356           (horizontal_factor != 4) && (vertical_factor != 1) &&
1357           (vertical_factor != 2) && (vertical_factor != 4))
1358         ThrowWriterException(CorruptImageError,"UnexpectedSamplingFactor");
1359     }
1360   if ((image->colorspace == YCbCrColorspace) &&
1361       ((horizontal_factor == 2) || (vertical_factor == 2)))
1362     if ((image->columns % 2) != 0)
1363       image->columns++;
1364   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1365   if (status == MagickFalse)
1366     return(status);
1367   /*
1368     Write file header.
1369   */
1370   (void) ResetMagickMemory(&dpx,0,sizeof(dpx));
1371   offset=0;
1372   dpx.file.magic=0x53445058U;
1373   offset+=WriteBlobLong(image,dpx.file.magic);
1374   dpx.file.image_offset=0x2000U;
1375   profile=GetImageProfile(image,"dpx");
1376   if (profile != (StringInfo *) NULL)
1377     {
1378       if (GetStringInfoLength(profile) > 1048576)
1379         ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1380       dpx.file.image_offset+=(unsigned int) GetStringInfoLength(profile);
1381       dpx.file.image_offset=(((dpx.file.image_offset+0x2000-1)/0x2000)*0x2000);
1382     }
1383   offset+=WriteBlobLong(image,dpx.file.image_offset);
1384   (void) strncpy(dpx.file.version,"V2.0",sizeof(dpx.file.version));
1385   offset+=WriteBlob(image,8,(unsigned char *) &dpx.file.version);
1386   dpx.file.file_size=(unsigned int) (4U*image->columns*image->rows+
1387     dpx.file.image_offset);
1388   offset+=WriteBlobLong(image,dpx.file.file_size);
1389   dpx.file.ditto_key=1U;  /* new frame */
1390   offset+=WriteBlobLong(image,dpx.file.ditto_key);
1391   dpx.file.generic_size=0x00000680U;
1392   offset+=WriteBlobLong(image,dpx.file.generic_size);
1393   dpx.file.industry_size=0x00000180U;
1394   offset+=WriteBlobLong(image,dpx.file.industry_size);
1395   dpx.file.user_size=0;
1396   if (profile != (StringInfo *) NULL)
1397     {
1398       dpx.file.user_size+=(unsigned int) GetStringInfoLength(profile);
1399       dpx.file.user_size=(((dpx.file.user_size+0x2000-1)/0x2000)*0x2000);
1400     }
1401   offset+=WriteBlobLong(image,dpx.file.user_size);
1402   value=GetDPXProperty(image_info,image,"dpx:file.filename");
1403   if (value != (const char *) NULL)
1404     (void) strncpy(dpx.file.filename,value,sizeof(dpx.file.filename));
1405   offset+=WriteBlob(image,sizeof(dpx.file.filename),(unsigned char *)
1406     dpx.file.filename);
1407   seconds=time((time_t *) NULL);
1408   (void) FormatMagickTime(seconds,sizeof(dpx.file.timestamp),
1409     dpx.file.timestamp);
1410   offset+=WriteBlob(image,sizeof(dpx.file.timestamp),(unsigned char *)
1411     dpx.file.timestamp);
1412   (void) strncpy(dpx.file.creator,GetMagickVersion((size_t *) NULL),
1413     sizeof(dpx.file.creator));
1414   value=GetDPXProperty(image_info,image,"dpx:file.creator");
1415   if (value != (const char *) NULL)
1416     (void) strncpy(dpx.file.creator,value,sizeof(dpx.file.creator));
1417   offset+=WriteBlob(image,sizeof(dpx.file.creator),(unsigned char *)
1418     dpx.file.creator);
1419   value=GetDPXProperty(image_info,image,"dpx:file.project");
1420   if (value != (const char *) NULL)
1421     (void) strncpy(dpx.file.project,value,sizeof(dpx.file.project));
1422   offset+=WriteBlob(image,sizeof(dpx.file.project),(unsigned char *)
1423     dpx.file.project);
1424   value=GetDPXProperty(image_info,image,"dpx:file.copyright");
1425   if (value != (const char *) NULL)
1426     (void) strncpy(dpx.file.copyright,value,
1427       sizeof(dpx.file.copyright));
1428   offset+=WriteBlob(image,sizeof(dpx.file.copyright),(unsigned char *)
1429     dpx.file.copyright);
1430   dpx.file.encrypt_key=(~0U);
1431   offset+=WriteBlobLong(image,dpx.file.encrypt_key);
1432   offset+=WriteBlob(image,sizeof(dpx.file.reserve),(unsigned char *)
1433     dpx.file.reserve);
1434   /*
1435     Write image header.
1436   */
1437   dpx.image.orientation=0x00;  /* left-to-right; top-to-bottom */
1438   offset+=WriteBlobShort(image,dpx.image.orientation);
1439   dpx.image.number_elements=1;
1440   offset+=WriteBlobShort(image,dpx.image.number_elements);
1441   if ((image->columns != (unsigned int) image->columns) ||
1442       (image->rows != (unsigned int) image->rows))
1443     ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1444   offset+=WriteBlobLong(image,(unsigned int) image->columns);
1445   offset+=WriteBlobLong(image,(unsigned int) image->rows);
1446   for (i=0; i < 8; i++)
1447   {
1448     dpx.image.image_element[i].data_sign=0U;
1449     offset+=WriteBlobLong(image,dpx.image.image_element[i].data_sign);
1450     dpx.image.image_element[i].low_data=0U;
1451     offset+=WriteBlobLong(image,dpx.image.image_element[i].low_data);
1452     dpx.image.image_element[i].low_quantity=0.0f;
1453     offset+=WriteBlobFloat(image,dpx.image.image_element[i].low_quantity);
1454     dpx.image.image_element[i].high_data=0U;
1455     offset+=WriteBlobLong(image,dpx.image.image_element[i].high_data);
1456     dpx.image.image_element[i].high_quantity=0.0f;
1457     offset+=WriteBlobFloat(image,dpx.image.image_element[i].high_quantity);
1458     dpx.image.image_element[i].descriptor=0;
1459     if (i == 0)
1460       switch (image->colorspace)
1461       {
1462         case Rec601YCbCrColorspace:
1463         case Rec709YCbCrColorspace:
1464         case YCbCrColorspace:
1465         {
1466           dpx.image.image_element[i].descriptor=CbYCr444ComponentType;
1467           if (image->matte != MagickFalse)
1468             dpx.image.image_element[i].descriptor=CbYCrA4444ComponentType;
1469           break;
1470         }
1471         default:
1472         {
1473           dpx.image.image_element[i].descriptor=RGBComponentType;
1474           if (image->matte != MagickFalse)
1475             dpx.image.image_element[i].descriptor=RGBAComponentType;
1476           if ((image_info->type != TrueColorType) &&
1477               (image->matte == MagickFalse) &&
1478               (IsGrayImage(image,&image->exception) != MagickFalse))
1479             dpx.image.image_element[i].descriptor=LumaComponentType;
1480           break;
1481         }
1482       }
1483     offset+=WriteBlobByte(image,dpx.image.image_element[i].descriptor);
1484     dpx.image.image_element[i].transfer=0;
1485     if (image->colorspace == LogColorspace)
1486       dpx.image.image_element[0].transfer=PrintingDensityColorimetric;
1487     offset+=WriteBlobByte(image,dpx.image.image_element[i].transfer);
1488     dpx.image.image_element[i].colorimetric=0;
1489     offset+=WriteBlobByte(image,dpx.image.image_element[i].colorimetric);
1490     dpx.image.image_element[i].bit_size=0;
1491     if (i == 0)
1492       dpx.image.image_element[i].bit_size=(unsigned char) image->depth;
1493     offset+=WriteBlobByte(image,dpx.image.image_element[i].bit_size);
1494     dpx.image.image_element[i].packing=0;
1495     if ((image->depth == 10) || (image->depth == 12))
1496       dpx.image.image_element[i].packing=1;
1497     offset+=WriteBlobShort(image,dpx.image.image_element[i].packing);
1498     dpx.image.image_element[i].encoding=0;
1499     offset+=WriteBlobShort(image,dpx.image.image_element[i].encoding);
1500     dpx.image.image_element[i].data_offset=0U;
1501     if (i == 0)
1502       dpx.image.image_element[i].data_offset=dpx.file.image_offset;
1503     offset+=WriteBlobLong(image,dpx.image.image_element[i].data_offset);
1504     dpx.image.image_element[i].end_of_line_padding=0U;
1505     offset+=WriteBlobLong(image,dpx.image.image_element[i].end_of_line_padding);
1506     offset+=WriteBlobLong(image,
1507       dpx.image.image_element[i].end_of_image_padding);
1508     offset+=WriteBlob(image,sizeof(dpx.image.image_element[i].description),
1509       (unsigned char *) dpx.image.image_element[i].description);
1510   }
1511   offset+=WriteBlob(image,sizeof(dpx.image.reserve),(unsigned char *)
1512     dpx.image.reserve);
1513   /*
1514     Write orientation header.
1515   */
1516   if ((image->rows != image->magick_rows) ||
1517       (image->columns != image->magick_columns))
1518     {
1519       /*
1520         These properties are not valid if image size changed.
1521       */
1522       (void) DeleteImageProperty(image,"dpx:orientation.x_offset");
1523       (void) DeleteImageProperty(image,"dpx:orientation.y_offset");
1524       (void) DeleteImageProperty(image,"dpx:orientation.x_center");
1525       (void) DeleteImageProperty(image,"dpx:orientation.y_center");
1526       (void) DeleteImageProperty(image,"dpx:orientation.x_size");
1527       (void) DeleteImageProperty(image,"dpx:orientation.y_size");
1528     }
1529   dpx.orientation.x_offset=0U;
1530   value=GetDPXProperty(image_info,image,"dpx:orientation.x_offset");
1531   if (value != (const char *) NULL)
1532     dpx.orientation.x_offset=(unsigned int) StringToUnsignedLong(value);
1533   offset+=WriteBlobLong(image,dpx.orientation.x_offset);
1534   dpx.orientation.y_offset=0U;
1535   value=GetDPXProperty(image_info,image,"dpx:orientation.y_offset");
1536   if (value != (const char *) NULL)
1537     dpx.orientation.y_offset=(unsigned int) StringToUnsignedLong(value);
1538   offset+=WriteBlobLong(image,dpx.orientation.y_offset);
1539   dpx.orientation.x_center=0.0f;
1540   value=GetDPXProperty(image_info,image,"dpx:orientation.x_center");
1541   if (value != (const char *) NULL)
1542     dpx.orientation.x_center=StringToDouble(value);
1543   offset+=WriteBlobFloat(image,dpx.orientation.x_center);
1544   dpx.orientation.y_center=0.0f;
1545   value=GetDPXProperty(image_info,image,"dpx:orientation.y_center");
1546   if (value != (const char *) NULL)
1547     dpx.orientation.y_center=StringToDouble(value);
1548   offset+=WriteBlobFloat(image,dpx.orientation.y_center);
1549   dpx.orientation.x_size=0U;
1550   value=GetDPXProperty(image_info,image,"dpx:orientation.x_size");
1551   if (value != (const char *) NULL)
1552     dpx.orientation.x_size=(unsigned int) StringToUnsignedLong(value);
1553   offset+=WriteBlobLong(image,dpx.orientation.x_size);
1554   dpx.orientation.y_size=0U;
1555   value=GetDPXProperty(image_info,image,"dpx:orientation.y_size");
1556   if (value != (const char *) NULL)
1557     dpx.orientation.y_size=(unsigned int) StringToUnsignedLong(value);
1558   offset+=WriteBlobLong(image,dpx.orientation.y_size);
1559   value=GetDPXProperty(image_info,image,"dpx:orientation.filename");
1560   if (value != (const char *) NULL)
1561     (void) strncpy(dpx.orientation.filename,value,
1562       sizeof(dpx.orientation.filename));
1563   offset+=WriteBlob(image,sizeof(dpx.orientation.filename),(unsigned char *)
1564     dpx.orientation.filename);
1565   offset+=WriteBlob(image,sizeof(dpx.orientation.timestamp),(unsigned char *)
1566     dpx.orientation.timestamp);
1567   value=GetDPXProperty(image_info,image,"dpx:orientation.device");
1568   if (value != (const char *) NULL)
1569     (void) strncpy(dpx.orientation.device,value,sizeof(dpx.orientation.device));
1570   offset+=WriteBlob(image,sizeof(dpx.orientation.device),(unsigned char *)
1571     dpx.orientation.device);
1572   value=GetDPXProperty(image_info,image,"dpx:orientation.serial");
1573   if (value != (const char *) NULL)
1574     (void) strncpy(dpx.orientation.serial,value,sizeof(dpx.orientation.serial));
1575   offset+=WriteBlob(image,sizeof(dpx.orientation.serial),(unsigned char *)
1576     dpx.orientation.serial);
1577   for (i=0; i < 4; i++)
1578     dpx.orientation.border[i]=0;
1579   value=GetDPXProperty(image_info,image,"dpx:orientation.border");
1580   if (value != (const char *) NULL)
1581     {
1582       flags=ParseGeometry(value,&geometry_info);
1583       if ((flags & SigmaValue) == 0)
1584         geometry_info.sigma=geometry_info.rho;
1585       dpx.orientation.border[0]=(unsigned short) (geometry_info.rho+0.5);
1586       dpx.orientation.border[1]=(unsigned short) (geometry_info.sigma+0.5);
1587       dpx.orientation.border[2]=(unsigned short) (geometry_info.xi+0.5);
1588       dpx.orientation.border[3]=(unsigned short) (geometry_info.psi+0.5);
1589     }
1590   for (i=0; i < 4; i++)
1591     offset+=WriteBlobShort(image,dpx.orientation.border[i]);
1592   for (i=0; i < 2; i++)
1593     dpx.orientation.aspect_ratio[i]=0U;
1594   value=GetDPXProperty(image_info,image,"dpx:orientation.aspect_ratio");
1595   if (value != (const char *) NULL)
1596     {
1597       flags=ParseGeometry(value,&geometry_info);
1598       if ((flags & SigmaValue) == 0)
1599         geometry_info.sigma=geometry_info.rho;
1600       dpx.orientation.aspect_ratio[0]=(unsigned int) (geometry_info.rho+0.5);
1601       dpx.orientation.aspect_ratio[1]=(unsigned int) (geometry_info.sigma+0.5);
1602     }
1603   for (i=0; i < 2; i++)
1604     offset+=WriteBlobLong(image,dpx.orientation.aspect_ratio[i]);
1605   offset+=WriteBlob(image,sizeof(dpx.orientation.reserve),(unsigned char *)
1606     dpx.orientation.reserve);
1607   /*
1608     Write film header.
1609   */
1610   *dpx.film.id='\0';
1611   value=GetDPXProperty(image_info,image,"dpx:film.id");
1612   if (value != (const char *) NULL)
1613     (void) strncpy(dpx.film.id,value,sizeof(dpx.film.id));
1614   offset+=WriteBlob(image,sizeof(dpx.film.id),(unsigned char *) dpx.film.id);
1615   *dpx.film.type='\0';
1616   value=GetDPXProperty(image_info,image,"dpx:film.type");
1617   if (value != (const char *) NULL)
1618     (void) strncpy(dpx.film.type,value,sizeof(dpx.film.type));
1619   offset+=WriteBlob(image,sizeof(dpx.film.type),(unsigned char *)
1620     dpx.film.type);
1621   *dpx.film.offset='\0';
1622   value=GetDPXProperty(image_info,image,"dpx:film.offset");
1623   if (value != (const char *) NULL)
1624     (void) strncpy(dpx.film.offset,value,sizeof(dpx.film.offset));
1625   offset+=WriteBlob(image,sizeof(dpx.film.offset),(unsigned char *)
1626     dpx.film.offset);
1627   *dpx.film.prefix='\0';
1628   value=GetDPXProperty(image_info,image,"dpx:film.prefix");
1629   if (value != (const char *) NULL)
1630     (void) strncpy(dpx.film.prefix,value,sizeof(dpx.film.prefix));
1631   offset+=WriteBlob(image,sizeof(dpx.film.prefix),(unsigned char *)
1632     dpx.film.prefix);
1633   *dpx.film.count='\0';
1634   value=GetDPXProperty(image_info,image,"dpx:film.count");
1635   if (value != (const char *) NULL)
1636     (void) strncpy(dpx.film.count,value,sizeof(dpx.film.count));
1637   offset+=WriteBlob(image,sizeof(dpx.film.count),(unsigned char *)
1638     dpx.film.count);
1639   *dpx.film.format='\0';
1640   value=GetDPXProperty(image_info,image,"dpx:film.format");
1641   if (value != (const char *) NULL)
1642     (void) strncpy(dpx.film.format,value,sizeof(dpx.film.format));
1643   offset+=WriteBlob(image,sizeof(dpx.film.format),(unsigned char *)
1644     dpx.film.format);
1645   dpx.film.frame_position=0U;
1646   value=GetDPXProperty(image_info,image,"dpx:film.frame_position");
1647   if (value != (const char *) NULL)
1648     dpx.film.frame_position=(unsigned int) StringToUnsignedLong(value);
1649   offset+=WriteBlobLong(image,dpx.film.frame_position);
1650   dpx.film.sequence_extent=0U;
1651   value=GetDPXProperty(image_info,image,"dpx:film.sequence_extent");
1652   if (value != (const char *) NULL)
1653     dpx.film.sequence_extent=(unsigned int) StringToUnsignedLong(value);
1654   offset+=WriteBlobLong(image,dpx.film.sequence_extent);
1655   dpx.film.held_count=0U;
1656   value=GetDPXProperty(image_info,image,"dpx:film.held_count");
1657   if (value != (const char *) NULL)
1658     dpx.film.held_count=(unsigned int) StringToUnsignedLong(value);
1659   offset+=WriteBlobLong(image,dpx.film.held_count);
1660   dpx.film.frame_rate=0.0f;
1661   value=GetDPXProperty(image_info,image,"dpx:film.frame_rate");
1662   if (value != (const char *) NULL)
1663     dpx.film.frame_rate=StringToDouble(value);
1664   offset+=WriteBlobFloat(image,dpx.film.frame_rate);
1665   dpx.film.shutter_angle=0.0f;
1666   value=GetDPXProperty(image_info,image,"dpx:film.shutter_angle");
1667   if (value != (const char *) NULL)
1668     dpx.film.shutter_angle=StringToDouble(value);
1669   offset+=WriteBlobFloat(image,dpx.film.shutter_angle);
1670   *dpx.film.frame_id='\0';
1671   value=GetDPXProperty(image_info,image,"dpx:film.frame_id");
1672   if (value != (const char *) NULL)
1673     (void) strncpy(dpx.film.frame_id,value,sizeof(dpx.film.frame_id));
1674   offset+=WriteBlob(image,sizeof(dpx.film.frame_id),(unsigned char *)
1675     dpx.film.frame_id);
1676   value=GetDPXProperty(image_info,image,"dpx:film.slate");
1677   if (value != (const char *) NULL)
1678     (void) strncpy(dpx.film.slate,value,sizeof(dpx.film.slate));
1679   offset+=WriteBlob(image,sizeof(dpx.film.slate),(unsigned char *)
1680     dpx.film.slate);
1681   offset+=WriteBlob(image,sizeof(dpx.film.reserve),(unsigned char *)
1682     dpx.film.reserve);
1683   /*
1684     Write television header.
1685   */
1686   value=GetDPXProperty(image_info,image,"dpx:television.time.code");
1687   if (value != (const char *) NULL)
1688     dpx.television.time_code=StringToTimeCode(value);
1689   offset+=WriteBlobLong(image,dpx.television.time_code);
1690   value=GetDPXProperty(image_info,image,"dpx:television.user.bits");
1691   if (value != (const char *) NULL)
1692     dpx.television.user_bits=StringToTimeCode(value);
1693   offset+=WriteBlobLong(image,dpx.television.user_bits);
1694   value=GetDPXProperty(image_info,image,"dpx:television.interlace");
1695   if (value != (const char *) NULL)
1696     dpx.television.interlace=(unsigned char) StringToLong(value);
1697   offset+=WriteBlobByte(image,dpx.television.interlace);
1698   value=GetDPXProperty(image_info,image,"dpx:television.field_number");
1699   if (value != (const char *) NULL)
1700     dpx.television.field_number=(unsigned char) StringToLong(value);
1701   offset+=WriteBlobByte(image,dpx.television.field_number);
1702   dpx.television.video_signal=0;
1703   value=GetDPXProperty(image_info,image,"dpx:television.video_signal");
1704   if (value != (const char *) NULL)
1705     dpx.television.video_signal=(unsigned char) StringToLong(value);
1706   offset+=WriteBlobByte(image,dpx.television.video_signal);
1707   dpx.television.padding=0;
1708   value=GetDPXProperty(image_info,image,"dpx:television.padding");
1709   if (value != (const char *) NULL)
1710     dpx.television.padding=(unsigned char) StringToLong(value);
1711   offset+=WriteBlobByte(image,dpx.television.padding);
1712   dpx.television.horizontal_sample_rate=0.0f;
1713   value=GetDPXProperty(image_info,image,
1714     "dpx:television.horizontal_sample_rate");
1715   if (value != (const char *) NULL)
1716     dpx.television.horizontal_sample_rate=StringToDouble(value);
1717   offset+=WriteBlobFloat(image,dpx.television.horizontal_sample_rate);
1718   dpx.television.vertical_sample_rate=0.0f;
1719   value=GetDPXProperty(image_info,image,"dpx:television.vertical_sample_rate");
1720   if (value != (const char *) NULL)
1721     dpx.television.vertical_sample_rate=StringToDouble(value);
1722   offset+=WriteBlobFloat(image,dpx.television.vertical_sample_rate);
1723   dpx.television.frame_rate=0.0f;
1724   value=GetDPXProperty(image_info,image,"dpx:television.frame_rate");
1725   if (value != (const char *) NULL)
1726     dpx.television.frame_rate=StringToDouble(value);
1727   offset+=WriteBlobFloat(image,dpx.television.frame_rate);
1728   dpx.television.time_offset=0.0f;
1729   value=GetDPXProperty(image_info,image,"dpx:television.time_offset");
1730   if (value != (const char *) NULL)
1731     dpx.television.time_offset=StringToDouble(value);
1732   offset+=WriteBlobFloat(image,dpx.television.time_offset);
1733   dpx.television.gamma=0.0f;
1734   value=GetDPXProperty(image_info,image,"dpx:television.gamma");
1735   if (value != (const char *) NULL)
1736     dpx.television.gamma=StringToDouble(value);
1737   offset+=WriteBlobFloat(image,dpx.television.gamma);
1738   dpx.television.black_level=0.0f;
1739   value=GetDPXProperty(image_info,image,"dpx:television.black_level");
1740   if (value != (const char *) NULL)
1741     dpx.television.black_level=StringToDouble(value);
1742   offset+=WriteBlobFloat(image,dpx.television.black_level);
1743   dpx.television.black_gain=0.0f;
1744   value=GetDPXProperty(image_info,image,"dpx:television.black_gain");
1745   if (value != (const char *) NULL)
1746     dpx.television.black_gain=StringToDouble(value);
1747   offset+=WriteBlobFloat(image,dpx.television.black_gain);
1748   dpx.television.break_point=0.0f;
1749   value=GetDPXProperty(image_info,image,"dpx:television.break_point");
1750   if (value != (const char *) NULL)
1751     dpx.television.break_point=StringToDouble(value);
1752   offset+=WriteBlobFloat(image,dpx.television.break_point);
1753   dpx.television.white_level=0.0f;
1754   value=GetDPXProperty(image_info,image,"dpx:television.white_level");
1755   if (value != (const char *) NULL)
1756     dpx.television.white_level=StringToDouble(value);
1757   offset+=WriteBlobFloat(image,dpx.television.white_level);
1758   dpx.television.integration_times=0.0f;
1759   value=GetDPXProperty(image_info,image,"dpx:television.integration_times");
1760   if (value != (const char *) NULL)
1761     dpx.television.integration_times=StringToDouble(value);
1762   offset+=WriteBlobFloat(image,dpx.television.integration_times);
1763   offset+=WriteBlob(image,sizeof(dpx.television.reserve),(unsigned char *)
1764     dpx.television.reserve);
1765   /*
1766     Write user header.
1767   */
1768   value=GetDPXProperty(image_info,image,"dpx:user.id");
1769   if (value != (const char *) NULL)
1770     (void) strncpy(dpx.user.id,value,sizeof(dpx.user.id));
1771   offset+=WriteBlob(image,sizeof(dpx.user.id),(unsigned char *) dpx.user.id);
1772   if (profile != (StringInfo *) NULL)
1773     offset+=WriteBlob(image,GetStringInfoLength(profile),
1774       GetStringInfoDatum(profile));
1775   while (offset < (MagickOffsetType) dpx.image.image_element[0].data_offset)
1776   {
1777     count=WriteBlobByte(image,0x00);
1778     if (count != 1)
1779       {
1780         ThrowFileException(&image->exception,FileOpenError,"UnableToWriteFile",
1781           image->filename);
1782         break;
1783       }
1784     offset+=count;
1785   }
1786   /*
1787     Convert pixel packets to DPX raster image.
1788   */
1789   quantum_info=AcquireQuantumInfo(image_info,image);
1790   SetQuantumQuantum(quantum_info,32);
1791   SetQuantumPack(quantum_info,dpx.image.image_element[0].packing == 0 ?
1792     MagickTrue : MagickFalse);
1793   quantum_type=RGBQuantum;
1794   if (image->matte != MagickFalse)
1795     quantum_type=RGBAQuantum;
1796   if (image->colorspace == YCbCrColorspace)
1797     {
1798       quantum_type=CbYCrQuantum;
1799       if (image->matte != MagickFalse)
1800         quantum_type=CbYCrAQuantum;
1801       if ((horizontal_factor == 2) || (vertical_factor == 2))
1802         quantum_type=CbYCrYQuantum;
1803     }
1804   extent=GetBytesPerRow(image->columns,image->matte != MagickFalse ? 4UL : 3UL,
1805     image->depth,MagickTrue);
1806   if ((image_info->type != TrueColorType) && (image->matte == MagickFalse) &&
1807       (IsGrayImage(image,&image->exception) != MagickFalse))
1808     {
1809       quantum_type=GrayQuantum;
1810       extent=GetBytesPerRow(image->columns,1UL,image->depth,MagickTrue);
1811     }
1812   pixels=GetQuantumPixels(quantum_info);
1813   for (y=0; y < (ssize_t) image->rows; y++)
1814   {
1815     p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1816     if (p == (const PixelPacket *) NULL)
1817       break;
1818     (void) ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1819       quantum_type,pixels,&image->exception);
1820     count=WriteBlob(image,extent,pixels);
1821     if (count != (ssize_t) extent)
1822       break;
1823     status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1824                 image->rows);
1825     if (status == MagickFalse)
1826       break;
1827   }
1828   quantum_info=DestroyQuantumInfo(quantum_info);
1829   (void) CloseBlob(image);
1830   return(status);
1831 }