]> 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     double
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   MagickBooleanType
553     status;
554
555   MagickOffsetType
556     offset;
557
558   QuantumInfo
559     *quantum_info;
560
561   QuantumType
562     quantum_type;
563
564   register ssize_t
565     i;
566
567   size_t
568     extent,
569     samples_per_pixel;
570
571   ssize_t
572     count,
573     row,
574     y;
575
576   unsigned char
577     component_type;
578
579   /*
580     Open image file.
581   */
582   assert(image_info != (const ImageInfo *) NULL);
583   assert(image_info->signature == MagickSignature);
584   if (image_info->debug != MagickFalse)
585     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
586       image_info->filename);
587   assert(exception != (ExceptionInfo *) NULL);
588   assert(exception->signature == MagickSignature);
589   image=AcquireImage(image_info);
590   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
591   if (status == MagickFalse)
592     {
593       image=DestroyImageList(image);
594       return((Image *) NULL);
595     }
596   /*
597     Read DPX file header.
598   */
599   offset=0;
600   count=ReadBlob(image,4,(unsigned char *) magick);
601   offset+=count;
602   if ((count != 4) || ((LocaleNCompare(magick,"SDPX",4) != 0) &&
603       (LocaleNCompare((char *) magick,"XPDS",4) != 0)))
604     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
605   image->endian=LSBEndian;
606   if (LocaleNCompare(magick,"SDPX",4) == 0)
607     image->endian=MSBEndian;
608   (void) ResetMagickMemory(&dpx,0,sizeof(dpx));
609   dpx.file.image_offset=ReadBlobLong(image);
610   offset+=4;
611   offset+=ReadBlob(image,sizeof(dpx.file.version),(unsigned char *)
612     dpx.file.version);
613   (void) FormatImageProperty(image,"dpx:file.version","%.8s",dpx.file.version);
614   dpx.file.file_size=ReadBlobLong(image);
615   offset+=4;
616   dpx.file.ditto_key=ReadBlobLong(image);
617   offset+=4;
618   if (dpx.file.ditto_key != ~0U)
619     (void) FormatImageProperty(image,"dpx:file.ditto.key","%u",
620       dpx.file.ditto_key);
621   dpx.file.generic_size=ReadBlobLong(image);
622   offset+=4;
623   dpx.file.industry_size=ReadBlobLong(image);
624   offset+=4;
625   dpx.file.user_size=ReadBlobLong(image);
626   offset+=4;
627   offset+=ReadBlob(image,sizeof(dpx.file.filename),(unsigned char *)
628     dpx.file.filename);
629   (void) FormatImageProperty(image,"dpx:file.filename","%.100s",
630     dpx.file.filename);
631   (void) FormatImageProperty(image,"document","%.100s",dpx.file.filename);
632   offset+=ReadBlob(image,sizeof(dpx.file.timestamp),(unsigned char *)
633     dpx.file.timestamp);
634   if (*dpx.file.timestamp != '\0')
635     (void) FormatImageProperty(image,"dpx:file.timestamp","%.24s",
636       dpx.file.timestamp);
637   offset+=ReadBlob(image,sizeof(dpx.file.creator),(unsigned char *)
638     dpx.file.creator);
639   if (*dpx.file.creator != '\0')
640     {
641       (void) FormatImageProperty(image,"dpx:file.creator","%.100s",
642         dpx.file.creator);
643       (void) FormatImageProperty(image,"software","%.100s",dpx.file.creator);
644     }
645   offset+=ReadBlob(image,sizeof(dpx.file.project),(unsigned char *)
646     dpx.file.project);
647   if (*dpx.file.project != '\0')
648     {
649       (void) FormatImageProperty(image,"dpx:file.project","%.200s",
650         dpx.file.project);
651       (void) FormatImageProperty(image,"comment","%.100s",dpx.file.project);
652     }
653   offset+=ReadBlob(image,sizeof(dpx.file.copyright),(unsigned char *)
654     dpx.file.copyright);
655   if (*dpx.file.copyright != '\0')
656     {
657       (void) FormatImageProperty(image,"dpx:file.copyright","%.200s",
658         dpx.file.copyright);
659       (void) FormatImageProperty(image,"copyright","%.100s",
660         dpx.file.copyright);
661     }
662   dpx.file.encrypt_key=ReadBlobLong(image);
663   offset+=4;
664   if (dpx.file.encrypt_key != ~0U)
665     (void) FormatImageProperty(image,"dpx:file.encrypt_key","%u",
666       dpx.file.encrypt_key);
667   offset+=ReadBlob(image,sizeof(dpx.file.reserve),(unsigned char *)
668     dpx.file.reserve);
669   /*
670     Read DPX image header.
671   */
672   dpx.image.orientation=ReadBlobShort(image);
673   offset+=2;
674   if (dpx.image.orientation != (unsigned short) (~0U))
675     (void) FormatImageProperty(image,"dpx:image.orientation","%d",
676       dpx.image.orientation);
677   switch (dpx.image.orientation)
678   {
679     default:
680     case 0: image->orientation=TopLeftOrientation; break;
681     case 1: image->orientation=TopRightOrientation; break;
682     case 2: image->orientation=BottomLeftOrientation; break;
683     case 3: image->orientation=BottomRightOrientation; break;
684     case 4: image->orientation=LeftTopOrientation; break;
685     case 5: image->orientation=RightTopOrientation; break;
686     case 6: image->orientation=LeftBottomOrientation; break;
687     case 7: image->orientation=RightBottomOrientation; break;
688   }
689   dpx.image.number_elements=ReadBlobShort(image);
690   offset+=2;
691   dpx.image.pixels_per_line=ReadBlobLong(image);
692   offset+=4;
693   image->columns=dpx.image.pixels_per_line;
694   dpx.image.lines_per_element=ReadBlobLong(image);
695   offset+=4;
696   image->rows=dpx.image.lines_per_element;
697   for (i=0; i < 8; i++)
698   {
699     dpx.image.image_element[i].data_sign=ReadBlobLong(image);
700     offset+=4;
701     dpx.image.image_element[i].low_data=ReadBlobLong(image);
702     offset+=4;
703     dpx.image.image_element[i].low_quantity=ReadBlobFloat(image);
704     offset+=4;
705     dpx.image.image_element[i].high_data=ReadBlobLong(image);
706     offset+=4;
707     dpx.image.image_element[i].high_quantity=ReadBlobFloat(image);
708     offset+=4;
709     dpx.image.image_element[i].descriptor=(unsigned char) ReadBlobByte(image);
710     offset++;
711     dpx.image.image_element[i].transfer=(unsigned char) ReadBlobByte(image);
712     offset++;
713     dpx.image.image_element[i].colorimetric=(unsigned char) ReadBlobByte(image);
714     offset++;
715     dpx.image.image_element[i].bit_size=(unsigned char) ReadBlobByte(image);
716     offset++;
717     dpx.image.image_element[i].packing=ReadBlobShort(image);
718     offset+=2;
719     dpx.image.image_element[i].encoding=ReadBlobShort(image);
720     offset+=2;
721     dpx.image.image_element[i].data_offset=ReadBlobLong(image);
722     offset+=4;
723     dpx.image.image_element[i].end_of_line_padding=ReadBlobLong(image);
724     offset+=4;
725     dpx.image.image_element[i].end_of_image_padding=ReadBlobLong(image);
726     offset+=4;
727     offset+=ReadBlob(image,sizeof(dpx.image.image_element[i].description),
728       (unsigned char *) dpx.image.image_element[i].description);
729   }
730   SetPrimaryChromaticity((DPXColorimetric)
731     dpx.image.image_element[0].colorimetric,&image->chromaticity);
732   offset+=ReadBlob(image,sizeof(dpx.image.reserve),(unsigned char *)
733     dpx.image.reserve);
734   component_type=dpx.image.image_element[0].descriptor;
735   image->depth=dpx.image.image_element[0].bit_size;
736   if (dpx.file.image_offset >= 1664U)
737     {
738       /*
739         Read DPX orientation header.
740       */
741       dpx.orientation.x_offset=ReadBlobLong(image);
742       offset+=4;
743       if (dpx.orientation.x_offset != ~0U)
744         (void) FormatImageProperty(image,"dpx:orientation.x_offset","%u",
745           dpx.orientation.x_offset);
746       dpx.orientation.y_offset=ReadBlobLong(image);
747       offset+=4;
748       if (dpx.orientation.y_offset != ~0U)
749         (void) FormatImageProperty(image,"dpx:orientation.y_offset","%u",
750           dpx.orientation.y_offset);
751       dpx.orientation.x_center=ReadBlobFloat(image);
752       offset+=4;
753       if (IsFloatDefined(dpx.orientation.x_center) != MagickFalse)
754         (void) FormatImageProperty(image,"dpx:orientation.x_center","%g",
755           dpx.orientation.x_center);
756       dpx.orientation.y_center=ReadBlobFloat(image);
757       offset+=4;
758       if (IsFloatDefined(dpx.orientation.y_center) != MagickFalse)
759         (void) FormatImageProperty(image,"dpx:orientation.y_center","%g",
760           dpx.orientation.y_center);
761       dpx.orientation.x_size=ReadBlobLong(image);
762       offset+=4;
763       if (dpx.orientation.x_size != ~0U)
764         (void) FormatImageProperty(image,"dpx:orientation.x_size","%u",
765           dpx.orientation.x_size);
766       dpx.orientation.y_size=ReadBlobLong(image);
767       offset+=4;
768       if (dpx.orientation.y_size != ~0U)
769         (void) FormatImageProperty(image,"dpx:orientation.y_size","%u",
770           dpx.orientation.y_size);
771       offset+=ReadBlob(image,sizeof(dpx.orientation.filename),(unsigned char *)
772         dpx.orientation.filename);
773       if (*dpx.orientation.filename != '\0')
774         (void) FormatImageProperty(image,"dpx:orientation.filename","%.100s",
775           dpx.orientation.filename);
776       offset+=ReadBlob(image,sizeof(dpx.orientation.timestamp),(unsigned char *)
777         dpx.orientation.timestamp);
778       if (*dpx.orientation.timestamp != '\0')
779         (void) FormatImageProperty(image,"dpx:orientation.timestamp","%.24s",
780           dpx.orientation.timestamp);
781       offset+=ReadBlob(image,sizeof(dpx.orientation.device),(unsigned char *)
782         dpx.orientation.device);
783       if (*dpx.orientation.device != '\0')
784         (void) FormatImageProperty(image,"dpx:orientation.device","%.32s",
785           dpx.orientation.device);
786       offset+=ReadBlob(image,sizeof(dpx.orientation.serial),(unsigned char *)
787         dpx.orientation.serial);
788       if (*dpx.orientation.serial != '\0')
789         (void) FormatImageProperty(image,"dpx:orientation.serial","%.32s",
790           dpx.orientation.serial);
791       for (i=0; i < 4; i++)
792       {
793         dpx.orientation.border[i]=ReadBlobShort(image);
794         offset+=2;
795       }
796       if ((dpx.orientation.border[0] != (unsigned short) (~0U)) &&
797           (dpx.orientation.border[1] != (unsigned short) (~0U)))
798         (void) FormatImageProperty(image,"dpx:orientation.border","%dx%d%+d%+d",          dpx.orientation.border[0],dpx.orientation.border[1],
799           dpx.orientation.border[2],dpx.orientation.border[3]);
800       for (i=0; i < 2; i++)
801       {
802         dpx.orientation.aspect_ratio[i]=ReadBlobLong(image);
803         offset+=4;
804       }
805       if ((dpx.orientation.aspect_ratio[0] != ~0U) &&
806           (dpx.orientation.aspect_ratio[1] != ~0U))
807         (void) FormatImageProperty(image,"dpx:orientation.aspect_ratio",
808           "%ux%u",dpx.orientation.aspect_ratio[0],
809           dpx.orientation.aspect_ratio[1]);
810       offset+=ReadBlob(image,sizeof(dpx.orientation.reserve),(unsigned char *)
811         dpx.orientation.reserve);
812     }
813   if (dpx.file.image_offset >= 1920U)
814     {
815       /*
816         Read DPX film header.
817       */
818       offset+=ReadBlob(image,sizeof(dpx.film.id),(unsigned char *) dpx.film.id);
819       if (*dpx.film.type != '\0')
820         (void) FormatImageProperty(image,"dpx:film.id","%.2s",dpx.film.id);
821       offset+=ReadBlob(image,sizeof(dpx.film.type),(unsigned char *)
822         dpx.film.type);
823       if (*dpx.film.type != '\0')
824         (void) FormatImageProperty(image,"dpx:film.type","%.2s",dpx.film.type);
825       offset+=ReadBlob(image,sizeof(dpx.film.offset),(unsigned char *)
826         dpx.film.offset);
827       if (*dpx.film.offset != '\0')
828         (void) FormatImageProperty(image,"dpx:film.offset","%.2s",
829           dpx.film.offset);
830       offset+=ReadBlob(image,sizeof(dpx.film.prefix),(unsigned char *)
831         dpx.film.prefix);
832       if (*dpx.film.prefix != '\0')
833         (void) FormatImageProperty(image,"dpx:film.prefix","%.6s",
834           dpx.film.prefix);
835       offset+=ReadBlob(image,sizeof(dpx.film.count),(unsigned char *)
836         dpx.film.count);
837       if (*dpx.film.count != '\0')
838         (void) FormatImageProperty(image,"dpx:film.count","%.4s",
839           dpx.film.count);
840       offset+=ReadBlob(image,sizeof(dpx.film.format),(unsigned char *)
841         dpx.film.format);
842       if (*dpx.film.format != '\0')
843         (void) FormatImageProperty(image,"dpx:film.format","%.4s",
844           dpx.film.format);
845       dpx.film.frame_position=ReadBlobLong(image);
846       offset+=4;
847       if (dpx.film.frame_position != ~0U)
848         (void) FormatImageProperty(image,"dpx:film.frame_position","%u",
849           dpx.film.frame_position);
850       dpx.film.sequence_extent=ReadBlobLong(image);
851       offset+=4;
852       if (dpx.film.sequence_extent != ~0U)
853         (void) FormatImageProperty(image,"dpx:film.sequence_extent","%u",
854           dpx.film.sequence_extent);
855       dpx.film.held_count=ReadBlobLong(image);
856       offset+=4;
857       if (dpx.film.held_count != ~0U)
858         (void) FormatImageProperty(image,"dpx:film.held_count","%u",
859           dpx.film.held_count);
860       dpx.film.frame_rate=ReadBlobFloat(image);
861       offset+=4;
862       if (IsFloatDefined(dpx.film.frame_rate) != MagickFalse)
863         (void) FormatImageProperty(image,"dpx:film.frame_rate","%g",
864           dpx.film.frame_rate);
865       dpx.film.shutter_angle=ReadBlobFloat(image);
866       offset+=4;
867       if (IsFloatDefined(dpx.film.shutter_angle) != MagickFalse)
868         (void) FormatImageProperty(image,"dpx:film.shutter_angle","%g",
869           dpx.film.shutter_angle);
870       offset+=ReadBlob(image,sizeof(dpx.film.frame_id),(unsigned char *)
871         dpx.film.frame_id);
872       if (*dpx.film.frame_id != '\0')
873         (void) FormatImageProperty(image,"dpx:film.frame_id","%.32s",
874           dpx.film.frame_id);
875       offset+=ReadBlob(image,sizeof(dpx.film.slate),(unsigned char *)
876         dpx.film.slate);
877       if (*dpx.film.slate != '\0')
878         (void) FormatImageProperty(image,"dpx:film.slate","%.100s",
879           dpx.film.slate);
880       offset+=ReadBlob(image,sizeof(dpx.film.reserve),(unsigned char *)
881         dpx.film.reserve);
882     }
883   if (dpx.file.image_offset >= 2048U)
884     {
885       /*
886         Read DPX television header.
887       */
888       dpx.television.time_code=(unsigned int) ReadBlobLong(image);
889       offset+=4;
890       TimeCodeToString(dpx.television.time_code,value);
891       (void) SetImageProperty(image,"dpx:television.time.code",value);
892       dpx.television.user_bits=(unsigned int) ReadBlobLong(image);
893       offset+=4;
894       TimeCodeToString(dpx.television.user_bits,value);
895       (void) SetImageProperty(image,"dpx:television.user.bits",value);
896       dpx.television.interlace=(unsigned char) ReadBlobByte(image);
897       offset++;
898       if (dpx.television.interlace != 0)
899         (void) FormatImageProperty(image,"dpx:television.interlace","%.20g",
900           (double) dpx.television.interlace);
901       dpx.television.field_number=(unsigned char) ReadBlobByte(image);
902       offset++;
903       if (dpx.television.field_number != 0)
904         (void) FormatImageProperty(image,"dpx:television.field_number","%.20g",
905           (double) dpx.television.field_number);
906       dpx.television.video_signal=(unsigned char) ReadBlobByte(image);
907       offset++;
908       if (dpx.television.video_signal != 0)
909         (void) FormatImageProperty(image,"dpx:television.video_signal","%.20g",
910           (double) dpx.television.video_signal);
911       dpx.television.padding=(unsigned char) ReadBlobByte(image);
912       offset++;
913       if (dpx.television.padding != 0)
914         (void) FormatImageProperty(image,"dpx:television.padding","%d",
915           dpx.television.padding);
916       dpx.television.horizontal_sample_rate=ReadBlobFloat(image);
917       offset+=4;
918       if (IsFloatDefined(dpx.television.horizontal_sample_rate) != MagickFalse)
919         (void) FormatImageProperty(image,
920           "dpx:television.horizontal_sample_rate","%g",
921           dpx.television.horizontal_sample_rate);
922       dpx.television.vertical_sample_rate=ReadBlobFloat(image);
923       offset+=4;
924       if (IsFloatDefined(dpx.television.vertical_sample_rate) != MagickFalse)
925         (void) FormatImageProperty(image,"dpx:television.vertical_sample_rate",
926           "%g",dpx.television.vertical_sample_rate);
927       dpx.television.frame_rate=ReadBlobFloat(image);
928       offset+=4;
929       if (IsFloatDefined(dpx.television.frame_rate) != MagickFalse)
930         (void) FormatImageProperty(image,"dpx:television.frame_rate","%g",
931           dpx.television.frame_rate);
932       dpx.television.time_offset=ReadBlobFloat(image);
933       offset+=4;
934       if (IsFloatDefined(dpx.television.time_offset) != MagickFalse)
935         (void) FormatImageProperty(image,"dpx:television.time_offset","%g",
936           dpx.television.time_offset);
937       dpx.television.gamma=ReadBlobFloat(image);
938       offset+=4;
939       if (IsFloatDefined(dpx.television.gamma) != MagickFalse)
940         (void) FormatImageProperty(image,"dpx:television.gamma","%g",
941           dpx.television.gamma);
942       dpx.television.black_level=ReadBlobFloat(image);
943       offset+=4;
944       if (IsFloatDefined(dpx.television.black_level) != MagickFalse)
945         (void) FormatImageProperty(image,"dpx:television.black_level","%g",
946           dpx.television.black_level);
947       dpx.television.black_gain=ReadBlobFloat(image);
948       offset+=4;
949       if (IsFloatDefined(dpx.television.black_gain) != MagickFalse)
950         (void) FormatImageProperty(image,"dpx:television.black_gain","%g",
951           dpx.television.black_gain);
952       dpx.television.break_point=ReadBlobFloat(image);
953       offset+=4;
954       if (IsFloatDefined(dpx.television.break_point) != MagickFalse)
955         (void) FormatImageProperty(image,"dpx:television.break_point","%g",
956           dpx.television.break_point);
957       dpx.television.white_level=ReadBlobFloat(image);
958       offset+=4;
959       if (IsFloatDefined(dpx.television.white_level) != MagickFalse)
960         (void) FormatImageProperty(image,"dpx:television.white_level","%g",
961           dpx.television.white_level);
962       dpx.television.integration_times=ReadBlobFloat(image);
963       offset+=4;
964       if (IsFloatDefined(dpx.television.integration_times) != MagickFalse)
965         (void) FormatImageProperty(image,"dpx:television.integration_times",
966           "%g",dpx.television.integration_times);
967       offset+=ReadBlob(image,sizeof(dpx.television.reserve),(unsigned char *)
968         dpx.television.reserve);
969     }
970   if (dpx.file.image_offset > 2080U)
971     {
972       /*
973         Read DPX user header.
974       */
975       offset+=ReadBlob(image,sizeof(dpx.user.id),(unsigned char *) dpx.user.id);
976       if (*dpx.user.id != '\0')
977         (void) FormatImageProperty(image,"dpx:user.id","%.32s",dpx.user.id);
978       if ((dpx.file.user_size != ~0U) &&
979           ((size_t) dpx.file.user_size > sizeof(dpx.user.id)))
980         {
981           StringInfo
982             *profile;
983
984            profile=AcquireStringInfo(dpx.file.user_size-sizeof(dpx.user.id));
985            offset+=ReadBlob(image,GetStringInfoLength(profile),
986              GetStringInfoDatum(profile));
987            (void) SetImageProfile(image,"dpx",profile);
988            profile=DestroyStringInfo(profile);
989         }
990     }
991   for ( ; offset < (MagickOffsetType) dpx.file.image_offset; offset++)
992     (void) ReadBlobByte(image);
993   /*
994     Read DPX image header.
995   */
996   if (image_info->ping != MagickFalse)
997     {
998       (void) CloseBlob(image);
999       return(GetFirstImageInList(image));
1000     }
1001   /*
1002     Convert DPX raster image to pixel packets.
1003   */
1004   samples_per_pixel=1;
1005   quantum_type=GrayQuantum;
1006   switch (component_type)
1007   {
1008     case CbYCrY422ComponentType:
1009     {
1010       samples_per_pixel=2;
1011       quantum_type=CbYCrYQuantum;
1012       break;
1013     }
1014     case CbYACrYA4224ComponentType:
1015     case CbYCr444ComponentType:
1016     {
1017       samples_per_pixel=3;
1018       quantum_type=CbYCrQuantum;
1019       break;
1020     }
1021     case RGBComponentType:
1022     {
1023       samples_per_pixel=3;
1024       quantum_type=RGBQuantum;
1025       break;
1026     }
1027     case ABGRComponentType:
1028     case RGBAComponentType:
1029     {
1030       image->matte=MagickTrue;
1031       samples_per_pixel=4;
1032       quantum_type=RGBAQuantum;
1033       break;
1034     }
1035     default:
1036       break;
1037   }
1038   switch (component_type)
1039   {
1040     case CbYCrY422ComponentType:
1041     case CbYACrYA4224ComponentType:
1042     case CbYCr444ComponentType:
1043     {
1044       image->colorspace=Rec709YCbCrColorspace;
1045       break;
1046     }
1047     case LumaComponentType:
1048     {
1049       image->colorspace=RGBColorspace;
1050       break;
1051     }
1052     default:
1053     {
1054       image->colorspace=RGBColorspace;
1055       if (dpx.image.image_element[0].transfer == LogarithmicColorimetric)
1056         image->colorspace=LogColorspace;
1057       if (dpx.image.image_element[0].transfer == PrintingDensityColorimetric)
1058         image->colorspace=LogColorspace;
1059       break;
1060     }
1061   }
1062   extent=GetBytesPerRow(image->columns,samples_per_pixel,image->depth,
1063     dpx.image.image_element[0].packing == 0 ? MagickFalse : MagickTrue);
1064   /*
1065     DPX any-bit pixel format.
1066   */
1067   status=MagickTrue;
1068   row=0;
1069   quantum_info=AcquireQuantumInfo(image_info,image);
1070   if (quantum_info == (QuantumInfo *) NULL)
1071     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1072   SetQuantumQuantum(quantum_info,32);
1073   SetQuantumPack(quantum_info,dpx.image.image_element[0].packing == 0 ?
1074     MagickTrue : MagickFalse);
1075   for (y=0; y < (ssize_t) image->rows; y++)
1076   {
1077     MagickBooleanType
1078       sync;
1079
1080     register PixelPacket
1081       *q;
1082
1083     size_t
1084       length;
1085
1086     ssize_t
1087       count,
1088       offset;
1089
1090     unsigned char
1091       *pixels;
1092
1093     if (status == MagickFalse)
1094       continue;
1095     pixels=GetQuantumPixels(quantum_info);
1096     {
1097       count=ReadBlob(image,extent,pixels);
1098       if ((image->progress_monitor != (MagickProgressMonitor) NULL) &&
1099           (image->previous == (Image *) NULL))
1100         {
1101           MagickBooleanType
1102             proceed;
1103
1104           proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) row,
1105             image->rows);
1106           if (proceed == MagickFalse)
1107             status=MagickFalse;
1108         }
1109       offset=row++;
1110     }
1111     if (count != (ssize_t) extent)
1112       status=MagickFalse;
1113     q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
1114     if (q == (PixelPacket *) NULL)
1115       {
1116         status=MagickFalse;
1117         continue;
1118       }
1119     length=ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1120       quantum_type,pixels,exception);
1121     (void) length;
1122     sync=SyncAuthenticPixels(image,exception);
1123     if (sync == MagickFalse)
1124       status=MagickFalse;
1125   }
1126   quantum_info=DestroyQuantumInfo(quantum_info);
1127   if (status == MagickFalse)
1128     ThrowReaderException(CorruptImageError,"UnableToReadImageData");
1129   SetQuantumImageType(image,quantum_type);
1130   if (EOFBlob(image) != MagickFalse)
1131     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1132       image->filename);
1133   (void) CloseBlob(image);
1134   return(GetFirstImageInList(image));
1135 }
1136 \f
1137 /*
1138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1139 %                                                                             %
1140 %                                                                             %
1141 %                                                                             %
1142 %   R e g i s t e r D P X I m a g e                                           %
1143 %                                                                             %
1144 %                                                                             %
1145 %                                                                             %
1146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1147 %
1148 %  RegisterDPXImage() adds properties for the DPX image format to
1149 %  the list of supported formats.  The properties include the image format
1150 %  tag, a method to read and/or write the format, whether the format
1151 %  supports the saving of more than one frame to the same file or blob,
1152 %  whether the format supports native in-memory I/O, and a brief
1153 %  description of the format.
1154 %
1155 %  The format of the RegisterDPXImage method is:
1156 %
1157 %      size_t RegisterDPXImage(void)
1158 %
1159 */
1160 ModuleExport size_t RegisterDPXImage(void)
1161 {
1162   MagickInfo
1163     *entry;
1164
1165   static const char
1166     *DPXNote =
1167     {
1168       "Digital Moving Picture Exchange Bitmap, Version 2.0.\n"
1169       "See SMPTE 268M-2003 specification at http://www.smtpe.org\n"
1170     };
1171
1172   entry=SetMagickInfo("DPX");
1173   entry->decoder=(DecodeImageHandler *) ReadDPXImage;
1174   entry->encoder=(EncodeImageHandler *) WriteDPXImage;
1175   entry->magick=(IsImageFormatHandler *) IsDPX;
1176   entry->adjoin=MagickFalse;
1177   entry->description=ConstantString("SMPTE 268M-2003 (DPX 2.0)");
1178   entry->note=ConstantString(DPXNote);
1179   entry->module=ConstantString("DPX");
1180   (void) RegisterMagickInfo(entry);
1181   return(MagickImageCoderSignature);
1182 }
1183 \f
1184 /*
1185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1186 %                                                                             %
1187 %                                                                             %
1188 %                                                                             %
1189 %   U n r e g i s t e r D P X I m a g e                                       %
1190 %                                                                             %
1191 %                                                                             %
1192 %                                                                             %
1193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1194 %
1195 %  UnregisterDPXImage() removes format registrations made by the
1196 %  DPX module from the list of supported formats.
1197 %
1198 %  The format of the UnregisterDPXImage method is:
1199 %
1200 %      UnregisterDPXImage(void)
1201 %
1202 */
1203 ModuleExport void UnregisterDPXImage(void)
1204 {
1205   (void) UnregisterMagickInfo("DPX");
1206 }
1207 \f
1208 /*
1209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1210 %                                                                             %
1211 %                                                                             %
1212 %                                                                             %
1213 %   W r i t e D P X I m a g e                                                 %
1214 %                                                                             %
1215 %                                                                             %
1216 %                                                                             %
1217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1218 %
1219 %  WriteDPXImage() writes an image in DPX encoded image format.
1220 %
1221 %  The format of the WriteDPXImage method is:
1222 %
1223 %      MagickBooleanType WriteDPXImage(const ImageInfo *image_info,Image *image)
1224 %
1225 %  A description of each parameter follows.
1226 %
1227 %    o image_info: the image info.
1228 %
1229 %    o image:  The image.
1230 %
1231 */
1232
1233 static inline const char *GetDPXProperty(const ImageInfo *image_info,
1234   const Image *image,const char *property)
1235 {
1236   const char
1237     *value;
1238
1239   value=GetImageOption(image_info,property);
1240   if (value != (const char *) NULL)
1241     return(value);
1242   return(GetImageProperty(image,property));
1243 }
1244
1245 static unsigned int StringToTimeCode(const char *key)
1246 {
1247   char
1248     buffer[2];
1249
1250   register ssize_t
1251     i;
1252
1253   unsigned int
1254     shift,
1255     value;
1256
1257   value=0;
1258   shift=28;
1259   buffer[1]='\0';
1260   for (i=0; (*key != 0) && (i < 11); i++)
1261   {
1262     if (isxdigit((int) ((unsigned char) *key)) == 0)
1263       {
1264         key++;
1265         continue;
1266       }
1267     buffer[0]=(*key++);
1268     value|=(unsigned int) ((strtol(buffer,(char **) NULL,16)) << shift);
1269     shift-=4;
1270   }
1271   return(value);
1272 }
1273
1274 static MagickBooleanType WriteDPXImage(const ImageInfo *image_info,Image *image)
1275 {
1276   const char
1277     *value;
1278
1279   const StringInfo
1280     *profile;
1281
1282   DPXInfo
1283     dpx;
1284
1285   MagickBooleanType
1286     status;
1287
1288   MagickOffsetType
1289     offset;
1290
1291   MagickStatusType
1292     flags;
1293
1294   GeometryInfo
1295     geometry_info;
1296
1297   QuantumInfo
1298     *quantum_info;
1299
1300   QuantumType
1301     quantum_type;
1302
1303   register const PixelPacket
1304     *p;
1305
1306   register ssize_t
1307     i;
1308
1309   ssize_t
1310     count,
1311     horizontal_factor,
1312     vertical_factor,
1313     y;
1314
1315   size_t
1316     extent;
1317
1318   time_t
1319     seconds;
1320
1321   unsigned char
1322     *pixels;
1323
1324   /*
1325     Open output image file.
1326   */
1327   assert(image_info != (const ImageInfo *) NULL);
1328   assert(image_info->signature == MagickSignature);
1329   assert(image != (Image *) NULL);
1330   assert(image->signature == MagickSignature);
1331   if (image->debug != MagickFalse)
1332     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1333   horizontal_factor=4;
1334   vertical_factor=4;
1335   if (image_info->sampling_factor != (char *) NULL)
1336     {
1337       GeometryInfo
1338         geometry_info;
1339
1340       MagickStatusType
1341         flags;
1342
1343       flags=ParseGeometry(image_info->sampling_factor,&geometry_info);
1344       horizontal_factor=(ssize_t) geometry_info.rho;
1345       vertical_factor=(ssize_t) geometry_info.sigma;
1346       if ((flags & SigmaValue) == 0)
1347         vertical_factor=horizontal_factor;
1348       if ((horizontal_factor != 1) && (horizontal_factor != 2) &&
1349           (horizontal_factor != 4) && (vertical_factor != 1) &&
1350           (vertical_factor != 2) && (vertical_factor != 4))
1351         ThrowWriterException(CorruptImageError,"UnexpectedSamplingFactor");
1352     }
1353   if ((image->colorspace == YCbCrColorspace) &&
1354       ((horizontal_factor == 2) || (vertical_factor == 2)))
1355     if ((image->columns % 2) != 0)
1356       image->columns++;
1357   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1358   if (status == MagickFalse)
1359     return(status);
1360   /*
1361     Write file header.
1362   */
1363   (void) ResetMagickMemory(&dpx,0,sizeof(dpx));
1364   offset=0;
1365   dpx.file.magic=0x53445058U;
1366   offset+=WriteBlobLong(image,dpx.file.magic);
1367   dpx.file.image_offset=0x2000U;
1368   profile=GetImageProfile(image,"dpx");
1369   if (profile != (StringInfo *) NULL)
1370     {
1371       if (GetStringInfoLength(profile) > 1048576)
1372         ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1373       dpx.file.image_offset+=(unsigned int) GetStringInfoLength(profile);
1374       dpx.file.image_offset=(((dpx.file.image_offset+0x2000-1)/0x2000)*0x2000);
1375     }
1376   offset+=WriteBlobLong(image,dpx.file.image_offset);
1377   (void) strncpy(dpx.file.version,"V2.0",sizeof(dpx.file.version));
1378   offset+=WriteBlob(image,8,(unsigned char *) &dpx.file.version);
1379   dpx.file.file_size=(unsigned int) (4U*image->columns*image->rows+
1380     dpx.file.image_offset);
1381   offset+=WriteBlobLong(image,dpx.file.file_size);
1382   dpx.file.ditto_key=1U;  /* new frame */
1383   offset+=WriteBlobLong(image,dpx.file.ditto_key);
1384   dpx.file.generic_size=0x00000680U;
1385   offset+=WriteBlobLong(image,dpx.file.generic_size);
1386   dpx.file.industry_size=0x00000180U;
1387   offset+=WriteBlobLong(image,dpx.file.industry_size);
1388   dpx.file.user_size=0;
1389   if (profile != (StringInfo *) NULL)
1390     {
1391       dpx.file.user_size+=(unsigned int) GetStringInfoLength(profile);
1392       dpx.file.user_size=(((dpx.file.user_size+0x2000-1)/0x2000)*0x2000);
1393     }
1394   offset+=WriteBlobLong(image,dpx.file.user_size);
1395   value=GetDPXProperty(image_info,image,"dpx:file.filename");
1396   if (value != (const char *) NULL)
1397     (void) strncpy(dpx.file.filename,value,sizeof(dpx.file.filename));
1398   offset+=WriteBlob(image,sizeof(dpx.file.filename),(unsigned char *)
1399     dpx.file.filename);
1400   seconds=time((time_t *) NULL);
1401   (void) FormatMagickTime(seconds,sizeof(dpx.file.timestamp),
1402     dpx.file.timestamp);
1403   offset+=WriteBlob(image,sizeof(dpx.file.timestamp),(unsigned char *)
1404     dpx.file.timestamp);
1405   (void) strncpy(dpx.file.creator,GetMagickVersion((size_t *) NULL),
1406     sizeof(dpx.file.creator));
1407   value=GetDPXProperty(image_info,image,"dpx:file.creator");
1408   if (value != (const char *) NULL)
1409     (void) strncpy(dpx.file.creator,value,sizeof(dpx.file.creator));
1410   offset+=WriteBlob(image,sizeof(dpx.file.creator),(unsigned char *)
1411     dpx.file.creator);
1412   value=GetDPXProperty(image_info,image,"dpx:file.project");
1413   if (value != (const char *) NULL)
1414     (void) strncpy(dpx.file.project,value,sizeof(dpx.file.project));
1415   offset+=WriteBlob(image,sizeof(dpx.file.project),(unsigned char *)
1416     dpx.file.project);
1417   value=GetDPXProperty(image_info,image,"dpx:file.copyright");
1418   if (value != (const char *) NULL)
1419     (void) strncpy(dpx.file.copyright,value,
1420       sizeof(dpx.file.copyright));
1421   offset+=WriteBlob(image,sizeof(dpx.file.copyright),(unsigned char *)
1422     dpx.file.copyright);
1423   dpx.file.encrypt_key=(~0U);
1424   offset+=WriteBlobLong(image,dpx.file.encrypt_key);
1425   offset+=WriteBlob(image,sizeof(dpx.file.reserve),(unsigned char *)
1426     dpx.file.reserve);
1427   /*
1428     Write image header.
1429   */
1430   dpx.image.orientation=0x00;  /* left-to-right; top-to-bottom */
1431   offset+=WriteBlobShort(image,dpx.image.orientation);
1432   dpx.image.number_elements=1;
1433   offset+=WriteBlobShort(image,dpx.image.number_elements);
1434   if ((image->columns != (unsigned int) image->columns) ||
1435       (image->rows != (unsigned int) image->rows))
1436     ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1437   offset+=WriteBlobLong(image,(unsigned int) image->columns);
1438   offset+=WriteBlobLong(image,(unsigned int) image->rows);
1439   for (i=0; i < 8; i++)
1440   {
1441     dpx.image.image_element[i].data_sign=0U;
1442     offset+=WriteBlobLong(image,dpx.image.image_element[i].data_sign);
1443     dpx.image.image_element[i].low_data=0U;
1444     offset+=WriteBlobLong(image,dpx.image.image_element[i].low_data);
1445     dpx.image.image_element[i].low_quantity=0.0f;
1446     offset+=WriteBlobFloat(image,dpx.image.image_element[i].low_quantity);
1447     dpx.image.image_element[i].high_data=0U;
1448     offset+=WriteBlobLong(image,dpx.image.image_element[i].high_data);
1449     dpx.image.image_element[i].high_quantity=0.0f;
1450     offset+=WriteBlobFloat(image,dpx.image.image_element[i].high_quantity);
1451     dpx.image.image_element[i].descriptor=0;
1452     if (i == 0)
1453       switch (image->colorspace)
1454       {
1455         case Rec601YCbCrColorspace:
1456         case Rec709YCbCrColorspace:
1457         case YCbCrColorspace:
1458         {
1459           dpx.image.image_element[i].descriptor=CbYCr444ComponentType;
1460           if (image->matte != MagickFalse)
1461             dpx.image.image_element[i].descriptor=CbYCrA4444ComponentType;
1462           break;
1463         }
1464         default:
1465         {
1466           dpx.image.image_element[i].descriptor=RGBComponentType;
1467           if (image->matte != MagickFalse)
1468             dpx.image.image_element[i].descriptor=RGBAComponentType;
1469           if ((image_info->type != TrueColorType) &&
1470               (image->matte == MagickFalse) &&
1471               (IsGrayImage(image,&image->exception) != MagickFalse))
1472             dpx.image.image_element[i].descriptor=LumaComponentType;
1473           break;
1474         }
1475       }
1476     offset+=WriteBlobByte(image,dpx.image.image_element[i].descriptor);
1477     dpx.image.image_element[i].transfer=0;
1478     if (image->colorspace == LogColorspace)
1479       dpx.image.image_element[0].transfer=PrintingDensityColorimetric;
1480     offset+=WriteBlobByte(image,dpx.image.image_element[i].transfer);
1481     dpx.image.image_element[i].colorimetric=0;
1482     offset+=WriteBlobByte(image,dpx.image.image_element[i].colorimetric);
1483     dpx.image.image_element[i].bit_size=0;
1484     if (i == 0)
1485       dpx.image.image_element[i].bit_size=(unsigned char) image->depth;
1486     offset+=WriteBlobByte(image,dpx.image.image_element[i].bit_size);
1487     dpx.image.image_element[i].packing=0;
1488     if ((image->depth == 10) || (image->depth == 12))
1489       dpx.image.image_element[i].packing=1;
1490     offset+=WriteBlobShort(image,dpx.image.image_element[i].packing);
1491     dpx.image.image_element[i].encoding=0;
1492     offset+=WriteBlobShort(image,dpx.image.image_element[i].encoding);
1493     dpx.image.image_element[i].data_offset=0U;
1494     if (i == 0)
1495       dpx.image.image_element[i].data_offset=dpx.file.image_offset;
1496     offset+=WriteBlobLong(image,dpx.image.image_element[i].data_offset);
1497     dpx.image.image_element[i].end_of_line_padding=0U;
1498     offset+=WriteBlobLong(image,dpx.image.image_element[i].end_of_line_padding);
1499     offset+=WriteBlobLong(image,
1500       dpx.image.image_element[i].end_of_image_padding);
1501     offset+=WriteBlob(image,sizeof(dpx.image.image_element[i].description),
1502       (unsigned char *) dpx.image.image_element[i].description);
1503   }
1504   offset+=WriteBlob(image,sizeof(dpx.image.reserve),(unsigned char *)
1505     dpx.image.reserve);
1506   /*
1507     Write orientation header.
1508   */
1509   if ((image->rows != image->magick_rows) ||
1510       (image->columns != image->magick_columns))
1511     {
1512       /*
1513         These properties are not valid if image size changed.
1514       */
1515       (void) DeleteImageProperty(image,"dpx:orientation.x_offset");
1516       (void) DeleteImageProperty(image,"dpx:orientation.y_offset");
1517       (void) DeleteImageProperty(image,"dpx:orientation.x_center");
1518       (void) DeleteImageProperty(image,"dpx:orientation.y_center");
1519       (void) DeleteImageProperty(image,"dpx:orientation.x_size");
1520       (void) DeleteImageProperty(image,"dpx:orientation.y_size");
1521     }
1522   dpx.orientation.x_offset=0U;
1523   value=GetDPXProperty(image_info,image,"dpx:orientation.x_offset");
1524   if (value != (const char *) NULL)
1525     dpx.orientation.x_offset=(unsigned int) StringToUnsignedLong(value);
1526   offset+=WriteBlobLong(image,dpx.orientation.x_offset);
1527   dpx.orientation.y_offset=0U;
1528   value=GetDPXProperty(image_info,image,"dpx:orientation.y_offset");
1529   if (value != (const char *) NULL)
1530     dpx.orientation.y_offset=(unsigned int) StringToUnsignedLong(value);
1531   offset+=WriteBlobLong(image,dpx.orientation.y_offset);
1532   dpx.orientation.x_center=0.0f;
1533   value=GetDPXProperty(image_info,image,"dpx:orientation.x_center");
1534   if (value != (const char *) NULL)
1535     dpx.orientation.x_center=StringToDouble(value);
1536   offset+=WriteBlobFloat(image,dpx.orientation.x_center);
1537   dpx.orientation.y_center=0.0f;
1538   value=GetDPXProperty(image_info,image,"dpx:orientation.y_center");
1539   if (value != (const char *) NULL)
1540     dpx.orientation.y_center=StringToDouble(value);
1541   offset+=WriteBlobFloat(image,dpx.orientation.y_center);
1542   dpx.orientation.x_size=0U;
1543   value=GetDPXProperty(image_info,image,"dpx:orientation.x_size");
1544   if (value != (const char *) NULL)
1545     dpx.orientation.x_size=(unsigned int) StringToUnsignedLong(value);
1546   offset+=WriteBlobLong(image,dpx.orientation.x_size);
1547   dpx.orientation.y_size=0U;
1548   value=GetDPXProperty(image_info,image,"dpx:orientation.y_size");
1549   if (value != (const char *) NULL)
1550     dpx.orientation.y_size=(unsigned int) StringToUnsignedLong(value);
1551   offset+=WriteBlobLong(image,dpx.orientation.y_size);
1552   value=GetDPXProperty(image_info,image,"dpx:orientation.filename");
1553   if (value != (const char *) NULL)
1554     (void) strncpy(dpx.orientation.filename,value,
1555       sizeof(dpx.orientation.filename));
1556   offset+=WriteBlob(image,sizeof(dpx.orientation.filename),(unsigned char *)
1557     dpx.orientation.filename);
1558   offset+=WriteBlob(image,sizeof(dpx.orientation.timestamp),(unsigned char *)
1559     dpx.orientation.timestamp);
1560   value=GetDPXProperty(image_info,image,"dpx:orientation.device");
1561   if (value != (const char *) NULL)
1562     (void) strncpy(dpx.orientation.device,value,sizeof(dpx.orientation.device));
1563   offset+=WriteBlob(image,sizeof(dpx.orientation.device),(unsigned char *)
1564     dpx.orientation.device);
1565   value=GetDPXProperty(image_info,image,"dpx:orientation.serial");
1566   if (value != (const char *) NULL)
1567     (void) strncpy(dpx.orientation.serial,value,sizeof(dpx.orientation.serial));
1568   offset+=WriteBlob(image,sizeof(dpx.orientation.serial),(unsigned char *)
1569     dpx.orientation.serial);
1570   for (i=0; i < 4; i++)
1571     dpx.orientation.border[i]=0;
1572   value=GetDPXProperty(image_info,image,"dpx:orientation.border");
1573   if (value != (const char *) NULL)
1574     {
1575       flags=ParseGeometry(value,&geometry_info);
1576       if ((flags & SigmaValue) == 0)
1577         geometry_info.sigma=geometry_info.rho;
1578       dpx.orientation.border[0]=(unsigned short) (geometry_info.rho+0.5);
1579       dpx.orientation.border[1]=(unsigned short) (geometry_info.sigma+0.5);
1580       dpx.orientation.border[2]=(unsigned short) (geometry_info.xi+0.5);
1581       dpx.orientation.border[3]=(unsigned short) (geometry_info.psi+0.5);
1582     }
1583   for (i=0; i < 4; i++)
1584     offset+=WriteBlobShort(image,dpx.orientation.border[i]);
1585   for (i=0; i < 2; i++)
1586     dpx.orientation.aspect_ratio[i]=0U;
1587   value=GetDPXProperty(image_info,image,"dpx:orientation.aspect_ratio");
1588   if (value != (const char *) NULL)
1589     {
1590       flags=ParseGeometry(value,&geometry_info);
1591       if ((flags & SigmaValue) == 0)
1592         geometry_info.sigma=geometry_info.rho;
1593       dpx.orientation.aspect_ratio[0]=(unsigned int) (geometry_info.rho+0.5);
1594       dpx.orientation.aspect_ratio[1]=(unsigned int) (geometry_info.sigma+0.5);
1595     }
1596   for (i=0; i < 2; i++)
1597     offset+=WriteBlobLong(image,dpx.orientation.aspect_ratio[i]);
1598   offset+=WriteBlob(image,sizeof(dpx.orientation.reserve),(unsigned char *)
1599     dpx.orientation.reserve);
1600   /*
1601     Write film header.
1602   */
1603   *dpx.film.id='\0';
1604   value=GetDPXProperty(image_info,image,"dpx:film.id");
1605   if (value != (const char *) NULL)
1606     (void) strncpy(dpx.film.id,value,sizeof(dpx.film.id));
1607   offset+=WriteBlob(image,sizeof(dpx.film.id),(unsigned char *) dpx.film.id);
1608   *dpx.film.type='\0';
1609   value=GetDPXProperty(image_info,image,"dpx:film.type");
1610   if (value != (const char *) NULL)
1611     (void) strncpy(dpx.film.type,value,sizeof(dpx.film.type));
1612   offset+=WriteBlob(image,sizeof(dpx.film.type),(unsigned char *)
1613     dpx.film.type);
1614   *dpx.film.offset='\0';
1615   value=GetDPXProperty(image_info,image,"dpx:film.offset");
1616   if (value != (const char *) NULL)
1617     (void) strncpy(dpx.film.offset,value,sizeof(dpx.film.offset));
1618   offset+=WriteBlob(image,sizeof(dpx.film.offset),(unsigned char *)
1619     dpx.film.offset);
1620   *dpx.film.prefix='\0';
1621   value=GetDPXProperty(image_info,image,"dpx:film.prefix");
1622   if (value != (const char *) NULL)
1623     (void) strncpy(dpx.film.prefix,value,sizeof(dpx.film.prefix));
1624   offset+=WriteBlob(image,sizeof(dpx.film.prefix),(unsigned char *)
1625     dpx.film.prefix);
1626   *dpx.film.count='\0';
1627   value=GetDPXProperty(image_info,image,"dpx:film.count");
1628   if (value != (const char *) NULL)
1629     (void) strncpy(dpx.film.count,value,sizeof(dpx.film.count));
1630   offset+=WriteBlob(image,sizeof(dpx.film.count),(unsigned char *)
1631     dpx.film.count);
1632   *dpx.film.format='\0';
1633   value=GetDPXProperty(image_info,image,"dpx:film.format");
1634   if (value != (const char *) NULL)
1635     (void) strncpy(dpx.film.format,value,sizeof(dpx.film.format));
1636   offset+=WriteBlob(image,sizeof(dpx.film.format),(unsigned char *)
1637     dpx.film.format);
1638   dpx.film.frame_position=0U;
1639   value=GetDPXProperty(image_info,image,"dpx:film.frame_position");
1640   if (value != (const char *) NULL)
1641     dpx.film.frame_position=(unsigned int) StringToUnsignedLong(value);
1642   offset+=WriteBlobLong(image,dpx.film.frame_position);
1643   dpx.film.sequence_extent=0U;
1644   value=GetDPXProperty(image_info,image,"dpx:film.sequence_extent");
1645   if (value != (const char *) NULL)
1646     dpx.film.sequence_extent=(unsigned int) StringToUnsignedLong(value);
1647   offset+=WriteBlobLong(image,dpx.film.sequence_extent);
1648   dpx.film.held_count=0U;
1649   value=GetDPXProperty(image_info,image,"dpx:film.held_count");
1650   if (value != (const char *) NULL)
1651     dpx.film.held_count=(unsigned int) StringToUnsignedLong(value);
1652   offset+=WriteBlobLong(image,dpx.film.held_count);
1653   dpx.film.frame_rate=0.0f;
1654   value=GetDPXProperty(image_info,image,"dpx:film.frame_rate");
1655   if (value != (const char *) NULL)
1656     dpx.film.frame_rate=StringToDouble(value);
1657   offset+=WriteBlobFloat(image,dpx.film.frame_rate);
1658   dpx.film.shutter_angle=0.0f;
1659   value=GetDPXProperty(image_info,image,"dpx:film.shutter_angle");
1660   if (value != (const char *) NULL)
1661     dpx.film.shutter_angle=StringToDouble(value);
1662   offset+=WriteBlobFloat(image,dpx.film.shutter_angle);
1663   *dpx.film.frame_id='\0';
1664   value=GetDPXProperty(image_info,image,"dpx:film.frame_id");
1665   if (value != (const char *) NULL)
1666     (void) strncpy(dpx.film.frame_id,value,sizeof(dpx.film.frame_id));
1667   offset+=WriteBlob(image,sizeof(dpx.film.frame_id),(unsigned char *)
1668     dpx.film.frame_id);
1669   value=GetDPXProperty(image_info,image,"dpx:film.slate");
1670   if (value != (const char *) NULL)
1671     (void) strncpy(dpx.film.slate,value,sizeof(dpx.film.slate));
1672   offset+=WriteBlob(image,sizeof(dpx.film.slate),(unsigned char *)
1673     dpx.film.slate);
1674   offset+=WriteBlob(image,sizeof(dpx.film.reserve),(unsigned char *)
1675     dpx.film.reserve);
1676   /*
1677     Write television header.
1678   */
1679   value=GetDPXProperty(image_info,image,"dpx:television.time.code");
1680   if (value != (const char *) NULL)
1681     dpx.television.time_code=StringToTimeCode(value);
1682   offset+=WriteBlobLong(image,dpx.television.time_code);
1683   value=GetDPXProperty(image_info,image,"dpx:television.user.bits");
1684   if (value != (const char *) NULL)
1685     dpx.television.user_bits=StringToTimeCode(value);
1686   offset+=WriteBlobLong(image,dpx.television.user_bits);
1687   value=GetDPXProperty(image_info,image,"dpx:television.interlace");
1688   if (value != (const char *) NULL)
1689     dpx.television.interlace=(unsigned char) StringToLong(value);
1690   offset+=WriteBlobByte(image,dpx.television.interlace);
1691   value=GetDPXProperty(image_info,image,"dpx:television.field_number");
1692   if (value != (const char *) NULL)
1693     dpx.television.field_number=(unsigned char) StringToLong(value);
1694   offset+=WriteBlobByte(image,dpx.television.field_number);
1695   dpx.television.video_signal=0;
1696   value=GetDPXProperty(image_info,image,"dpx:television.video_signal");
1697   if (value != (const char *) NULL)
1698     dpx.television.video_signal=(unsigned char) StringToLong(value);
1699   offset+=WriteBlobByte(image,dpx.television.video_signal);
1700   dpx.television.padding=0;
1701   value=GetDPXProperty(image_info,image,"dpx:television.padding");
1702   if (value != (const char *) NULL)
1703     dpx.television.padding=(unsigned char) StringToLong(value);
1704   offset+=WriteBlobByte(image,dpx.television.padding);
1705   dpx.television.horizontal_sample_rate=0.0f;
1706   value=GetDPXProperty(image_info,image,
1707     "dpx:television.horizontal_sample_rate");
1708   if (value != (const char *) NULL)
1709     dpx.television.horizontal_sample_rate=StringToDouble(value);
1710   offset+=WriteBlobFloat(image,dpx.television.horizontal_sample_rate);
1711   dpx.television.vertical_sample_rate=0.0f;
1712   value=GetDPXProperty(image_info,image,"dpx:television.vertical_sample_rate");
1713   if (value != (const char *) NULL)
1714     dpx.television.vertical_sample_rate=StringToDouble(value);
1715   offset+=WriteBlobFloat(image,dpx.television.vertical_sample_rate);
1716   dpx.television.frame_rate=0.0f;
1717   value=GetDPXProperty(image_info,image,"dpx:television.frame_rate");
1718   if (value != (const char *) NULL)
1719     dpx.television.frame_rate=StringToDouble(value);
1720   offset+=WriteBlobFloat(image,dpx.television.frame_rate);
1721   dpx.television.time_offset=0.0f;
1722   value=GetDPXProperty(image_info,image,"dpx:television.time_offset");
1723   if (value != (const char *) NULL)
1724     dpx.television.time_offset=StringToDouble(value);
1725   offset+=WriteBlobFloat(image,dpx.television.time_offset);
1726   dpx.television.gamma=0.0f;
1727   value=GetDPXProperty(image_info,image,"dpx:television.gamma");
1728   if (value != (const char *) NULL)
1729     dpx.television.gamma=StringToDouble(value);
1730   offset+=WriteBlobFloat(image,dpx.television.gamma);
1731   dpx.television.black_level=0.0f;
1732   value=GetDPXProperty(image_info,image,"dpx:television.black_level");
1733   if (value != (const char *) NULL)
1734     dpx.television.black_level=StringToDouble(value);
1735   offset+=WriteBlobFloat(image,dpx.television.black_level);
1736   dpx.television.black_gain=0.0f;
1737   value=GetDPXProperty(image_info,image,"dpx:television.black_gain");
1738   if (value != (const char *) NULL)
1739     dpx.television.black_gain=StringToDouble(value);
1740   offset+=WriteBlobFloat(image,dpx.television.black_gain);
1741   dpx.television.break_point=0.0f;
1742   value=GetDPXProperty(image_info,image,"dpx:television.break_point");
1743   if (value != (const char *) NULL)
1744     dpx.television.break_point=StringToDouble(value);
1745   offset+=WriteBlobFloat(image,dpx.television.break_point);
1746   dpx.television.white_level=0.0f;
1747   value=GetDPXProperty(image_info,image,"dpx:television.white_level");
1748   if (value != (const char *) NULL)
1749     dpx.television.white_level=StringToDouble(value);
1750   offset+=WriteBlobFloat(image,dpx.television.white_level);
1751   dpx.television.integration_times=0.0f;
1752   value=GetDPXProperty(image_info,image,"dpx:television.integration_times");
1753   if (value != (const char *) NULL)
1754     dpx.television.integration_times=StringToDouble(value);
1755   offset+=WriteBlobFloat(image,dpx.television.integration_times);
1756   offset+=WriteBlob(image,sizeof(dpx.television.reserve),(unsigned char *)
1757     dpx.television.reserve);
1758   /*
1759     Write user header.
1760   */
1761   value=GetDPXProperty(image_info,image,"dpx:user.id");
1762   if (value != (const char *) NULL)
1763     (void) strncpy(dpx.user.id,value,sizeof(dpx.user.id));
1764   offset+=WriteBlob(image,sizeof(dpx.user.id),(unsigned char *) dpx.user.id);
1765   if (profile != (StringInfo *) NULL)
1766     offset+=WriteBlob(image,GetStringInfoLength(profile),
1767       GetStringInfoDatum(profile));
1768   while (offset < (MagickOffsetType) dpx.image.image_element[0].data_offset)
1769   {
1770     count=WriteBlobByte(image,0x00);
1771     if (count != 1)
1772       {
1773         ThrowFileException(&image->exception,FileOpenError,"UnableToWriteFile",
1774           image->filename);
1775         break;
1776       }
1777     offset+=count;
1778   }
1779   /*
1780     Convert pixel packets to DPX raster image.
1781   */
1782   quantum_info=AcquireQuantumInfo(image_info,image);
1783   SetQuantumQuantum(quantum_info,32);
1784   SetQuantumPack(quantum_info,dpx.image.image_element[0].packing == 0 ?
1785     MagickTrue : MagickFalse);
1786   quantum_type=RGBQuantum;
1787   if (image->matte != MagickFalse)
1788     quantum_type=RGBAQuantum;
1789   if (image->colorspace == YCbCrColorspace)
1790     {
1791       quantum_type=CbYCrQuantum;
1792       if (image->matte != MagickFalse)
1793         quantum_type=CbYCrAQuantum;
1794       if ((horizontal_factor == 2) || (vertical_factor == 2))
1795         quantum_type=CbYCrYQuantum;
1796     }
1797   extent=GetBytesPerRow(image->columns,image->matte != MagickFalse ? 4UL : 3UL,
1798     image->depth,MagickTrue);
1799   if ((image_info->type != UndefinedType) &&
1800       (image_info->type != TrueColorType) && (image->matte == MagickFalse) &&
1801       (IsGrayImage(image,&image->exception) != MagickFalse))
1802     {
1803       quantum_type=GrayQuantum;
1804       extent=GetBytesPerRow(image->columns,1UL,image->depth,MagickTrue);
1805     }
1806   pixels=GetQuantumPixels(quantum_info);
1807   for (y=0; y < (ssize_t) image->rows; y++)
1808   {
1809     p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1810     if (p == (const PixelPacket *) NULL)
1811       break;
1812     (void) ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1813       quantum_type,pixels,&image->exception);
1814     count=WriteBlob(image,extent,pixels);
1815     if (count != (ssize_t) extent)
1816       break;
1817     status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1818       image->rows);
1819     if (status == MagickFalse)
1820       break;
1821   }
1822   quantum_info=DestroyQuantumInfo(quantum_info);
1823   (void) CloseBlob(image);
1824   return(status);
1825 }