root/ImageMagick/trunk/coders/cin.c

Revision 1, 40.1 KB (checked in by cristy, 3 months ago)


Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                             CCCC  IIIII  N   N                              %
7%                            C        I    NN  N                              %
8%                            C        I    N N N                              %
9%                            C        I    N  NN                              %
10%                             CCCC  IIIII  N   N                              %
11%                                                                             %
12%                                                                             %
13%                    Read/Write Kodak Cineon Image Format                     %
14%                Cineon Image Format is a subset of SMTPE CIN                 %
15%                                                                             %
16%                                                                             %
17%                              Software Design                                %
18%                                John Cristy                                  %
19%                             Kelly Bergougnoux                               %
20%                               October 2003                                  %
21%                                                                             %
22%                                                                             %
23%  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
24%  dedicated to making software imaging solutions freely available.           %
25%                                                                             %
26%  You may not use this file except in compliance with the License.  You may  %
27%  obtain a copy of the License at                                            %
28%                                                                             %
29%    http://www.imagemagick.org/script/license.php                            %
30%                                                                             %
31%  Unless required by applicable law or agreed to in writing, software        %
32%  distributed under the License is distributed on an "AS IS" BASIS,          %
33%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
34%  See the License for the specific language governing permissions and        %
35%  limitations under the License.                                             %
36%                                                                             %
37%                                                                             %
38%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39%
40%  Cineon image file format draft is available at
41%  http://www.cineon.com/ff_draft.php.
42%
43%
44*/
45
46/*
47  Include declarations.
48*/
49#include "magick/studio.h"
50#include "magick/blob.h"
51#include "magick/blob-private.h"
52#include "magick/cache.h"
53#include "magick/colorspace.h"
54#include "magick/exception.h"
55#include "magick/exception-private.h"
56#include "magick/image.h"
57#include "magick/image-private.h"
58#include "magick/list.h"
59#include "magick/magick.h"
60#include "magick/memory_.h"
61#include "magick/monitor.h"
62#include "magick/monitor-private.h"
63#include "magick/option.h"
64#include "magick/profile.h"
65#include "magick/property.h"
66#include "magick/quantum-private.h"
67#include "magick/quantum-private.h"
68#include "magick/static.h"
69#include "magick/string_.h"
70#include "magick/module.h"
71
72/*
73  Typedef declaration.
74*/
75typedef struct _CINDataFormatInfo
76{
77  unsigned char
78    interleave,
79    packing,
80    sign,
81    sense;
82
83  unsigned long
84    line_pad,
85    channel_pad;
86
87  unsigned char
88    reserve[20];
89} CINDataFormatInfo;
90
91typedef struct _CINFileInfo
92{
93  unsigned long
94    magic,
95    image_offset,
96    generic_length,
97    industry_length,
98    user_length,
99    file_size;
100
101  char
102    version[8],
103    filename[100],
104    create_date[12],
105    create_time[12],
106    reserve[36];
107} CINFileInfo;
108
109typedef struct _CINFilmInfo
110{
111  char
112    id,
113    type,
114    offset,
115    reserve1;
116
117  unsigned long
118    prefix,
119    count;
120
121  char
122    format[32];
123
124  unsigned long
125    frame_position;
126
127  float
128    frame_rate;
129
130  char
131    frame_id[32],
132    slate_info[200],
133    reserve[740];
134} CINFilmInfo;
135
136typedef struct _CINImageChannel
137{
138  unsigned char
139    designator[2],
140    bits_per_pixel,
141    reserve;
142
143  unsigned long
144    pixels_per_line,
145    lines_per_image;
146
147  float
148    min_data,
149    min_quantity,
150    max_data,
151    max_quantity;
152} CINImageChannel;
153
154typedef struct _CINImageInfo
155{
156  unsigned char
157    orientation,
158    number_channels,
159    reserve1[2];
160
161  CINImageChannel
162    channel[8];
163
164  float
165    white_point[2],
166    red_primary_chromaticity[2],
167    green_primary_chromaticity[2],
168    blue_primary_chromaticity[2];
169
170  char
171    label[200],
172    reserve[28];
173} CINImageInfo;
174
175typedef struct _CINOriginationInfo
176{
177  long
178    x_offset,
179    y_offset;
180
181  char
182    filename[100],
183    create_date[12],
184    create_time[12],
185    device[64],
186    model[32],
187    serial[32];
188
189  float
190    x_pitch,
191    y_pitch,
192    gamma;
193
194  char
195    reserve[40];
196} CINOriginationInfo;
197
198typedef struct _CINUserInfo
199{
200  char
201    id[32];
202} CINUserInfo;
203
204typedef struct CINInfo
205{
206  CINFileInfo
207    file;
208
209  CINImageInfo
210    image;
211
212  CINDataFormatInfo
213    data_format;
214
215  CINOriginationInfo
216    origination;
217
218  CINFilmInfo
219    film;
220
221  CINUserInfo
222    user;
223} CINInfo;
224
225/*
226  Forward declaractions.
227*/
228static MagickBooleanType
229  WriteCINImage(const ImageInfo *,Image *);
230
231/*
232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233%                                                                             %
234%                                                                             %
235%                                                                             %
236%   I s C I N E O N                                                           %
237%                                                                             %
238%                                                                             %
239%                                                                             %
240%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241%
242%  IsCIN() returns MagickTrue if the image format type, identified by the magick
243%  string, is CIN.
244%
245%  The format of the IsCIN method is:
246%
247%      MagickBooleanType IsCIN(const unsigned char *magick,const size_t length)
248%
249%  A description of each parameter follows:
250%
251%    o magick: compare image format pattern against these bytes.
252%
253%    o length: Specifies the length of the magick string.
254%
255*/
256static MagickBooleanType IsCIN(const unsigned char *magick,const size_t length)
257{
258  if (length < 4)
259    return(MagickFalse);
260  if (memcmp(magick,"\200\052\137\327",4) == 0)
261    return(MagickTrue);
262  return(MagickFalse);
263}
264
265/*
266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267%                                                                             %
268%                                                                             %
269%                                                                             %
270%   R e a d C I N E O N I m a g e                                             %
271%                                                                             %
272%                                                                             %
273%                                                                             %
274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275%
276%  ReadCINImage() reads an CIN X image file and returns it.  It allocates
277%  the memory necessary for the new Image structure and returns a point to the
278%  new image.
279%
280%  The format of the ReadCINImage method is:
281%
282%      Image *ReadCINImage(const ImageInfo *image_info,
283%        ExceptionInfo *exception)
284%
285%  A description of each parameter follows:
286%
287%    o image_info: the image info.
288%
289%    o exception: return any errors or warnings in this structure.
290%
291*/
292
293static size_t GetBytesPerRow(unsigned long columns,
294  unsigned long samples_per_pixel,unsigned long bits_per_pixel,
295  MagickBooleanType pad)
296{
297  size_t
298    bytes_per_row;
299
300  switch (bits_per_pixel)
301  {
302    case 1:
303    {
304      bytes_per_row=4*(((size_t) samples_per_pixel*columns*
305        bits_per_pixel+31)/32);
306      break;
307    }
308    case 8:
309    default:
310    {
311      bytes_per_row=4*(((size_t) samples_per_pixel*columns*
312        bits_per_pixel+31)/32);
313      break;
314    }
315    case 10:
316    {
317      if (pad == MagickFalse)
318        {
319          bytes_per_row=4*(((size_t) samples_per_pixel*columns*
320            bits_per_pixel+31)/32);
321          break;
322        }
323      bytes_per_row=4*(((size_t) (32*((samples_per_pixel*columns+2)/3))+31)/32);
324      break;
325    }
326    case 12:
327    {
328      if (pad == MagickFalse)
329        {
330          bytes_per_row=4*(((size_t) samples_per_pixel*columns*
331            bits_per_pixel+31)/32);
332          break;
333        }
334      bytes_per_row=2*(((size_t) (16*samples_per_pixel*columns)+15)/16);
335      break;
336    }
337    case 16:
338    {
339      bytes_per_row=2*(((size_t) samples_per_pixel*columns*
340        bits_per_pixel+8)/16);
341      break;
342    }
343    case 32:
344    {
345      bytes_per_row=4*(((size_t) samples_per_pixel*columns*
346        bits_per_pixel+31)/32);
347      break;
348    }
349    case 64:
350    {
351      bytes_per_row=8*(((size_t) samples_per_pixel*columns*
352        bits_per_pixel+63)/64);
353      break;
354    }
355  }
356  return(bytes_per_row);
357}
358
359static inline MagickBooleanType IsFloatDefined(const float value)
360{
361  union
362  {
363    unsigned long
364      unsigned_value;
365
366    double
367      float_value;
368  } quantum;
369
370  quantum.unsigned_value=0UL;
371  quantum.float_value=value;
372  if (quantum.unsigned_value == 0UL)
373    return(MagickFalse);
374  return(MagickTrue);
375}
376
377static Image *ReadCINImage(const ImageInfo *image_info,
378  ExceptionInfo *exception)
379{
380#define MonoColorType  1
381#define RGBColorType  3
382
383  char
384    magick[4];
385
386  CINInfo
387    cin;
388
389  Image
390    *image;
391
392  long
393    y;
394
395  MagickBooleanType
396    status;
397
398  MagickOffsetType
399    offset;
400
401  QuantumInfo
402    *quantum_info;
403
404  QuantumType
405    quantum_type;
406
407  register long
408    i;
409
410  register PixelPacket
411    *q;
412
413  size_t
414    length;
415
416  ssize_t
417    count;
418
419  unsigned char
420    *pixels;
421
422  unsigned long
423    lsb_first;
424
425  /*
426    Open image file.
427  */
428  assert(image_info != (const ImageInfo *) NULL);
429  assert(image_info->signature == MagickSignature);
430  if (image_info->debug != MagickFalse)
431    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
432      image_info->filename);
433  assert(exception != (ExceptionInfo *) NULL);
434  assert(exception->signature == MagickSignature);
435  image=AcquireImage(image_info);
436  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
437  if (status == MagickFalse)
438    {
439      image=DestroyImageList(image);
440      return((Image *) NULL);
441    }
442  /*
443    File information.
444  */
445  offset=0;
446  count=ReadBlob(image,4,(unsigned char *) magick);
447  offset+=count;
448  if ((count != 4) ||
449      ((LocaleNCompare((char *) magick,"\200\052\137\327",4) != 0)))
450    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
451  image->endian=LSBEndian;
452  lsb_first=1;
453  if ((int) (*(char *) &lsb_first) != 0)
454    image->endian=MSBEndian;
455  cin.file.image_offset=ReadBlobLong(image);
456  offset+=4;
457  cin.file.generic_length=ReadBlobLong(image);
458  offset+=4;
459  cin.file.industry_length=ReadBlobLong(image);
460  offset+=4;
461  cin.file.user_length=ReadBlobLong(image);
462  offset+=4;
463  cin.file.file_size=ReadBlobLong(image);
464  offset+=4;
465  offset+=ReadBlob(image,sizeof(cin.file.version),(unsigned char *)
466    cin.file.version);
467  (void) SetImageProperty(image,"cin:file.version",cin.file.version);
468  offset+=ReadBlob(image,sizeof(cin.file.filename),(unsigned char *)
469    cin.file.filename);
470  (void) SetImageProperty(image,"cin:file.filename",cin.file.filename);
471  offset+=ReadBlob(image,sizeof(cin.file.create_date),(unsigned char *)
472    cin.file.create_date);
473  (void) SetImageProperty(image,"cin:file.create_date",cin.file.create_date);
474  offset+=ReadBlob(image,sizeof(cin.file.create_time),(unsigned char *)
475    cin.file.create_time);
476  (void) SetImageProperty(image,"cin:file.create_time",cin.file.create_time);
477  offset+=ReadBlob(image,sizeof(cin.file.reserve),(unsigned char *)
478    cin.file.reserve);
479  /*
480    Image information.
481  */
482  cin.image.orientation=(unsigned char) ReadBlobByte(image);
483  offset++;
484  if (cin.image.orientation != (unsigned char) (~0U))
485    (void) FormatImageProperty(image,"cin:image.orientation","%d",
486      cin.image.orientation);
487  switch (cin.image.orientation)
488  {
489    default:
490    case 0:  image->orientation=TopLeftOrientation; break;
491    case 1:  image->orientation=TopRightOrientation; break;
492    case 2:  image->orientation=BottomLeftOrientation; break;
493    case 3:  image->orientation=BottomRightOrientation; break;
494    case 4:  image->orientation=LeftTopOrientation; break;
495    case 5:  image->orientation=RightTopOrientation; break;
496    case 6:  image->orientation=LeftBottomOrientation; break;
497    case 7:  image->orientation=RightBottomOrientation; break;
498  }
499  cin.image.number_channels=(unsigned char) ReadBlobByte(image);
500  offset++;
501  offset+=ReadBlob(image,sizeof(cin.image.reserve1),(unsigned char *)
502    cin.image.reserve1);
503  for (i=0; i < 8; i++)
504  {
505    cin.image.channel[i].designator[0]=(unsigned char) ReadBlobByte(image);
506    offset++;
507    cin.image.channel[i].designator[1]=(unsigned char) ReadBlobByte(image);
508    offset++;
509    cin.image.channel[i].bits_per_pixel=(unsigned char) ReadBlobByte(image);
510    offset++;
511    cin.image.channel[i].reserve=(unsigned char) ReadBlobByte(image);
512    offset++;
513    cin.image.channel[i].pixels_per_line=ReadBlobLong(image);
514    offset+=4;
515    cin.image.channel[i].lines_per_image=ReadBlobLong(image);
516    offset+=4;
517    cin.image.channel[i].min_data=ReadBlobFloat(image);
518    offset+=4;
519    cin.image.channel[i].min_quantity=ReadBlobFloat(image);
520    offset+=4;
521    cin.image.channel[i].max_data=ReadBlobFloat(image);
522    offset+=4;
523    cin.image.channel[i].max_quantity=ReadBlobFloat(image);
524    offset+=4;
525  }
526  cin.image.white_point[0]=ReadBlobFloat(image);
527  offset+=4;
528  if (IsFloatDefined(cin.image.white_point[0]) != MagickFalse)
529    image->chromaticity.white_point.x=cin.image.white_point[0];
530  cin.image.white_point[1]=ReadBlobFloat(image);
531  offset+=4;
532  if (IsFloatDefined(cin.image.white_point[1]) != MagickFalse)
533    image->chromaticity.white_point.y=cin.image.white_point[1];
534  cin.image.red_primary_chromaticity[0]=ReadBlobFloat(image);
535  offset+=4;
536  if (IsFloatDefined(cin.image.red_primary_chromaticity[0]) != MagickFalse)
537    image->chromaticity.red_primary.x=cin.image.red_primary_chromaticity[0];
538  cin.image.red_primary_chromaticity[1]=ReadBlobFloat(image);
539  offset+=4;
540  if (IsFloatDefined(cin.image.red_primary_chromaticity[1]) != MagickFalse)
541    image->chromaticity.red_primary.y=cin.image.red_primary_chromaticity[1];
542  cin.image.green_primary_chromaticity[0]=ReadBlobFloat(image);
543  offset+=4;
544  if (IsFloatDefined(cin.image.green_primary_chromaticity[0]) != MagickFalse)
545    image->chromaticity.red_primary.x=cin.image.green_primary_chromaticity[0];
546  cin.image.green_primary_chromaticity[1]=ReadBlobFloat(image);
547  offset+=4;
548  if (IsFloatDefined(cin.image.green_primary_chromaticity[1]) != MagickFalse)
549    image->chromaticity.green_primary.y=cin.image.green_primary_chromaticity[1];
550  cin.image.blue_primary_chromaticity[0]=ReadBlobFloat(image);
551  offset+=4;
552  if (IsFloatDefined(cin.image.blue_primary_chromaticity[0]) != MagickFalse)
553    image->chromaticity.blue_primary.x=cin.image.blue_primary_chromaticity[0];
554  cin.image.blue_primary_chromaticity[1]=ReadBlobFloat(image);
555  offset+=4;
556  if (IsFloatDefined(cin.image.blue_primary_chromaticity[1]) != MagickFalse)
557    image->chromaticity.blue_primary.y=cin.image.blue_primary_chromaticity[1];
558  offset+=ReadBlob(image,sizeof(cin.image.label),(unsigned char *)
559    cin.image.label);
560  (void) SetImageProperty(image,"cin:image.label",cin.image.label);
561  offset+=ReadBlob(image,sizeof(cin.image.reserve),(unsigned char *)
562    cin.image.reserve);
563  /*
564    Image data format information.
565  */
566  cin.data_format.interleave=(unsigned char) ReadBlobByte(image);
567  offset++;
568  cin.data_format.packing=(unsigned char) ReadBlobByte(image);
569  offset++;
570  cin.data_format.sign=(unsigned char) ReadBlobByte(image);
571  offset++;
572  cin.data_format.sense=(unsigned char) ReadBlobByte(image);
573  offset++;
574  cin.data_format.line_pad=ReadBlobLong(image);
575  offset+=4;
576  cin.data_format.channel_pad=ReadBlobLong(image);
577  offset+=4;
578  offset+=ReadBlob(image,sizeof(cin.data_format.reserve),(unsigned char *)
579    cin.data_format.reserve);
580  /*
581    Image origination information.
582  */
583  cin.origination.x_offset=(long) ReadBlobLong(image);
584  offset+=4;
585  if ((unsigned long) cin.origination.x_offset != ~0UL)
586    (void) FormatImageProperty(image,"cin:origination.x_offset","%ld",
587      cin.origination.x_offset);
588  cin.origination.y_offset=(long) ReadBlobLong(image);
589  offset+=4;
590  if ((unsigned long) cin.origination.y_offset != ~0UL)
591    (void) FormatImageProperty(image,"cin:origination.y_offset","%ld",
592      cin.origination.y_offset);
593  offset+=ReadBlob(image,sizeof(cin.origination.filename),(unsigned char *)
594    cin.origination.filename);
595  (void) SetImageProperty(image,"cin:origination.filename",
596    cin.origination.filename);
597  offset+=ReadBlob(image,sizeof(cin.origination.create_date),(unsigned char *)
598    cin.origination.create_date);
599  (void) SetImageProperty(image,"cin:origination.create_date",
600    cin.origination.create_date);
601  offset+=ReadBlob(image,sizeof(cin.origination.create_time),(unsigned char *)
602    cin.origination.create_time);
603  (void) SetImageProperty(image,"cin:origination.create_time",
604    cin.origination.create_time);
605  offset+=ReadBlob(image,sizeof(cin.origination.device),(unsigned char *)
606    cin.origination.device);
607  (void) SetImageProperty(image,"cin:origination.device",
608    cin.origination.device);
609  offset+=ReadBlob(image,sizeof(cin.origination.model),(unsigned char *)
610    cin.origination.model);
611  (void) SetImageProperty(image,"cin:origination.model",cin.origination.model);
612  offset+=ReadBlob(image,sizeof(cin.origination.serial),(unsigned char *)
613    cin.origination.serial);
614  (void) SetImageProperty(image,"cin:origination.serial",
615    cin.origination.serial);
616  cin.origination.x_pitch=ReadBlobFloat(image);
617  offset+=4;
618  cin.origination.y_pitch=ReadBlobFloat(image);
619  offset+=4;
620  cin.origination.gamma=ReadBlobFloat(image);
621  offset+=4;
622  if (IsFloatDefined(cin.origination.gamma) != MagickFalse)
623    image->gamma=cin.origination.gamma;
624  offset+=ReadBlob(image,sizeof(cin.origination.reserve),(unsigned char *)
625    cin.origination.reserve);
626  if ((cin.file.image_offset > 2048) && (cin.file.user_length != 0))
627    {
628      /*
629        Image film information.
630      */
631      cin.film.id=ReadBlobByte(image);
632      offset++;
633      if ((unsigned long) cin.film.id != ~0UL)
634        (void) FormatImageProperty(image,"cin:film.id","%d",cin.film.id);
635      cin.film.type=ReadBlobByte(image);
636      offset++;
637      if ((unsigned long) cin.film.type != ~0UL)
638        (void) FormatImageProperty(image,"cin:film.type","%d",cin.film.type);
639      cin.film.offset=ReadBlobByte(image);
640      offset++;
641      if ((unsigned long) cin.film.offset != ~0UL)
642        (void) FormatImageProperty(image,"cin:film.offset","%d",
643          cin.film.offset);
644      cin.film.reserve1=ReadBlobByte(image);
645      offset++;
646      cin.film.prefix=ReadBlobLong(image);
647      offset+=4;
648      if (cin.film.prefix != ~0UL)
649        (void) FormatImageProperty(image,"cin:film.prefix","%lu",
650          cin.film.prefix);
651      cin.film.count=ReadBlobLong(image);
652      offset+=4;
653      offset+=ReadBlob(image,sizeof(cin.film.format),(unsigned char *)
654        cin.film.format);
655      (void) SetImageProperty(image,"cin:film.format",cin.film.format);
656      cin.film.frame_position=ReadBlobLong(image);
657      offset+=4;
658      if (cin.film.frame_position != ~0UL)
659        (void) FormatImageProperty(image,"cin:film.frame_position","%lu",
660          cin.film.frame_position);
661      cin.film.frame_rate=ReadBlobFloat(image);
662      offset+=4;
663      if (IsFloatDefined(cin.film.frame_rate) != MagickFalse)
664        (void) FormatImageProperty(image,"cin:film.frame_rate","%g",
665          cin.film.frame_rate);
666      offset+=ReadBlob(image,sizeof(cin.film.frame_id),(unsigned char *)
667        cin.film.frame_id);
668      (void) SetImageProperty(image,"cin:film.frame_id",cin.film.frame_id);
669      offset+=ReadBlob(image,sizeof(cin.film.slate_info),(unsigned char *)
670        cin.film.slate_info);
671      (void) SetImageProperty(image,"cin:film.slate_info",cin.film.slate_info);
672      offset+=ReadBlob(image,sizeof(cin.film.reserve),(unsigned char *)
673        cin.film.reserve);
674    }
675  if ((cin.file.image_offset > 2048) && (cin.file.user_length != 0))
676    {
677      StringInfo
678        *profile;
679
680      /*
681        User defined data.
682      */
683      profile=AcquireStringInfo(cin.file.user_length);
684      offset+=ReadBlob(image,GetStringInfoLength(profile),
685        GetStringInfoDatum(profile));
686      (void) SetImageProfile(image,"cin:user.data",profile);
687      profile=DestroyStringInfo(profile);
688    }
689  for ( ; offset < (long) cin.file.image_offset; offset++)
690    (void) ReadBlobByte(image);
691  image->depth=cin.image.channel[0].bits_per_pixel;
692  image->columns=cin.image.channel[0].pixels_per_line;
693  image->rows=cin.image.channel[0].lines_per_image;
694  if (image_info->ping)
695    {
696      (void) CloseBlob(image);
697      return(image);
698    }
699  /*
700    Convert CIN raster image to pixel packets.
701  */
702  quantum_info=AcquireQuantumInfo(image_info,image);
703  if (quantum_info == (QuantumInfo *) NULL)
704    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
705  quantum_info->quantum=32;
706  quantum_info->pack=MagickFalse;
707  quantum_type=RGBQuantum;
708  pixels=GetQuantumPixels(quantum_info);
709  length=GetQuantumExtent(image,quantum_info,quantum_type);
710  length=GetBytesPerRow(image->columns,3,image->depth,MagickTrue);
711  if (cin.image.number_channels == 1)
712    {
713      quantum_type=GrayQuantum;
714      length=GetBytesPerRow(image->columns,1,image->depth,MagickTrue);
715    }
716  for (y=0; y < (long) image->rows; y++)
717  {
718    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
719    if (q == (PixelPacket *) NULL)
720      break;
721    count=ReadBlob(image,length,pixels);
722    if ((size_t) count != length)
723      break;
724    (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
725      quantum_type,pixels,exception);
726    if (SyncAuthenticPixels(image,exception) == MagickFalse)
727      break;
728    if (image->previous == (Image *) NULL)
729      {
730        status=SetImageProgress(image,LoadImageTag,y,image->rows);
731        if (status == MagickFalse)
732          break;
733      }
734  }
735  SetQuantumImageType(image,quantum_type);
736  quantum_info=DestroyQuantumInfo(quantum_info);
737  if (EOFBlob(image) != MagickFalse)
738    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
739      image->filename);
740  image->colorspace=LogColorspace;
741  (void) CloseBlob(image);
742  return(GetFirstImageInList(image));
743}
744
745/*
746%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
747%                                                                             %
748%                                                                             %
749%                                                                             %
750%   R e g i s t e r C I N E O N I m a g e                                     %
751%                                                                             %
752%                                                                             %
753%                                                                             %
754%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
755%
756%  RegisterCINImage() adds attributes for the CIN image format to the list of
757%  of supported formats.  The attributes include the image format tag, a method
758%  to read and/or write the format, whether the format supports the saving of
759%  more than one frame to the same file or blob, whether the format supports
760%  native in-memory I/O, and a brief description of the format.
761%
762%  The format of the RegisterCINImage method is:
763%
764%      unsigned long RegisterCINImage(void)
765%
766*/
767ModuleExport unsigned long RegisterCINImage(void)
768{
769  MagickInfo
770    *entry;
771
772  entry=SetMagickInfo("CIN");
773  entry->decoder=(DecodeImageHandler *) ReadCINImage;
774  entry->encoder=(EncodeImageHandler *) WriteCINImage;
775  entry->magick=(IsImageFormatHandler *) IsCIN;
776  entry->description=ConstantString("Cineon Image File");
777  entry->module=ConstantString("CIN");
778  (void) RegisterMagickInfo(entry);
779  return(MagickImageCoderSignature);
780}
781
782/*
783%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
784%                                                                             %
785%                                                                             %
786%                                                                             %
787%   U n r e g i s t e r C I N E O N I m a g e                                 %
788%                                                                             %
789%                                                                             %
790%                                                                             %
791%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
792%
793%  UnregisterCINImage() removes format registrations made by the CIN module
794%  from the list of supported formats.
795%
796%  The format of the UnregisterCINImage method is:
797%
798%      UnregisterCINImage(void)
799%
800*/
801ModuleExport void UnregisterCINImage(void)
802{
803  (void) UnregisterMagickInfo("CINEON");
804}
805
806/*
807%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
808%                                                                             %
809%                                                                             %
810%                                                                             %
811%   W r i t e C I N E O N I m a g e                                           %
812%                                                                             %
813%                                                                             %
814%                                                                             %
815%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
816%
817%  WriteCINImage() writes an image in CIN encoded image format.
818%
819%  The format of the WriteCINImage method is:
820%
821%      MagickBooleanType WriteCINImage(const ImageInfo *image_info,Image *image)
822%
823%  A description of each parameter follows.
824%
825%    o image_info: the image info.
826%
827%    o image:  The image.
828%
829*/
830
831static inline const char *GetCINProperty(const ImageInfo *image_info,
832  const Image *image,const char *property)
833{
834  const char
835    *value;
836
837  value=GetImageOption(image_info,property);
838  if (value != (const char *) NULL)
839    return(value);
840  return(GetImageProperty(image,property));
841}
842
843static MagickBooleanType WriteCINImage(const ImageInfo *image_info,Image *image)
844{
845  const char
846    *value;
847
848  CINInfo
849    cin;
850
851  const StringInfo
852    *profile;
853
854  long
855    y;
856
857  MagickBooleanType
858    status;
859
860  MagickOffsetType
861    offset;
862
863  QuantumInfo
864    *quantum_info;
865
866  QuantumType
867    quantum_type;
868
869  register const PixelPacket
870    *p;
871
872  register long
873    i;
874
875  size_t
876    length;
877
878  ssize_t
879    count;
880
881  struct tm
882    local_time;
883
884  time_t
885    seconds;
886
887  unsigned char
888    *pixels;
889
890  /*
891    Open output image file.
892  */
893  assert(image_info != (const ImageInfo *) NULL);
894  assert(image_info->signature == MagickSignature);
895  assert(image != (Image *) NULL);
896  assert(image->signature == MagickSignature);
897  if (image->debug != MagickFalse)
898    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
899  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
900  if (status == MagickFalse)
901    return(status);
902  if (image->colorspace != LogColorspace)
903    (void) TransformImageColorspace(image,LogColorspace);
904  /*
905    Write image information.
906  */
907  (void) ResetMagickMemory(&cin,0,sizeof(cin));
908  offset=0;
909  cin.file.magic=0x802A5FD7UL;
910  offset+=WriteBlobLong(image,cin.file.magic);
911  cin.file.image_offset=0x800;
912  profile=GetImageProfile(image,"cin:user.data");
913  if (profile != (StringInfo *) NULL)
914    {
915      cin.file.image_offset+=(unsigned long) GetStringInfoLength(profile);
916      cin.file.image_offset=(((cin.file.image_offset+0x2000-1)/0x2000)*0x2000);
917    }
918  offset+=WriteBlobLong(image,cin.file.image_offset);
919  cin.file.generic_length=0x400;
920  offset+=WriteBlobLong(image,cin.file.generic_length);
921  cin.file.industry_length=0x400;
922  offset+=WriteBlobLong(image,cin.file.industry_length);
923  cin.file.user_length=0x00;
924  if (profile != (StringInfo *) NULL)
925    {
926      cin.file.user_length+=(unsigned long) GetStringInfoLength(profile);
927      cin.file.user_length=(((cin.file.user_length+0x2000-1)/0x2000)*0x2000);
928    }
929  offset+=WriteBlobLong(image,cin.file.user_length);
930  cin.file.file_size=4*image->columns*image->rows+0x2000;
931  offset+=WriteBlobLong(image,cin.file.file_size);
932  (void) CopyMagickString(cin.file.version,"V4.5",sizeof(cin.file.version));
933  offset+=WriteBlob(image,sizeof(cin.file.version),(unsigned char *)
934    cin.file.version);
935  value=GetCINProperty(image_info,image,"cin:file.filename");
936  if (value != (const char *) NULL)
937    (void) CopyMagickString(cin.file.filename,value,sizeof(cin.file.filename));
938  else
939    (void) CopyMagickString(cin.file.filename,image->filename,
940      sizeof(cin.file.filename));
941  offset+=WriteBlob(image,sizeof(cin.file.filename),(unsigned char *)
942    cin.file.filename);
943  seconds=time((time_t *) NULL);
944#if defined(MAGICKCORE_HAVE_LOCALTIME_R)
945  (void) localtime_r(&seconds,&local_time);
946#else
947  (void) memcpy(&local_time,localtime(&seconds),sizeof(local_time));
948#endif
949  (void) strftime(cin.file.create_date,sizeof(cin.file.create_date),"%Y:%m:%d",
950    &local_time);
951  offset+=WriteBlob(image,sizeof(cin.file.create_date),(unsigned char *)
952    cin.file.create_date);
953  (void) strftime(cin.file.create_time,sizeof(cin.file.create_time),
954    "%H:%M:%S%Z",&local_time);
955  offset+=WriteBlob(image,sizeof(cin.file.create_time),(unsigned char *)
956    cin.file.create_time);
957  offset+=WriteBlob(image,sizeof(cin.file.reserve),(unsigned char *)
958    cin.file.reserve);
959  cin.image.orientation=0x00;
960  offset+=WriteBlobByte(image,cin.image.orientation);
961  cin.image.number_channels=3;
962  offset+=WriteBlobByte(image,cin.image.number_channels);
963  offset+=WriteBlob(image,sizeof(cin.image.reserve1),(unsigned char *)
964    cin.image.reserve1);
965  for (i=0; i < 8; i++)
966  {
967    cin.image.channel[i].designator[0]=0; /* universal metric */
968    offset+=WriteBlobByte(image,cin.image.channel[0].designator[0]);
969    cin.image.channel[i].designator[1]=(unsigned char) (i > 3 ? 0 : i+1); /* channel color */;
970    offset+=WriteBlobByte(image,cin.image.channel[1].designator[0]);
971    cin.image.channel[i].bits_per_pixel=(unsigned char) image->depth;
972    offset+=WriteBlobByte(image,cin.image.channel[0].bits_per_pixel);
973    offset+=WriteBlobByte(image,cin.image.channel[0].reserve);
974    cin.image.channel[i].pixels_per_line=image->columns;
975    offset+=WriteBlobLong(image,cin.image.channel[0].pixels_per_line);
976    cin.image.channel[i].lines_per_image=image->rows;
977    offset+=WriteBlobLong(image,cin.image.channel[0].lines_per_image);
978    cin.image.channel[i].min_data=0;
979    offset+=WriteBlobFloat(image,cin.image.channel[0].min_data);
980    cin.image.channel[i].min_quantity=0.0;
981    offset+=WriteBlobFloat(image,cin.image.channel[0].min_quantity);
982    cin.image.channel[i].max_data=(float) ((MagickOffsetType)
983      GetQuantumRange(image->depth));
984    offset+=WriteBlobFloat(image,cin.image.channel[0].max_data);
985    cin.image.channel[i].max_quantity=2.048f;
986    offset+=WriteBlobFloat(image,cin.image.channel[0].max_quantity);
987  }
988  offset+=WriteBlobFloat(image,image->chromaticity.white_point.x);
989  offset+=WriteBlobFloat(image,image->chromaticity.white_point.y);
990  offset+=WriteBlobFloat(image,image->chromaticity.red_primary.x);
991  offset+=WriteBlobFloat(image,image->chromaticity.red_primary.y);
992  offset+=WriteBlobFloat(image,image->chromaticity.green_primary.x);
993  offset+=WriteBlobFloat(image,image->chromaticity.green_primary.y);
994  offset+=WriteBlobFloat(image,image->chromaticity.blue_primary.x);
995  offset+=WriteBlobFloat(image,image->chromaticity.blue_primary.y);
996  value=GetCINProperty(image_info,image,"cin:image.label");
997  if (value != (const char *) NULL)
998    (void) CopyMagickString(cin.image.label,value,sizeof(cin.image.label));
999  offset+=WriteBlob(image,sizeof(cin.image.label),(unsigned char *)
1000    cin.image.label);
1001  offset+=WriteBlob(image,sizeof(cin.image.reserve),(unsigned char *)
1002    cin.image.reserve);
1003  /*
1004    Write data format information.
1005  */
1006  cin.data_format.interleave=0; /* pixel interleave (rgbrgbr...) */
1007  offset+=WriteBlobByte(image,cin.data_format.interleave);
1008  cin.data_format.packing=5; /* packing longword (32bit) boundaries */
1009  offset+=WriteBlobByte(image,cin.data_format.packing);
1010  cin.data_format.sign=0; /* unsigned data */
1011  offset+=WriteBlobByte(image,cin.data_format.sign);
1012  cin.data_format.sense=0; /* image sense: positive image */
1013  offset+=WriteBlobByte(image,cin.data_format.sense);
1014  cin.data_format.line_pad=0;
1015  offset+=WriteBlobLong(image,cin.data_format.line_pad);
1016  cin.data_format.channel_pad=0;
1017  offset+=WriteBlobLong(image,cin.data_format.channel_pad);
1018  offset+=WriteBlob(image,sizeof(cin.data_format.reserve),(unsigned char *)
1019    cin.data_format.reserve);
1020  /*
1021    Write origination information.
1022  */
1023  cin.origination.x_offset=0UL;
1024  value=GetCINProperty(image_info,image,"cin:origination.x_offset");
1025  if (value != (const char *) NULL)
1026    cin.origination.x_offset=atol(value);
1027  offset+=WriteBlobLong(image,(unsigned long) cin.origination.x_offset);
1028  cin.origination.y_offset=0UL;
1029  value=GetCINProperty(image_info,image,"cin:origination.y_offset");
1030  if (value != (const char *) NULL)
1031    cin.origination.y_offset=atol(value);
1032  offset+=WriteBlobLong(image,(unsigned long) cin.origination.y_offset);
1033  value=GetCINProperty(image_info,image,"cin:origination.filename");
1034  if (value != (const char *) NULL)
1035    (void) CopyMagickString(cin.origination.filename,value,
1036      sizeof(cin.origination.filename));
1037  else
1038    (void) CopyMagickString(cin.origination.filename,image->filename,
1039      sizeof(cin.origination.filename));
1040  offset+=WriteBlob(image,sizeof(cin.origination.filename),(unsigned char *)
1041    cin.origination.filename);
1042  seconds=time((time_t *) NULL);
1043  (void) strftime(cin.origination.create_date,
1044    sizeof(cin.origination.create_date),"%Y:%m:%d",&local_time);
1045  offset+=WriteBlob(image,sizeof(cin.origination.create_date),(unsigned char *)
1046    cin.origination.create_date);
1047  (void) strftime(cin.origination.create_time,
1048    sizeof(cin.origination.create_time),"%H:%M:%S%Z",&local_time);
1049  offset+=WriteBlob(image,sizeof(cin.origination.create_time),(unsigned char *)
1050    cin.origination.create_time);
1051  value=GetCINProperty(image_info,image,"cin:origination.device");
1052  if (value != (const char *) NULL)
1053    (void) CopyMagickString(cin.origination.device,value,
1054      sizeof(cin.origination.device));
1055  offset+=WriteBlob(image,sizeof(cin.origination.device),(unsigned char *)
1056    cin.origination.device);
1057  value=GetCINProperty(image_info,image,"cin:origination.model");
1058  if (value != (const char *) NULL)
1059    (void) CopyMagickString(cin.origination.model,value,
1060      sizeof(cin.origination.model));
1061  offset+=WriteBlob(image,sizeof(cin.origination.model),(unsigned char *)
1062    cin.origination.model);
1063  value=GetCINProperty(image_info,image,"cin:origination.serial");
1064  if (value != (const char *) NULL)
1065    (void) CopyMagickString(cin.origination.serial,value,
1066      sizeof(cin.origination.serial));
1067  offset+=WriteBlob(image,sizeof(cin.origination.serial),(unsigned char *)
1068    cin.origination.serial);
1069  cin.origination.x_pitch=0.0f;
1070  value=GetCINProperty(image_info,image,"cin:origination.x_pitch");
1071  if (value != (const char *) NULL)
1072    cin.origination.x_pitch=atof(value);
1073  offset+=WriteBlobFloat(image,cin.origination.x_pitch);
1074  cin.origination.y_pitch=0.0f;
1075  value=GetCINProperty(image_info,image,"cin:origination.y_pitch");
1076  if (value != (const char *) NULL)
1077    cin.origination.y_pitch=atof(value);
1078  offset+=WriteBlobFloat(image,cin.origination.y_pitch);
1079  cin.origination.gamma=image->gamma;
1080  offset+=WriteBlobFloat(image,cin.origination.gamma);
1081  offset+=WriteBlob(image,sizeof(cin.origination.reserve),(unsigned char *)
1082    cin.origination.reserve);
1083  /*
1084    Image film information.
1085  */
1086  cin.film.id=0;
1087  value=GetCINProperty(image_info,image,"cin:film.id");
1088  if (value != (const char *) NULL)
1089    cin.film.id=(char) atoi(value);
1090  offset+=WriteBlobByte(image,(unsigned char) cin.film.id);
1091  cin.film.type=0;
1092  value=GetCINProperty(image_info,image,"cin:film.type");
1093  if (value != (const char *) NULL)
1094    cin.film.type=(char) atoi(value);
1095  offset+=WriteBlobByte(image,(unsigned char) cin.film.type);
1096  cin.film.offset=0;
1097  value=GetCINProperty(image_info,image,"cin:film.offset");
1098  if (value != (const char *) NULL)
1099    cin.film.offset=(char) atoi(value);
1100  offset+=WriteBlobByte(image,(unsigned char) cin.film.offset);
1101  offset+=WriteBlobByte(image,(unsigned char) cin.film.reserve1);
1102  cin.film.prefix=0UL;
1103  value=GetCINProperty(image_info,image,"cin:film.prefix");
1104  if (value != (const char *) NULL)
1105    cin.film.prefix=(unsigned long) atol(value);
1106  offset+=WriteBlobLong(image,cin.film.prefix);
1107  cin.film.count=0UL;
1108  value=GetCINProperty(image_info,image,"cin:film.count");
1109  if (value != (const char *) NULL)
1110    cin.film.count=(unsigned long) atol(value);
1111  offset+=WriteBlobLong(image,cin.film.count);
1112  value=GetCINProperty(image_info,image,"cin:film.format");
1113  if (value != (const char *) NULL)
1114    (void) CopyMagickString(cin.film.format,value,sizeof(cin.film.format));
1115  offset+=WriteBlob(image,sizeof(cin.film.format),(unsigned char *)
1116    cin.film.format);
1117  cin.film.frame_position=0UL;
1118  value=GetCINProperty(image_info,image,"cin:film.frame_position");
1119  if (value != (const char *) NULL)
1120    cin.film.frame_position=(unsigned long) atol(value);
1121  offset+=WriteBlobLong(image,cin.film.frame_position);
1122  cin.film.frame_rate=0.0f;
1123  value=GetCINProperty(image_info,image,"cin:film.frame_rate");
1124  if (value != (const char *) NULL)
1125    cin.film.frame_rate=atof(value);
1126  offset+=WriteBlobFloat(image,cin.film.frame_rate);
1127  value=GetCINProperty(image_info,image,"cin:film.frame_id");
1128  if (value != (const char *) NULL)
1129    (void) CopyMagickString(cin.film.frame_id,value,sizeof(cin.film.frame_id));
1130  offset+=WriteBlob(image,sizeof(cin.film.frame_id),(unsigned char *)
1131    cin.film.frame_id);
1132  value=GetCINProperty(image_info,image,"cin:film.slate_info");
1133  if (value != (const char *) NULL)
1134    (void) CopyMagickString(cin.film.slate_info,value,
1135      sizeof(cin.film.slate_info));
1136  offset+=WriteBlob(image,sizeof(cin.film.slate_info),(unsigned char *)
1137    cin.film.slate_info);
1138  offset+=WriteBlob(image,sizeof(cin.film.reserve),(unsigned char *)
1139    cin.film.reserve);
1140  if (profile != (StringInfo *) NULL)
1141    offset+=WriteBlob(image,GetStringInfoLength(profile),
1142      GetStringInfoDatum(profile));
1143  while (offset < (MagickOffsetType) cin.file.image_offset)
1144    offset+=WriteBlobByte(image,0x00);
1145  /*
1146    Convert pixel packets to CIN raster image.
1147  */
1148  quantum_info=AcquireQuantumInfo(image_info,image);
1149  if (quantum_info == (QuantumInfo *) NULL)
1150    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1151  quantum_info->quantum=32;
1152  quantum_info->pack=MagickFalse;
1153  quantum_type=RGBQuantum;
1154  pixels=GetQuantumPixels(quantum_info);
1155  length=GetBytesPerRow(image->columns,3,image->depth,MagickTrue);
1156  if (0)
1157    {
1158      quantum_type=GrayQuantum;
1159      length=GetBytesPerRow(image->columns,3,image->depth,MagickTrue);
1160    }
1161  for (y=0; y < (long) image->rows; y++)
1162  {
1163    p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1164    if (p == (const PixelPacket *) NULL)
1165      break;
1166    (void) ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1167      quantum_type,pixels,&image->exception);
1168    count=WriteBlob(image,length,pixels);
1169    if (count != (ssize_t) length)
1170      break;
1171    status=SetImageProgress(image,SaveImageTag,y,image->rows);
1172    if (status == MagickFalse)
1173      break;
1174  }
1175  quantum_info=DestroyQuantumInfo(quantum_info);
1176  (void) CloseBlob(image);
1177  return(status);
1178}
Note: See TracBrowser for help on using the browser.