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