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