source: ImageMagick/trunk/coders/fpx.c @ 8316

Revision 8316, 36.9 KB checked in by cristy, 12 months ago (diff)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                            FFFFF  PPPP   X   X                              %
7%                            F      P   P   X X                               %
8%                            FFF    PPPP     X                                %
9%                            F      P       X X                               %
10%                            F      P      X   X                              %
11%                                                                             %
12%                                                                             %
13%                     Read/Write FlashPIX Image Format                        %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                                 July 1992                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2012 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 "MagickCore/studio.h"
43#include "MagickCore/attribute.h"
44#include "MagickCore/property.h"
45#include "MagickCore/blob.h"
46#include "MagickCore/blob-private.h"
47#include "MagickCore/cache.h"
48#include "MagickCore/color.h"
49#include "MagickCore/color-private.h"
50#include "MagickCore/colormap.h"
51#include "MagickCore/colorspace.h"
52#include "MagickCore/colorspace-private.h"
53#include "MagickCore/constitute.h"
54#include "MagickCore/exception.h"
55#include "MagickCore/exception-private.h"
56#include "MagickCore/geometry.h"
57#include "MagickCore/image.h"
58#include "MagickCore/image-private.h"
59#include "MagickCore/list.h"
60#include "MagickCore/magick.h"
61#include "MagickCore/memory_.h"
62#include "MagickCore/monitor.h"
63#include "MagickCore/monitor-private.h"
64#include "MagickCore/pixel.h"
65#include "MagickCore/pixel-accessor.h"
66#include "MagickCore/property.h"
67#include "MagickCore/quantum-private.h"
68#include "MagickCore/static.h"
69#include "MagickCore/string_.h"
70#include "MagickCore/module.h"
71#if defined(MAGICKCORE_FPX_DELEGATE)
72#if !defined(vms) && !defined(macintosh) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
73#include <fpxlib.h>
74#else
75#include "Fpxlib.h"
76#endif
77#endif
78
79#if defined(MAGICKCORE_FPX_DELEGATE)
80/*
81  Forward declarations.
82*/
83static MagickBooleanType
84  WriteFPXImage(const ImageInfo *,Image *,ExceptionInfo *);
85#endif
86
87/*
88%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89%                                                                             %
90%                                                                             %
91%                                                                             %
92%   I s F P X                                                                 %
93%                                                                             %
94%                                                                             %
95%                                                                             %
96%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
97%
98%  IsFPX() returns MagickTrue if the image format type, identified by the
99%  magick string, is FPX.
100%
101%  The format of the IsFPX method is:
102%
103%      MagickBooleanType IsFPX(const unsigned char *magick,const size_t length)
104%
105%  A description of each parameter follows:
106%
107%    o magick: compare image format pattern against these bytes.
108%
109%    o length: Specifies the length of the magick string.
110%
111*/
112static MagickBooleanType IsFPX(const unsigned char *magick,const size_t length)
113{
114  if (length < 4)
115    return(MagickFalse);
116  if (memcmp(magick,"\320\317\021\340",4) == 0)
117    return(MagickTrue);
118  return(MagickFalse);
119}
120
121#if defined(MAGICKCORE_FPX_DELEGATE)
122/*
123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
124%                                                                             %
125%                                                                             %
126%                                                                             %
127%   R e a d F P X I m a g e                                                   %
128%                                                                             %
129%                                                                             %
130%                                                                             %
131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132%
133%  ReadFPXImage() reads a FlashPix image file and returns it.  It
134%  allocates the memory necessary for the new Image structure and returns a
135%  pointer to the new image.  This method was contributed by BillR@corbis.com.
136%
137%  The format of the ReadFPXImage method is:
138%
139%      Image *ReadFPXImage(const ImageInfo *image_info,ExceptionInfo *exception)
140%
141%  A description of each parameter follows:
142%
143%    o image_info: the image info.
144%
145%    o exception: return any errors or warnings in this structure.
146%
147*/
148static Image *ReadFPXImage(const ImageInfo *image_info,ExceptionInfo *exception)
149{
150  FPXColorspace
151    colorspace;
152
153  FPXImageComponentDesc
154    *alpha_component,
155    *blue_component,
156    *green_component,
157    *red_component;
158
159  FPXImageDesc
160    fpx_info;
161
162  FPXImageHandle
163    *flashpix;
164
165  FPXStatus
166    fpx_status;
167
168  FPXSummaryInformation
169    summary_info;
170
171  Image
172    *image;
173
174  MagickBooleanType
175    status;
176
177  Quantum
178    index;
179
180  register ssize_t
181    i,
182    x;
183
184  register Quantum
185    *q;
186
187  register unsigned char
188    *a,
189    *b,
190    *g,
191    *r;
192
193  size_t
194    memory_limit;
195
196  ssize_t
197    y;
198
199  unsigned char
200    *pixels;
201
202  unsigned int
203    height,
204    tile_width,
205    tile_height,
206    width;
207
208  size_t
209    scene;
210
211  /*
212    Open image.
213  */
214  assert(image_info != (const ImageInfo *) NULL);
215  assert(image_info->signature == MagickSignature);
216  if (image_info->debug != MagickFalse)
217    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
218      image_info->filename);
219  assert(exception != (ExceptionInfo *) NULL);
220  assert(exception->signature == MagickSignature);
221  image=AcquireImage(image_info,exception);
222  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
223  if (status == MagickFalse)
224    {
225      image=DestroyImageList(image);
226      return((Image *) NULL);
227    }
228  (void) CloseBlob(image);
229  /*
230    Initialize FPX toolkit.
231  */
232  fpx_status=FPX_InitSystem();
233  if (fpx_status != FPX_OK)
234    ThrowReaderException(CoderError,"UnableToInitializeFPXLibrary");
235  memory_limit=20000000;
236  fpx_status=FPX_SetToolkitMemoryLimit(&memory_limit);
237  if (fpx_status != FPX_OK)
238    {
239      FPX_ClearSystem();
240      ThrowReaderException(CoderError,"UnableToInitializeFPXLibrary");
241    }
242  tile_width=64;
243  tile_height=64;
244  flashpix=(FPXImageHandle *) NULL;
245  {
246#if defined(macintosh)
247    FSSpec
248      fsspec;
249
250    FilenameToFSSpec(image->filename,&fsspec);
251    fpx_status=FPX_OpenImageByFilename((const FSSpec &) fsspec,(char *) NULL,
252#else
253    fpx_status=FPX_OpenImageByFilename(image->filename,(char *) NULL,
254#endif
255      &width,&height,&tile_width,&tile_height,&colorspace,&flashpix);
256  }
257  if (fpx_status == FPX_LOW_MEMORY_ERROR)
258    {
259      FPX_ClearSystem();
260      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
261    }
262  if (fpx_status != FPX_OK)
263    {
264      FPX_ClearSystem();
265      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
266        image->filename);
267      image=DestroyImageList(image);
268      return((Image *) NULL);
269    }
270  if (colorspace.numberOfComponents == 0)
271    {
272      FPX_ClearSystem();
273      ThrowReaderException(CorruptImageError,"ImageTypeNotSupported");
274    }
275  if (image_info->view == (char *) NULL)
276    {
277      float
278        aspect_ratio;
279
280      /*
281        Get the aspect ratio.
282      */
283      aspect_ratio=(float) width/height;
284      fpx_status=FPX_GetImageResultAspectRatio(flashpix,&aspect_ratio);
285      if (fpx_status != FPX_OK)
286        ThrowReaderException(DelegateError,"UnableToReadAspectRatio");
287      if (width != (size_t) floor((aspect_ratio*height)+0.5))
288        Swap(width,height);
289    }
290  fpx_status=FPX_GetSummaryInformation(flashpix,&summary_info);
291  if (fpx_status != FPX_OK)
292    {
293      FPX_ClearSystem();
294      ThrowReaderException(DelegateError,"UnableToReadSummaryInfo");
295    }
296  if (summary_info.title_valid)
297    if ((summary_info.title.length != 0) &&
298        (summary_info.title.ptr != (unsigned char *) NULL))
299      {
300        char
301          *label;
302
303        /*
304          Note image label.
305        */
306        label=(char *) NULL;
307        if (~summary_info.title.length >= (MaxTextExtent-1))
308          label=(char *) AcquireQuantumMemory(summary_info.title.length+
309            MaxTextExtent,sizeof(*label));
310        if (label == (char *) NULL)
311          {
312            FPX_ClearSystem();
313            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
314          }
315        (void) CopyMagickString(label,(char *) summary_info.title.ptr,
316          summary_info.title.length+1);
317        (void) SetImageProperty(image,"label",label,exception);
318        label=DestroyString(label);
319      }
320  if (summary_info.comments_valid)
321    if ((summary_info.comments.length != 0) &&
322        (summary_info.comments.ptr != (unsigned char *) NULL))
323      {
324        char
325          *comments;
326
327        /*
328          Note image comment.
329        */
330        comments=(char *) NULL;
331        if (~summary_info.comments.length >= (MaxTextExtent-1))
332          comments=(char *) AcquireQuantumMemory(summary_info.comments.length+
333            MaxTextExtent,sizeof(*comments));
334        if (comments == (char *) NULL)
335          {
336            FPX_ClearSystem();
337            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
338          }
339        (void) CopyMagickString(comments,(char *) summary_info.comments.ptr,
340          summary_info.comments.length+1);
341        (void) SetImageProperty(image,"comment",comments,exception);
342        comments=DestroyString(comments);
343      }
344  /*
345    Determine resolution by scene specification.
346  */
347  for (i=1; ; i++)
348    if (((width >> i) < tile_width) || ((height >> i) < tile_height))
349      break;
350  scene=i;
351  if (image_info->number_scenes != 0)
352    while (scene > image_info->scene)
353    {
354      width>>=1;
355      height>>=1;
356      scene--;
357    }
358  if (image_info->size != (char *) NULL)
359    while ((width > image->columns) || (height > image->rows))
360    {
361      width>>=1;
362      height>>=1;
363      scene--;
364    }
365  image->depth=8;
366  image->columns=width;
367  image->rows=height;
368  if ((colorspace.numberOfComponents % 2) == 0)
369    image->matte=MagickTrue;
370  if (colorspace.numberOfComponents == 1)
371    {
372      /*
373        Create linear colormap.
374      */
375      if (AcquireImageColormap(image,MaxColormapSize,exception) == MagickFalse)
376        {
377          FPX_ClearSystem();
378          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
379        }
380    }
381  if (image_info->ping != MagickFalse)
382    {
383      (void) FPX_CloseImage(flashpix);
384      FPX_ClearSystem();
385      return(GetFirstImageInList(image));
386    }
387  /*
388    Allocate memory for the image and pixel buffer.
389  */
390  pixels=(unsigned char *) AcquireQuantumMemory(image->columns,(tile_height+
391    1UL)*colorspace.numberOfComponents*sizeof(*pixels));
392  if (pixels == (unsigned char *) NULL)
393    {
394      FPX_ClearSystem();
395      (void) FPX_CloseImage(flashpix);
396      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
397    }
398  /*
399    Initialize FlashPix image description.
400  */
401  fpx_info.numberOfComponents=colorspace.numberOfComponents;
402  for (i=0; i < 4; i++)
403  {
404    fpx_info.components[i].myColorType.myDataType=DATA_TYPE_UNSIGNED_BYTE;
405    fpx_info.components[i].horzSubSampFactor=1;
406    fpx_info.components[i].vertSubSampFactor=1;
407    fpx_info.components[i].columnStride=fpx_info.numberOfComponents;
408    fpx_info.components[i].lineStride=image->columns*
409      fpx_info.components[i].columnStride;
410    fpx_info.components[i].theData=pixels+i;
411  }
412  fpx_info.components[0].myColorType.myColor=fpx_info.numberOfComponents > 2 ?
413    NIFRGB_R : MONOCHROME;
414  red_component=(&fpx_info.components[0]);
415  fpx_info.components[1].myColorType.myColor=fpx_info.numberOfComponents > 2 ?
416    NIFRGB_G : ALPHA;
417  green_component=(&fpx_info.components[1]);
418  fpx_info.components[2].myColorType.myColor=NIFRGB_B;
419  blue_component=(&fpx_info.components[2]);
420  fpx_info.components[3].myColorType.myColor=ALPHA;
421  alpha_component=(&fpx_info.components[fpx_info.numberOfComponents-1]);
422  FPX_SetResampleMethod(FPX_LINEAR_INTERPOLATION);
423  /*
424    Initialize image pixels.
425  */
426  for (y=0; y < (ssize_t) image->rows; y++)
427  {
428    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
429    if (q == (Quantum *) NULL)
430      break;
431    if ((y % tile_height) == 0)
432      {
433        /*
434          Read FPX image tile (with or without viewing affine)..
435        */
436        if (image_info->view != (char *) NULL)
437          fpx_status=FPX_ReadImageRectangle(flashpix,0,y,image->columns,y+
438            tile_height-1,scene,&fpx_info);
439        else
440          fpx_status=FPX_ReadImageTransformRectangle(flashpix,0.0F,
441            (float) y/image->rows,(float) image->columns/image->rows,
442            (float) (y+tile_height-1)/image->rows,(ssize_t) image->columns,
443            (ssize_t) tile_height,&fpx_info);
444        if (fpx_status == FPX_LOW_MEMORY_ERROR)
445          {
446            pixels=(unsigned char *) RelinquishMagickMemory(pixels);
447            (void) FPX_CloseImage(flashpix);
448            FPX_ClearSystem();
449            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
450          }
451      }
452    /*
453      Transfer a FPX pixels.
454    */
455    r=red_component->theData+(y % tile_height)*red_component->lineStride;
456    g=green_component->theData+(y % tile_height)*green_component->lineStride;
457    b=blue_component->theData+(y % tile_height)*blue_component->lineStride;
458    a=alpha_component->theData+(y % tile_height)*alpha_component->lineStride;
459    for (x=0; x < (ssize_t) image->columns; x++)
460    {
461      if (fpx_info.numberOfComponents > 2)
462        {
463          SetPixelRed(image,ScaleCharToQuantum(*r),q);
464          SetPixelGreen(image,ScaleCharToQuantum(*g),q);
465          SetPixelBlue(image,ScaleCharToQuantum(*b),q);
466        }
467      else
468        {
469          index=ScaleCharToQuantum(*r);
470          SetPixelBlack(image,index,q);
471          SetPixelRed(image,index,q);
472          SetPixelGreen(image,index,q);
473          SetPixelBlue(image,index,q);
474        }
475      SetPixelAlpha(image,OpaqueAlpha,q);
476      if (image->matte != MagickFalse)
477        SetPixelAlpha(image,ScaleCharToQuantum(*a),q);
478      q+=GetPixelChannels(image);
479      r+=red_component->columnStride;
480      g+=green_component->columnStride;
481      b+=blue_component->columnStride;
482      a+=alpha_component->columnStride;
483    }
484    if (SyncAuthenticPixels(image,exception) == MagickFalse)
485      break;
486    status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
487      image->rows);
488    if (status == MagickFalse)
489      break;
490  }
491  pixels=(unsigned char *) RelinquishMagickMemory(pixels);
492  (void) FPX_CloseImage(flashpix);
493  FPX_ClearSystem();
494  return(GetFirstImageInList(image));
495}
496#endif
497
498/*
499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500%                                                                             %
501%                                                                             %
502%                                                                             %
503%   R e g i s t e r F P X I m a g e                                           %
504%                                                                             %
505%                                                                             %
506%                                                                             %
507%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508%
509%  RegisterFPXImage() adds attributes for the FPX image format to
510%  the list of supported formats.  The attributes include the image format
511%  tag, a method to read and/or write the format, whether the format
512%  supports the saving of more than one frame to the same file or blob,
513%  whether the format supports native in-memory I/O, and a brief
514%  description of the format.
515%
516%  The format of the RegisterFPXImage method is:
517%
518%      size_t RegisterFPXImage(void)
519%
520*/
521ModuleExport size_t RegisterFPXImage(void)
522{
523  MagickInfo
524    *entry;
525
526  entry=SetMagickInfo("FPX");
527#if defined(MAGICKCORE_FPX_DELEGATE)
528  entry->decoder=(DecodeImageHandler *) ReadFPXImage;
529  entry->encoder=(EncodeImageHandler *) WriteFPXImage;
530#endif
531  entry->adjoin=MagickFalse;
532  entry->seekable_stream=MagickTrue;
533  entry->blob_support=MagickFalse;
534  entry->magick=(IsImageFormatHandler *) IsFPX;
535  entry->description=ConstantString("FlashPix Format");
536  entry->module=ConstantString("FPX");
537  (void) RegisterMagickInfo(entry);
538  return(MagickImageCoderSignature);
539}
540
541/*
542%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
543%                                                                             %
544%                                                                             %
545%                                                                             %
546%   U n r e g i s t e r F P X I m a g e                                       %
547%                                                                             %
548%                                                                             %
549%                                                                             %
550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551%
552%  UnregisterFPXImage() removes format registrations made by the
553%  FPX module from the list of supported formats.
554%
555%  The format of the UnregisterFPXImage method is:
556%
557%      UnregisterFPXImage(void)
558%
559*/
560ModuleExport void UnregisterFPXImage(void)
561{
562  (void) UnregisterMagickInfo("FPX");
563}
564
565#if defined(MAGICKCORE_FPX_DELEGATE)
566/*
567%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
568%                                                                             %
569%                                                                             %
570%                                                                             %
571%   W r i t e F P X I m a g e                                                 %
572%                                                                             %
573%                                                                             %
574%                                                                             %
575%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
576%
577%  WriteFPXImage() writes an image in the FlashPix image format.  This
578%  method was contributed by BillR@corbis.com.
579%
580%  The format of the WriteFPXImage method is:
581%
582%      MagickBooleanType WriteFPXImage(const ImageInfo *image_info,
583%        Image *image,ExceptionInfo *exception)
584%
585%  A description of each parameter follows.
586%
587%    o image_info: the image info.
588%
589%    o image:  The image.
590%
591%    o exception: return any errors or warnings in this structure.
592%
593*/
594
595static void ColorTwistMultiply(FPXColorTwistMatrix first,
596  FPXColorTwistMatrix second,FPXColorTwistMatrix *color_twist)
597{
598  /*
599    Matrix multiply.
600  */
601  assert(color_twist != (FPXColorTwistMatrix *) NULL);
602  color_twist->byy=(first.byy*second.byy)+(first.byc1*second.bc1y)+
603    (first.byc2*second.bc2y)+(first.dummy1_zero*second.dummy4_zero);
604  color_twist->byc1=(first.byy*second.byc1)+(first.byc1*second.bc1c1)+
605    (first.byc2*second.bc2c1)+(first.dummy1_zero*second.dummy5_zero);
606  color_twist->byc2=(first.byy*second.byc2)+(first.byc1*second.bc1c2)+
607    (first.byc2*second.bc2c2)+(first.dummy1_zero*second.dummy6_zero);
608  color_twist->dummy1_zero=(first.byy*second.dummy1_zero)+
609    (first.byc1*second.dummy2_zero)+(first.byc2*second.dummy3_zero)+
610    (first.dummy1_zero*second.dummy7_one);
611  color_twist->bc1y=(first.bc1y*second.byy)+(first.bc1c1*second.bc1y)+
612    (first.bc1c2*second.bc2y)+(first.dummy2_zero*second.dummy4_zero);
613  color_twist->bc1c1=(first.bc1y*second.byc1)+(first.bc1c1*second.bc1c1)+
614    (first.bc1c2*second.bc2c1)+(first.dummy2_zero*second.dummy5_zero);
615  color_twist->bc1c2=(first.bc1y*second.byc2)+(first.bc1c1*second.bc1c2)+
616    (first.bc1c2*second.bc2c2)+(first.dummy2_zero*second.dummy6_zero);
617  color_twist->dummy2_zero=(first.bc1y*second.dummy1_zero)+
618    (first.bc1c1*second.dummy2_zero)+(first.bc1c2*second.dummy3_zero)+
619    (first.dummy2_zero*second.dummy7_one);
620  color_twist->bc2y=(first.bc2y*second.byy)+(first.bc2c1*second.bc1y)+
621    (first.bc2c2*second.bc2y)+(first.dummy3_zero*second.dummy4_zero);
622  color_twist->bc2c1=(first.bc2y*second.byc1)+(first.bc2c1*second.bc1c1)+
623    (first.bc2c2*second.bc2c1)+(first.dummy3_zero*second.dummy5_zero);
624  color_twist->bc2c2=(first.bc2y*second.byc2)+(first.bc2c1*second.bc1c2)+
625    (first.bc2c2*second.bc2c2)+(first.dummy3_zero*second.dummy6_zero);
626  color_twist->dummy3_zero=(first.bc2y*second.dummy1_zero)+
627    (first.bc2c1*second.dummy2_zero)+(first.bc2c2*second.dummy3_zero)+
628    (first.dummy3_zero*second.dummy7_one);
629  color_twist->dummy4_zero=(first.dummy4_zero*second.byy)+
630    (first.dummy5_zero*second.bc1y)+(first.dummy6_zero*second.bc2y)+
631    (first.dummy7_one*second.dummy4_zero);
632  color_twist->dummy5_zero=(first.dummy4_zero*second.byc1)+
633    (first.dummy5_zero*second.bc1c1)+(first.dummy6_zero*second.bc2c1)+
634    (first.dummy7_one*second.dummy5_zero);
635  color_twist->dummy6_zero=(first.dummy4_zero*second.byc2)+
636    (first.dummy5_zero*second.bc1c2)+(first.dummy6_zero*second.bc2c2)+
637    (first.dummy7_one*second.dummy6_zero);
638  color_twist->dummy7_one=(first.dummy4_zero*second.dummy1_zero)+
639    (first.dummy5_zero*second.dummy2_zero)+
640    (first.dummy6_zero*second.dummy3_zero)+(first.dummy7_one*second.dummy7_one);
641}
642
643static void SetBrightness(double brightness,FPXColorTwistMatrix *color_twist)
644{
645  FPXColorTwistMatrix
646    effect,
647    result;
648
649  /*
650    Set image brightness in color twist matrix.
651  */
652  assert(color_twist != (FPXColorTwistMatrix *) NULL);
653  brightness=sqrt((double) brightness);
654  effect.byy=brightness;
655  effect.byc1=0.0;
656  effect.byc2=0.0;
657  effect.dummy1_zero=0.0;
658  effect.bc1y=0.0;
659  effect.bc1c1=brightness;
660  effect.bc1c2=0.0;
661  effect.dummy2_zero=0.0;
662  effect.bc2y=0.0;
663  effect.bc2c1=0.0;
664  effect.bc2c2=brightness;
665  effect.dummy3_zero=0.0;
666  effect.dummy4_zero=0.0;
667  effect.dummy5_zero=0.0;
668  effect.dummy6_zero=0.0;
669  effect.dummy7_one=1.0;
670  ColorTwistMultiply(*color_twist,effect,&result);
671  *color_twist=result;
672}
673
674static void SetColorBalance(double red,double green,double blue,
675  FPXColorTwistMatrix *color_twist)
676{
677  FPXColorTwistMatrix
678    blue_effect,
679    green_effect,
680    result,
681    rgb_effect,
682    rg_effect,
683    red_effect;
684
685  /*
686    Set image color balance in color twist matrix.
687  */
688  assert(color_twist != (FPXColorTwistMatrix *) NULL);
689  red=sqrt((double) red)-1.0;
690  green=sqrt((double) green)-1.0;
691  blue=sqrt((double) blue)-1.0;
692  red_effect.byy=1.0;
693  red_effect.byc1=0.0;
694  red_effect.byc2=0.299*red;
695  red_effect.dummy1_zero=0.0;
696  red_effect.bc1y=(-0.299)*red;
697  red_effect.bc1c1=1.0-0.299*red;
698  red_effect.bc1c2=(-0.299)*red;
699  red_effect.dummy2_zero=0.0;
700  red_effect.bc2y=0.701*red;
701  red_effect.bc2c1=0.0;
702  red_effect.bc2c2=1.0+0.402*red;
703  red_effect.dummy3_zero=0.0;
704  red_effect.dummy4_zero=0.0;
705  red_effect.dummy5_zero=0.0;
706  red_effect.dummy6_zero=0.0;
707  red_effect.dummy7_one=1.0;
708  green_effect.byy=1.0;
709  green_effect.byc1=(-0.114)*green;
710  green_effect.byc2=(-0.299)*green;
711  green_effect.dummy1_zero=0.0;
712  green_effect.bc1y=(-0.587)*green;
713  green_effect.bc1c1=1.0-0.473*green;
714  green_effect.bc1c2=0.299*green;
715  green_effect.dummy2_zero=0.0;
716  green_effect.bc2y=(-0.587)*green;
717  green_effect.bc2c1=0.114*green;
718  green_effect.bc2c2=1.0-0.288*green;
719  green_effect.dummy3_zero=0.0;
720  green_effect.dummy4_zero=0.0;
721  green_effect.dummy5_zero=0.0;
722  green_effect.dummy6_zero=0.0;
723  green_effect.dummy7_one=1.0;
724  blue_effect.byy=1.0;
725  blue_effect.byc1=0.114*blue;
726  blue_effect.byc2=0.0;
727  blue_effect.dummy1_zero=0.0;
728  blue_effect.bc1y=0.886*blue;
729  blue_effect.bc1c1=1.0+0.772*blue;
730  blue_effect.bc1c2=0.0;
731  blue_effect.dummy2_zero=0.0;
732  blue_effect.bc2y=(-0.114)*blue;
733  blue_effect.bc2c1=(-0.114)*blue;
734  blue_effect.bc2c2=1.0-0.114*blue;
735  blue_effect.dummy3_zero=0.0;
736  blue_effect.dummy4_zero=0.0;
737  blue_effect.dummy5_zero=0.0;
738  blue_effect.dummy6_zero=0.0;
739  blue_effect.dummy7_one=1.0;
740  ColorTwistMultiply(red_effect,green_effect,&rg_effect);
741  ColorTwistMultiply(rg_effect,blue_effect,&rgb_effect);
742  ColorTwistMultiply(*color_twist,rgb_effect,&result);
743  *color_twist=result;
744}
745
746static void SetSaturation(double saturation,FPXColorTwistMatrix *color_twist)
747{
748  FPXColorTwistMatrix
749    effect,
750    result;
751
752  /*
753    Set image saturation in color twist matrix.
754  */
755  assert(color_twist != (FPXColorTwistMatrix *) NULL);
756  effect.byy=1.0;
757  effect.byc1=0.0;
758  effect.byc2=0.0;
759  effect.dummy1_zero=0.0;
760  effect.bc1y=0.0;
761  effect.bc1c1=saturation;
762  effect.bc1c2=0.0;
763  effect.dummy2_zero=0.0;
764  effect.bc2y=0.0;
765  effect.bc2c1=0.0;
766  effect.bc2c2=saturation;
767  effect.dummy3_zero=0.0;
768  effect.dummy4_zero=0.0;
769  effect.dummy5_zero=0.0;
770  effect.dummy6_zero=0.0;
771  effect.dummy7_one=1.0;
772  ColorTwistMultiply(*color_twist,effect,&result);
773  *color_twist=result;
774}
775
776static MagickBooleanType WriteFPXImage(const ImageInfo *image_info,Image *image,
777  ExceptionInfo *exception)
778{
779  FPXBackground
780    background_color;
781
782  FPXColorspace
783    colorspace =
784    {
785      TRUE, 4,
786      {
787        { NIFRGB_R, DATA_TYPE_UNSIGNED_BYTE },
788        { NIFRGB_G, DATA_TYPE_UNSIGNED_BYTE },
789        { NIFRGB_B, DATA_TYPE_UNSIGNED_BYTE },
790        { ALPHA, DATA_TYPE_UNSIGNED_BYTE }
791      }
792    };
793
794  const char
795    *comment,
796    *label;
797
798  FPXCompressionOption
799    compression;
800
801  FPXImageDesc
802    fpx_info;
803
804  FPXImageHandle
805    *flashpix;
806
807  FPXStatus
808    fpx_status;
809
810  FPXSummaryInformation
811    summary_info;
812
813  MagickBooleanType
814    status;
815
816  QuantumInfo
817    *quantum_info;
818
819  QuantumType
820    quantum_type;
821
822  register const Quantum
823    *p;
824
825  register ssize_t
826    i;
827
828  size_t
829    length,
830    memory_limit;
831
832  ssize_t
833    y;
834
835  unsigned char
836    *pixels;
837
838  unsigned int
839    tile_height,
840    tile_width;
841
842  /*
843    Open input file.
844  */
845  assert(image_info != (const ImageInfo *) NULL);
846  assert(image_info->signature == MagickSignature);
847  assert(image != (Image *) NULL);
848  assert(image->signature == MagickSignature);
849  if (image->debug != MagickFalse)
850    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
851  assert(exception != (ExceptionInfo *) NULL);
852  assert(exception->signature == MagickSignature);
853  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
854  if (status == MagickFalse)
855    return(status);
856  if ((IssRGBColorspace(image->colorspace) == MagickFalse) &&
857      (IsImageGray(image,exception) == MagickFalse))
858    (void) TransformImageColorspace(image,sRGBColorspace,exception);
859  (void) CloseBlob(image);
860  /*
861    Initialize FPX toolkit.
862  */
863  image->depth=8;
864  memory_limit=20000000;
865  fpx_status=FPX_SetToolkitMemoryLimit(&memory_limit);
866  if (fpx_status != FPX_OK)
867    ThrowWriterException(DelegateError,"UnableToInitializeFPXLibrary");
868  tile_width=64;
869  tile_height=64;
870  colorspace.numberOfComponents=3;
871  if (image->matte != MagickFalse)
872    colorspace.numberOfComponents=4;
873  if ((image_info->type != TrueColorType) &&
874      (IsImageGray(image,exception) != MagickFalse))
875    {
876      colorspace.numberOfComponents=1;
877      colorspace.theComponents[0].myColor=MONOCHROME;
878    }
879  background_color.color1_value=0;
880  background_color.color2_value=0;
881  background_color.color3_value=0;
882  background_color.color4_value=0;
883  compression=NONE;
884  if (image->compression == JPEGCompression)
885    compression=JPEG_UNSPECIFIED;
886  if (image_info->compression == JPEGCompression)
887    compression=JPEG_UNSPECIFIED;
888  {
889#if defined(macintosh)
890    FSSpec
891      fsspec;
892
893    FilenameToFSSpec(filename,&fsspec);
894    fpx_status=FPX_CreateImageByFilename((const FSSpec &) fsspec,image->columns,
895#else
896    fpx_status=FPX_CreateImageByFilename(image->filename,image->columns,
897#endif
898      image->rows,tile_width,tile_height,colorspace,background_color,
899      compression,&flashpix);
900  }
901  if (fpx_status != FPX_OK)
902    return(status);
903  if (compression == JPEG_UNSPECIFIED)
904    {
905      /*
906        Initialize the compression by quality for the entire image.
907      */
908      fpx_status=FPX_SetJPEGCompression(flashpix,(unsigned short)
909        image->quality == UndefinedCompressionQuality ? 75 : image->quality);
910      if (fpx_status != FPX_OK)
911        ThrowWriterException(DelegateError,"UnableToSetJPEGLevel");
912    }
913  /*
914    Set image summary info.
915  */
916  summary_info.title_valid=MagickFalse;
917  summary_info.subject_valid=MagickFalse;
918  summary_info.author_valid=MagickFalse;
919  summary_info.comments_valid=MagickFalse;
920  summary_info.keywords_valid=MagickFalse;
921  summary_info.OLEtemplate_valid=MagickFalse;
922  summary_info.last_author_valid=MagickFalse;
923  summary_info.rev_number_valid=MagickFalse;
924  summary_info.edit_time_valid=MagickFalse;
925  summary_info.last_printed_valid=MagickFalse;
926  summary_info.create_dtm_valid=MagickFalse;
927  summary_info.last_save_dtm_valid=MagickFalse;
928  summary_info.page_count_valid=MagickFalse;
929  summary_info.word_count_valid=MagickFalse;
930  summary_info.char_count_valid=MagickFalse;
931  summary_info.thumbnail_valid=MagickFalse;
932  summary_info.appname_valid=MagickFalse;
933  summary_info.security_valid=MagickFalse;
934  label=GetImageProperty(image,"label",exception);
935  if (label != (const char *) NULL)
936    {
937      /*
938        Note image label.
939      */
940      summary_info.title_valid=MagickTrue;
941      length=strlen(label);
942      summary_info.title.length=length;
943      if (~length >= (MaxTextExtent-1))
944        summary_info.title.ptr=(unsigned char *) AcquireQuantumMemory(
945          length+MaxTextExtent,sizeof(*summary_info.title.ptr));
946      if (summary_info.title.ptr == (unsigned char *) NULL)
947        ThrowWriterException(DelegateError,"UnableToSetImageTitle");
948      (void) CopyMagickString((char *) summary_info.title.ptr,label,
949        MaxTextExtent);
950    }
951  comment=GetImageProperty(image,"comment",exception);
952  if (comment != (const char *) NULL)
953    {
954      /*
955        Note image comment.
956      */
957      summary_info.comments_valid=MagickTrue;
958      summary_info.comments.ptr=(unsigned char *) AcquireString(comment);
959      summary_info.comments.length=strlen(comment);
960    }
961  fpx_status=FPX_SetSummaryInformation(flashpix,&summary_info);
962  if (fpx_status != FPX_OK)
963    ThrowWriterException(DelegateError,"UnableToSetSummaryInfo");
964  /*
965    Initialize FlashPix image description.
966  */
967  quantum_info=AcquireQuantumInfo(image_info,image);
968  if (quantum_info == (QuantumInfo *) NULL)
969    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
970  pixels=GetQuantumPixels(quantum_info);
971  fpx_info.numberOfComponents=colorspace.numberOfComponents;
972  for (i=0; i < (ssize_t) fpx_info.numberOfComponents; i++)
973  {
974    fpx_info.components[i].myColorType.myDataType=DATA_TYPE_UNSIGNED_BYTE;
975    fpx_info.components[i].horzSubSampFactor=1;
976    fpx_info.components[i].vertSubSampFactor=1;
977    fpx_info.components[i].columnStride=fpx_info.numberOfComponents;
978    fpx_info.components[i].lineStride=
979      image->columns*fpx_info.components[i].columnStride;
980    fpx_info.components[i].theData=pixels+i;
981  }
982  fpx_info.components[0].myColorType.myColor=fpx_info.numberOfComponents != 1
983    ? NIFRGB_R : MONOCHROME;
984  fpx_info.components[1].myColorType.myColor=NIFRGB_G;
985  fpx_info.components[2].myColorType.myColor=NIFRGB_B;
986  fpx_info.components[3].myColorType.myColor=ALPHA;
987  /*
988    Write image pixelss.
989  */
990  quantum_type=RGBQuantum;
991  if (image->matte != MagickFalse)
992    quantum_type=RGBAQuantum;
993  if (fpx_info.numberOfComponents == 1)
994    quantum_type=GrayQuantum;
995  for (y=0; y < (ssize_t) image->rows; y++)
996  {
997    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
998    if (p == (const Quantum *) NULL)
999      break;
1000    length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1001      quantum_type,pixels,exception);
1002    fpx_status=FPX_WriteImageLine(flashpix,&fpx_info);
1003    if (fpx_status != FPX_OK)
1004      break;
1005    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1006      image->rows);
1007    if (status == MagickFalse)
1008      break;
1009  }
1010  quantum_info=DestroyQuantumInfo(quantum_info);
1011  if (image_info->view != (char *) NULL)
1012    {
1013      FPXAffineMatrix
1014        affine;
1015
1016      FPXColorTwistMatrix
1017        color_twist;
1018
1019      FPXContrastAdjustment
1020        contrast;
1021
1022      FPXFilteringValue
1023        sharpen;
1024
1025      FPXResultAspectRatio
1026        aspect_ratio;
1027
1028      FPXROI
1029        view_rect;
1030
1031      MagickBooleanType
1032        affine_valid,
1033        aspect_ratio_valid,
1034        color_twist_valid,
1035        contrast_valid,
1036        sharpen_valid,
1037        view_rect_valid;
1038
1039      /*
1040        Initialize default viewing parameters.
1041      */
1042      contrast=1.0;
1043      contrast_valid=MagickFalse;
1044      color_twist.byy=1.0;
1045      color_twist.byc1=0.0;
1046      color_twist.byc2=0.0;
1047      color_twist.dummy1_zero=0.0;
1048      color_twist.bc1y=0.0;
1049      color_twist.bc1c1=1.0;
1050      color_twist.bc1c2=0.0;
1051      color_twist.dummy2_zero=0.0;
1052      color_twist.bc2y=0.0;
1053      color_twist.bc2c1=0.0;
1054      color_twist.bc2c2=1.0;
1055      color_twist.dummy3_zero=0.0;
1056      color_twist.dummy4_zero=0.0;
1057      color_twist.dummy5_zero=0.0;
1058      color_twist.dummy6_zero=0.0;
1059      color_twist.dummy7_one=1.0;
1060      color_twist_valid=MagickFalse;
1061      sharpen=0.0;
1062      sharpen_valid=MagickFalse;
1063      aspect_ratio=(double) image->columns/image->rows;
1064      aspect_ratio_valid=MagickFalse;
1065      view_rect.left=(float) 0.1;
1066      view_rect.width=aspect_ratio-0.2;
1067      view_rect.top=(float) 0.1;
1068      view_rect.height=(float) 0.8; /* 1.0-0.2 */
1069      view_rect_valid=MagickFalse;
1070      affine.a11=1.0;
1071      affine.a12=0.0;
1072      affine.a13=0.0;
1073      affine.a14=0.0;
1074      affine.a21=0.0;
1075      affine.a22=1.0;
1076      affine.a23=0.0;
1077      affine.a24=0.0;
1078      affine.a31=0.0;
1079      affine.a32=0.0;
1080      affine.a33=1.0;
1081      affine.a34=0.0;
1082      affine.a41=0.0;
1083      affine.a42=0.0;
1084      affine.a43=0.0;
1085      affine.a44=1.0;
1086      affine_valid=MagickFalse;
1087      if (0)
1088        {
1089          /*
1090            Color color twist.
1091          */
1092          SetBrightness(0.5,&color_twist);
1093          SetSaturation(0.5,&color_twist);
1094          SetColorBalance(0.5,1.0,1.0,&color_twist);
1095          color_twist_valid=MagickTrue;
1096        }
1097      if (affine_valid)
1098        {
1099          fpx_status=FPX_SetImageAffineMatrix(flashpix,&affine);
1100          if (fpx_status != FPX_OK)
1101            ThrowWriterException(DelegateError,"UnableToSetAffineMatrix");
1102        }
1103      if (aspect_ratio_valid)
1104        {
1105          fpx_status=FPX_SetImageResultAspectRatio(flashpix,&aspect_ratio);
1106          if (fpx_status != FPX_OK)
1107            ThrowWriterException(DelegateError,"UnableToSetAspectRatio");
1108        }
1109      if (color_twist_valid)
1110        {
1111          fpx_status=FPX_SetImageColorTwistMatrix(flashpix,&color_twist);
1112          if (fpx_status != FPX_OK)
1113            ThrowWriterException(DelegateError,"UnableToSetColorTwist");
1114        }
1115      if (contrast_valid)
1116        {
1117          fpx_status=FPX_SetImageContrastAdjustment(flashpix,&contrast);
1118          if (fpx_status != FPX_OK)
1119            ThrowWriterException(DelegateError,"UnableToSetContrast");
1120        }
1121      if (sharpen_valid)
1122        {
1123          fpx_status=FPX_SetImageFilteringValue(flashpix,&sharpen);
1124          if (fpx_status != FPX_OK)
1125            ThrowWriterException(DelegateError,"UnableToSetFilteringValue");
1126        }
1127      if (view_rect_valid)
1128        {
1129          fpx_status=FPX_SetImageROI(flashpix,&view_rect);
1130          if (fpx_status != FPX_OK)
1131            ThrowWriterException(DelegateError,"UnableToSetRegionOfInterest");
1132        }
1133    }
1134  (void) FPX_CloseImage(flashpix);
1135  FPX_ClearSystem();
1136  return(MagickTrue);
1137}
1138#endif
Note: See TracBrowser for help on using the repository browser.