blob: 6215a3536df38c3afaaa21e1a0719735e115e8a7 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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% %
cristy45ef08f2012-12-07 13:13:34 +000020% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% 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*/
cristy0a4d92f2011-08-31 19:25:00 +000042#include "MagickCore/studio.h"
cristyfeb6b412011-08-08 14:03:48 +000043#include "MagickCore/attribute.h"
cristy4c08aed2011-07-01 19:47:50 +000044#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"
cristy6c9c9e82011-08-05 14:27:57 +000050#include "MagickCore/colormap.h"
51#include "MagickCore/colorspace.h"
52#include "MagickCore/colorspace-private.h"
cristy4c08aed2011-07-01 19:47:50 +000053#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"
cristyfeb6b412011-08-08 14:03:48 +000065#include "MagickCore/pixel-accessor.h"
66#include "MagickCore/property.h"
cristy4c08aed2011-07-01 19:47:50 +000067#include "MagickCore/quantum-private.h"
68#include "MagickCore/static.h"
69#include "MagickCore/string_.h"
70#include "MagickCore/module.h"
cristy3ed852e2009-09-05 21:47:34 +000071#if defined(MAGICKCORE_FPX_DELEGATE)
cristy0157aea2010-04-24 21:12:18 +000072#if !defined(vms) && !defined(macintosh) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +000073#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
cristy1e178e72011-08-28 19:44:34 +000084 WriteFPXImage(const ImageInfo *,Image *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +000085#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
cristy3ed852e2009-09-05 21:47:34 +0000174 MagickBooleanType
175 status;
176
cristy4c08aed2011-07-01 19:47:50 +0000177 Quantum
178 index;
cristy3ed852e2009-09-05 21:47:34 +0000179
cristybb503372010-05-27 20:51:26 +0000180 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000181 i,
182 x;
183
cristy4c08aed2011-07-01 19:47:50 +0000184 register Quantum
cristy3ed852e2009-09-05 21:47:34 +0000185 *q;
186
187 register unsigned char
188 *a,
189 *b,
190 *g,
191 *r;
192
cristy3083ad02011-10-12 18:12:35 +0000193 size_t
194 memory_limit;
195
cristy202de442011-04-24 18:19:07 +0000196 ssize_t
197 y;
198
cristy3ed852e2009-09-05 21:47:34 +0000199 unsigned char
200 *pixels;
201
202 unsigned int
203 height,
204 tile_width,
205 tile_height,
206 width;
207
cristybb503372010-05-27 20:51:26 +0000208 size_t
cristy3ed852e2009-09-05 21:47:34 +0000209 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);
cristy9950d572011-10-01 18:22:35 +0000221 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000222 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");
cristybb503372010-05-27 20:51:26 +0000287 if (width != (size_t) floor((aspect_ratio*height)+0.5))
cristy3ed852e2009-09-05 21:47:34 +0000288 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;
cristy37e0b382011-06-07 13:31:21 +0000307 if (~summary_info.title.length >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +0000308 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);
cristyd15e6592011-10-15 00:13:06 +0000317 (void) SetImageProperty(image,"label",label,exception);
cristy3ed852e2009-09-05 21:47:34 +0000318 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;
cristy37e0b382011-06-07 13:31:21 +0000331 if (~summary_info.comments.length >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +0000332 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);
cristyd15e6592011-10-15 00:13:06 +0000341 (void) SetImageProperty(image,"comment",comments,exception);
cristy3ed852e2009-09-05 21:47:34 +0000342 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)
cristy8a46d822012-08-28 23:32:39 +0000369 image->alpha_trait=BlendPixelTrait;
cristy3ed852e2009-09-05 21:47:34 +0000370 if (colorspace.numberOfComponents == 1)
371 {
372 /*
373 Create linear colormap.
374 */
cristy8f87c482011-12-16 14:38:09 +0000375 if (AcquireImageColormap(image,MaxColormapSize,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000376 {
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 */
cristybb503372010-05-27 20:51:26 +0000426 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000427 {
428 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000429 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000430 break;
cristy3ed852e2009-09-05 21:47:34 +0000431 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,
cristybb503372010-05-27 20:51:26 +0000442 (float) (y+tile_height-1)/image->rows,(ssize_t) image->columns,
443 (ssize_t) tile_height,&fpx_info);
cristy3ed852e2009-09-05 21:47:34 +0000444 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;
cristybb503372010-05-27 20:51:26 +0000459 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000460 {
461 if (fpx_info.numberOfComponents > 2)
462 {
cristy4c08aed2011-07-01 19:47:50 +0000463 SetPixelRed(image,ScaleCharToQuantum(*r),q);
464 SetPixelGreen(image,ScaleCharToQuantum(*g),q);
465 SetPixelBlue(image,ScaleCharToQuantum(*b),q);
cristy3ed852e2009-09-05 21:47:34 +0000466 }
467 else
468 {
469 index=ScaleCharToQuantum(*r);
cristy4c08aed2011-07-01 19:47:50 +0000470 SetPixelBlack(image,index,q);
471 SetPixelRed(image,index,q);
472 SetPixelGreen(image,index,q);
473 SetPixelBlue(image,index,q);
cristy3ed852e2009-09-05 21:47:34 +0000474 }
cristy4c08aed2011-07-01 19:47:50 +0000475 SetPixelAlpha(image,OpaqueAlpha,q);
cristy8a46d822012-08-28 23:32:39 +0000476 if (image->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +0000477 SetPixelAlpha(image,ScaleCharToQuantum(*a),q);
cristyed231572011-07-14 02:18:59 +0000478 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000479 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;
cristycee97112010-05-28 00:44:52 +0000486 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
cristy202de442011-04-24 18:19:07 +0000487 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000488 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%
cristybb503372010-05-27 20:51:26 +0000518% size_t RegisterFPXImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000519%
520*/
cristybb503372010-05-27 20:51:26 +0000521ModuleExport size_t RegisterFPXImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000522{
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%
cristy1e178e72011-08-28 19:44:34 +0000582% MagickBooleanType WriteFPXImage(const ImageInfo *image_info,
583% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000584%
585% A description of each parameter follows.
586%
587% o image_info: the image info.
588%
589% o image: The image.
590%
cristy1e178e72011-08-28 19:44:34 +0000591% o exception: return any errors or warnings in this structure.
592%
cristy3ed852e2009-09-05 21:47:34 +0000593*/
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
cristy1e178e72011-08-28 19:44:34 +0000776static MagickBooleanType WriteFPXImage(const ImageInfo *image_info,Image *image,
777 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000778{
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
cristy3ed852e2009-09-05 21:47:34 +0000813 MagickBooleanType
814 status;
815
816 QuantumInfo
817 *quantum_info;
818
819 QuantumType
820 quantum_type;
821
cristy4c08aed2011-07-01 19:47:50 +0000822 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +0000823 *p;
824
cristybb503372010-05-27 20:51:26 +0000825 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000826 i;
827
828 size_t
829 length,
830 memory_limit;
831
cristy202de442011-04-24 18:19:07 +0000832 ssize_t
833 y;
834
cristy3ed852e2009-09-05 21:47:34 +0000835 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);
cristy3a37efd2011-08-28 20:31:03 +0000851 assert(exception != (ExceptionInfo *) NULL);
852 assert(exception->signature == MagickSignature);
cristy1e178e72011-08-28 19:44:34 +0000853 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
cristy3ed852e2009-09-05 21:47:34 +0000854 if (status == MagickFalse)
855 return(status);
cristy3d9f5ba2012-06-26 13:37:31 +0000856 if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
cristyd9ecd042012-06-17 18:26:12 +0000857 (void) TransformImageColorspace(image,sRGBColorspace,exception);
cristy3ed852e2009-09-05 21:47:34 +0000858 (void) CloseBlob(image);
859 /*
860 Initialize FPX toolkit.
861 */
862 image->depth=8;
cristy3ed852e2009-09-05 21:47:34 +0000863 memory_limit=20000000;
864 fpx_status=FPX_SetToolkitMemoryLimit(&memory_limit);
865 if (fpx_status != FPX_OK)
866 ThrowWriterException(DelegateError,"UnableToInitializeFPXLibrary");
867 tile_width=64;
868 tile_height=64;
869 colorspace.numberOfComponents=3;
cristy8a46d822012-08-28 23:32:39 +0000870 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000871 colorspace.numberOfComponents=4;
872 if ((image_info->type != TrueColorType) &&
cristy1e178e72011-08-28 19:44:34 +0000873 (IsImageGray(image,exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +0000874 {
875 colorspace.numberOfComponents=1;
876 colorspace.theComponents[0].myColor=MONOCHROME;
877 }
878 background_color.color1_value=0;
879 background_color.color2_value=0;
880 background_color.color3_value=0;
881 background_color.color4_value=0;
882 compression=NONE;
883 if (image->compression == JPEGCompression)
884 compression=JPEG_UNSPECIFIED;
885 if (image_info->compression == JPEGCompression)
886 compression=JPEG_UNSPECIFIED;
887 {
888#if defined(macintosh)
889 FSSpec
890 fsspec;
891
892 FilenameToFSSpec(filename,&fsspec);
893 fpx_status=FPX_CreateImageByFilename((const FSSpec &) fsspec,image->columns,
894#else
895 fpx_status=FPX_CreateImageByFilename(image->filename,image->columns,
896#endif
897 image->rows,tile_width,tile_height,colorspace,background_color,
898 compression,&flashpix);
899 }
900 if (fpx_status != FPX_OK)
901 return(status);
902 if (compression == JPEG_UNSPECIFIED)
903 {
904 /*
905 Initialize the compression by quality for the entire image.
906 */
907 fpx_status=FPX_SetJPEGCompression(flashpix,(unsigned short)
908 image->quality == UndefinedCompressionQuality ? 75 : image->quality);
909 if (fpx_status != FPX_OK)
910 ThrowWriterException(DelegateError,"UnableToSetJPEGLevel");
911 }
912 /*
913 Set image summary info.
914 */
915 summary_info.title_valid=MagickFalse;
916 summary_info.subject_valid=MagickFalse;
917 summary_info.author_valid=MagickFalse;
918 summary_info.comments_valid=MagickFalse;
919 summary_info.keywords_valid=MagickFalse;
920 summary_info.OLEtemplate_valid=MagickFalse;
921 summary_info.last_author_valid=MagickFalse;
922 summary_info.rev_number_valid=MagickFalse;
923 summary_info.edit_time_valid=MagickFalse;
924 summary_info.last_printed_valid=MagickFalse;
925 summary_info.create_dtm_valid=MagickFalse;
926 summary_info.last_save_dtm_valid=MagickFalse;
927 summary_info.page_count_valid=MagickFalse;
928 summary_info.word_count_valid=MagickFalse;
929 summary_info.char_count_valid=MagickFalse;
930 summary_info.thumbnail_valid=MagickFalse;
931 summary_info.appname_valid=MagickFalse;
932 summary_info.security_valid=MagickFalse;
cristy8f87c482011-12-16 14:38:09 +0000933 label=GetImageProperty(image,"label",exception);
cristy3ed852e2009-09-05 21:47:34 +0000934 if (label != (const char *) NULL)
935 {
cristy3ed852e2009-09-05 21:47:34 +0000936 /*
937 Note image label.
938 */
939 summary_info.title_valid=MagickTrue;
940 length=strlen(label);
941 summary_info.title.length=length;
cristy37e0b382011-06-07 13:31:21 +0000942 if (~length >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +0000943 summary_info.title.ptr=(unsigned char *) AcquireQuantumMemory(
944 length+MaxTextExtent,sizeof(*summary_info.title.ptr));
945 if (summary_info.title.ptr == (unsigned char *) NULL)
946 ThrowWriterException(DelegateError,"UnableToSetImageTitle");
947 (void) CopyMagickString((char *) summary_info.title.ptr,label,
948 MaxTextExtent);
949 }
cristy8f87c482011-12-16 14:38:09 +0000950 comment=GetImageProperty(image,"comment",exception);
cristy3ed852e2009-09-05 21:47:34 +0000951 if (comment != (const char *) NULL)
952 {
953 /*
954 Note image comment.
955 */
956 summary_info.comments_valid=MagickTrue;
957 summary_info.comments.ptr=(unsigned char *) AcquireString(comment);
958 summary_info.comments.length=strlen(comment);
959 }
960 fpx_status=FPX_SetSummaryInformation(flashpix,&summary_info);
961 if (fpx_status != FPX_OK)
962 ThrowWriterException(DelegateError,"UnableToSetSummaryInfo");
963 /*
964 Initialize FlashPix image description.
965 */
966 quantum_info=AcquireQuantumInfo(image_info,image);
967 if (quantum_info == (QuantumInfo *) NULL)
968 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
969 pixels=GetQuantumPixels(quantum_info);
970 fpx_info.numberOfComponents=colorspace.numberOfComponents;
cristybb503372010-05-27 20:51:26 +0000971 for (i=0; i < (ssize_t) fpx_info.numberOfComponents; i++)
cristy3ed852e2009-09-05 21:47:34 +0000972 {
973 fpx_info.components[i].myColorType.myDataType=DATA_TYPE_UNSIGNED_BYTE;
974 fpx_info.components[i].horzSubSampFactor=1;
975 fpx_info.components[i].vertSubSampFactor=1;
976 fpx_info.components[i].columnStride=fpx_info.numberOfComponents;
977 fpx_info.components[i].lineStride=
978 image->columns*fpx_info.components[i].columnStride;
979 fpx_info.components[i].theData=pixels+i;
980 }
981 fpx_info.components[0].myColorType.myColor=fpx_info.numberOfComponents != 1
982 ? NIFRGB_R : MONOCHROME;
983 fpx_info.components[1].myColorType.myColor=NIFRGB_G;
984 fpx_info.components[2].myColorType.myColor=NIFRGB_B;
985 fpx_info.components[3].myColorType.myColor=ALPHA;
986 /*
987 Write image pixelss.
988 */
989 quantum_type=RGBQuantum;
cristy8a46d822012-08-28 23:32:39 +0000990 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000991 quantum_type=RGBAQuantum;
992 if (fpx_info.numberOfComponents == 1)
993 quantum_type=GrayQuantum;
cristybb503372010-05-27 20:51:26 +0000994 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000995 {
cristy1e178e72011-08-28 19:44:34 +0000996 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000997 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000998 break;
cristy4c08aed2011-07-01 19:47:50 +0000999 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
cristy1e178e72011-08-28 19:44:34 +00001000 quantum_type,pixels,exception);
cristy3ed852e2009-09-05 21:47:34 +00001001 fpx_status=FPX_WriteImageLine(flashpix,&fpx_info);
1002 if (fpx_status != FPX_OK)
1003 break;
cristycee97112010-05-28 00:44:52 +00001004 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
cristy202de442011-04-24 18:19:07 +00001005 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001006 if (status == MagickFalse)
1007 break;
1008 }
1009 quantum_info=DestroyQuantumInfo(quantum_info);
1010 if (image_info->view != (char *) NULL)
1011 {
1012 FPXAffineMatrix
1013 affine;
1014
1015 FPXColorTwistMatrix
1016 color_twist;
1017
1018 FPXContrastAdjustment
1019 contrast;
1020
1021 FPXFilteringValue
1022 sharpen;
1023
1024 FPXResultAspectRatio
1025 aspect_ratio;
1026
1027 FPXROI
1028 view_rect;
1029
1030 MagickBooleanType
1031 affine_valid,
1032 aspect_ratio_valid,
1033 color_twist_valid,
1034 contrast_valid,
1035 sharpen_valid,
1036 view_rect_valid;
1037
1038 /*
1039 Initialize default viewing parameters.
1040 */
1041 contrast=1.0;
1042 contrast_valid=MagickFalse;
1043 color_twist.byy=1.0;
1044 color_twist.byc1=0.0;
1045 color_twist.byc2=0.0;
1046 color_twist.dummy1_zero=0.0;
1047 color_twist.bc1y=0.0;
1048 color_twist.bc1c1=1.0;
1049 color_twist.bc1c2=0.0;
1050 color_twist.dummy2_zero=0.0;
1051 color_twist.bc2y=0.0;
1052 color_twist.bc2c1=0.0;
1053 color_twist.bc2c2=1.0;
1054 color_twist.dummy3_zero=0.0;
1055 color_twist.dummy4_zero=0.0;
1056 color_twist.dummy5_zero=0.0;
1057 color_twist.dummy6_zero=0.0;
1058 color_twist.dummy7_one=1.0;
1059 color_twist_valid=MagickFalse;
1060 sharpen=0.0;
1061 sharpen_valid=MagickFalse;
1062 aspect_ratio=(double) image->columns/image->rows;
1063 aspect_ratio_valid=MagickFalse;
1064 view_rect.left=(float) 0.1;
1065 view_rect.width=aspect_ratio-0.2;
1066 view_rect.top=(float) 0.1;
1067 view_rect.height=(float) 0.8; /* 1.0-0.2 */
1068 view_rect_valid=MagickFalse;
1069 affine.a11=1.0;
1070 affine.a12=0.0;
1071 affine.a13=0.0;
1072 affine.a14=0.0;
1073 affine.a21=0.0;
1074 affine.a22=1.0;
1075 affine.a23=0.0;
1076 affine.a24=0.0;
1077 affine.a31=0.0;
1078 affine.a32=0.0;
1079 affine.a33=1.0;
1080 affine.a34=0.0;
1081 affine.a41=0.0;
1082 affine.a42=0.0;
1083 affine.a43=0.0;
1084 affine.a44=1.0;
1085 affine_valid=MagickFalse;
1086 if (0)
1087 {
1088 /*
1089 Color color twist.
1090 */
1091 SetBrightness(0.5,&color_twist);
1092 SetSaturation(0.5,&color_twist);
1093 SetColorBalance(0.5,1.0,1.0,&color_twist);
1094 color_twist_valid=MagickTrue;
1095 }
1096 if (affine_valid)
1097 {
1098 fpx_status=FPX_SetImageAffineMatrix(flashpix,&affine);
1099 if (fpx_status != FPX_OK)
1100 ThrowWriterException(DelegateError,"UnableToSetAffineMatrix");
1101 }
1102 if (aspect_ratio_valid)
1103 {
1104 fpx_status=FPX_SetImageResultAspectRatio(flashpix,&aspect_ratio);
1105 if (fpx_status != FPX_OK)
1106 ThrowWriterException(DelegateError,"UnableToSetAspectRatio");
1107 }
1108 if (color_twist_valid)
1109 {
1110 fpx_status=FPX_SetImageColorTwistMatrix(flashpix,&color_twist);
1111 if (fpx_status != FPX_OK)
1112 ThrowWriterException(DelegateError,"UnableToSetColorTwist");
1113 }
1114 if (contrast_valid)
1115 {
1116 fpx_status=FPX_SetImageContrastAdjustment(flashpix,&contrast);
1117 if (fpx_status != FPX_OK)
1118 ThrowWriterException(DelegateError,"UnableToSetContrast");
1119 }
1120 if (sharpen_valid)
1121 {
1122 fpx_status=FPX_SetImageFilteringValue(flashpix,&sharpen);
1123 if (fpx_status != FPX_OK)
1124 ThrowWriterException(DelegateError,"UnableToSetFilteringValue");
1125 }
1126 if (view_rect_valid)
1127 {
1128 fpx_status=FPX_SetImageROI(flashpix,&view_rect);
1129 if (fpx_status != FPX_OK)
1130 ThrowWriterException(DelegateError,"UnableToSetRegionOfInterest");
1131 }
1132 }
1133 (void) FPX_CloseImage(flashpix);
1134 FPX_ClearSystem();
1135 return(MagickTrue);
1136}
1137#endif