root/ImageMagick/trunk/coders/dpx.c

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