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