source: ImageMagick/branches/ImageMagick-6/coders/jp2.c @ 8048

Revision 8048, 37.4 KB checked in by cristy, 12 months ago (diff)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                              JJJ  PPPP    222                               %
7%                               J   P   P  2   2                              %
8%                               J   PPPP     22                               %
9%                            J  J   P       2                                 %
10%                             JJ    P      22222                              %
11%                                                                             %
12%                                                                             %
13%                     Read/Write JPEG-2000 Image Format                       %
14%                                                                             %
15%                                John Cristy                                  %
16%                                Nathan Brown                                 %
17%                                 June 2001                                   %
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 "magick/studio.h"
43#include "magick/attribute.h"
44#include "magick/blob.h"
45#include "magick/blob-private.h"
46#include "magick/cache.h"
47#include "magick/colorspace.h"
48#include "magick/colorspace-private.h"
49#include "magick/color.h"
50#include "magick/color-private.h"
51#include "magick/exception.h"
52#include "magick/exception-private.h"
53#include "magick/image.h"
54#include "magick/image-private.h"
55#include "magick/list.h"
56#include "magick/magick.h"
57#include "magick/memory_.h"
58#include "magick/monitor.h"
59#include "magick/monitor-private.h"
60#include "magick/option.h"
61#include "magick/profile.h"
62#include "magick/quantum-private.h"
63#include "magick/static.h"
64#include "magick/statistic.h"
65#include "magick/string_.h"
66#include "magick/module.h"
67#if defined(MAGICKCORE_JP2_DELEGATE)
68#ifndef JAS_IMAGE_CM_GRAY
69#define JAS_IMAGE_CM_GRAY JAS_IMAGE_CS_GRAY
70#endif
71#ifndef JAS_IMAGE_CM_RGB
72#define JAS_IMAGE_CM_RGB JAS_IMAGE_CS_RGB
73#endif
74#if !defined(uchar)
75#define uchar  unsigned char
76#endif
77#if !defined(ushort)
78#define ushort  unsigned short
79#endif
80#if !defined(uint)
81#define uint  unsigned int
82#endif
83#if !defined(ssize_tssize_t)
84#define ssize_tssize_t  long long
85#endif
86#if !defined(ussize_tssize_t)
87#define ussize_tssize_t  unsigned long long
88#endif
89
90#undef PACKAGE_NAME
91#undef PACKAGE_STRING
92#undef PACKAGE_TARNAME
93#undef PACKAGE_VERSION
94#include "jasper/jasper.h"
95#undef PACKAGE_NAME
96#undef PACKAGE_STRING
97#undef PACKAGE_TARNAME
98#undef PACKAGE_VERSION
99
100#endif
101
102/*
103  Forward declarations.
104*/
105#if defined(MAGICKCORE_JP2_DELEGATE)
106static MagickBooleanType
107  WriteJP2Image(const ImageInfo *,Image *);
108
109static volatile MagickBooleanType
110  instantiate_jp2 = MagickFalse;
111#endif
112
113/*
114%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115%                                                                             %
116%                                                                             %
117%                                                                             %
118%   I s J P 2                                                                 %
119%                                                                             %
120%                                                                             %
121%                                                                             %
122%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123%
124%  IsJP2() returns MagickTrue if the image format type, identified by the
125%  magick string, is JP2.
126%
127%  The format of the IsJP2 method is:
128%
129%      MagickBooleanType IsJP2(const unsigned char *magick,const size_t length)
130%
131%  A description of each parameter follows:
132%
133%    o magick: compare image format pattern against these bytes.
134%
135%    o length: Specifies the length of the magick string.
136%
137*/
138static MagickBooleanType IsJP2(const unsigned char *magick,const size_t length)
139{
140  if (length < 9)
141    return(MagickFalse);
142  if (memcmp(magick+4,"\152\120\040\040\015",5) == 0)
143    return(MagickTrue);
144  return(MagickFalse);
145}
146
147/*
148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149%                                                                             %
150%                                                                             %
151%                                                                             %
152%   I s J P C                                                                 %
153%                                                                             %
154%                                                                             %
155%                                                                             %
156%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157%
158%  IsJPC()() returns MagickTrue if the image format type, identified by the
159%  magick string, is JPC.
160%
161%  The format of the IsJPC method is:
162%
163%      MagickBooleanType IsJPC(const unsigned char *magick,const size_t length)
164%
165%  A description of each parameter follows:
166%
167%    o magick: compare image format pattern against these bytes.
168%
169%    o length: Specifies the length of the magick string.
170%
171*/
172static MagickBooleanType IsJPC(const unsigned char *magick,const size_t length)
173{
174  if (length < 2)
175    return(MagickFalse);
176  if (memcmp(magick,"\377\117",2) == 0)
177    return(MagickTrue);
178  return(MagickFalse);
179}
180
181/*
182%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
183%                                                                             %
184%                                                                             %
185%                                                                             %
186%   R e a d J P 2 I m a g e                                                   %
187%                                                                             %
188%                                                                             %
189%                                                                             %
190%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191%
192%  ReadJP2Image() reads a JPEG 2000 Image file (JP2) or JPEG 2000
193%  codestream (JPC) image file and returns it.  It allocates the memory
194%  necessary for the new Image structure and returns a pointer to the new
195%  image or set of images.
196%
197%  JP2 support is originally written by Nathan Brown, nathanbrown@letu.edu.
198%
199%  The format of the ReadJP2Image method is:
200%
201%      Image *ReadJP2Image(const ImageInfo *image_info,
202%        ExceptionInfo *exception)
203%
204%  A description of each parameter follows:
205%
206%    o image_info: the image info.
207%
208%    o exception: return any errors or warnings in this structure.
209%
210*/
211#if defined(MAGICKCORE_JP2_DELEGATE)
212
213typedef struct _StreamManager
214{
215  jas_stream_t
216    *stream;
217
218  Image
219    *image;
220} StreamManager;
221
222static int BlobRead(jas_stream_obj_t *object,char *buffer,const int length)
223{
224  ssize_t
225    count;
226
227  StreamManager
228    *source;
229
230  source=(StreamManager *) object;
231  count=ReadBlob(source->image,(size_t) length,(unsigned char *) buffer);
232  return((int) count);
233}
234
235static int BlobWrite(jas_stream_obj_t *object,char *buffer,const int length)
236{
237  ssize_t
238    count;
239
240  StreamManager
241    *source;
242
243  source=(StreamManager *) object;
244  count=WriteBlob(source->image,(size_t) length,(unsigned char *) buffer);
245  return((int) count);
246}
247
248static long BlobSeek(jas_stream_obj_t *object,long offset,int origin)
249{
250  StreamManager
251    *source;
252
253  source=(StreamManager *) object;
254  return((long) SeekBlob(source->image,offset,origin));
255}
256
257static int BlobClose(jas_stream_obj_t *object)
258{
259  StreamManager
260    *source;
261
262  source=(StreamManager *) object;
263  (void) CloseBlob(source->image);
264  free(source);
265  source=(StreamManager *) NULL;
266  return(0);
267}
268
269static inline size_t MagickMax(const size_t x,const size_t y)
270{
271  if (x > y)
272    return(x);
273  return(y);
274}
275
276static inline size_t MagickMin(const size_t x,const size_t y)
277{
278  if (x < y)
279    return(x);
280  return(y);
281}
282
283static jas_stream_t *JP2StreamManager(Image *image)
284{
285  static jas_stream_ops_t
286    StreamOperators =
287    {
288      BlobRead,
289      BlobWrite,
290      BlobSeek,
291      BlobClose
292    };
293
294  jas_stream_t
295    *stream;
296
297  StreamManager
298    *source;
299
300  stream=(jas_stream_t *) jas_malloc(sizeof(*stream));
301  if (stream == (jas_stream_t *) NULL)
302    return((jas_stream_t *) NULL);
303  (void) ResetMagickMemory(stream,0,sizeof(*stream));
304  stream->rwlimit_=(-1);
305  stream->obj_=(jas_stream_obj_t *) jas_malloc(sizeof(StreamManager));
306  if (stream->obj_ == (jas_stream_obj_t *) NULL)
307    return((jas_stream_t *) NULL);
308  (void) ResetMagickMemory(stream->obj_,0,sizeof(StreamManager));
309  stream->ops_=(&StreamOperators);
310  stream->openmode_=JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
311  stream->bufbase_=(unsigned char *) jas_malloc(JAS_STREAM_BUFSIZE+
312    JAS_STREAM_MAXPUTBACK);
313  if (stream->bufbase_ == (void *) NULL)
314    {
315      stream->bufbase_=stream->tinybuf_;
316      stream->bufsize_=1;
317    }
318  else
319    {
320      stream->bufmode_=JAS_STREAM_FREEBUF | JAS_STREAM_BUFMODEMASK;
321      stream->bufsize_=JAS_STREAM_BUFSIZE;
322    }
323  stream->bufstart_=(&stream->bufbase_[JAS_STREAM_MAXPUTBACK]);
324  stream->ptr_=stream->bufstart_;
325  stream->cnt_=0;
326  source=(StreamManager *) stream->obj_;
327  source->image=image;
328  return(stream);
329}
330
331static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
332{
333  Image
334    *image;
335
336  jas_cmprof_t
337    *cm_profile;
338
339  jas_iccprof_t
340    *icc_profile;
341
342  jas_image_t
343    *jp2_image;
344
345  jas_matrix_t
346    *pixels[4];
347
348  jas_stream_t
349    *jp2_stream;
350
351  MagickBooleanType
352    status;
353
354  QuantumAny
355    pixel,
356    range[4];
357
358  register ssize_t
359    i,
360    x;
361
362  register PixelPacket
363    *q;
364
365  size_t
366    maximum_component_depth,
367    number_components,
368    x_step[4],
369    y_step[4];
370
371  ssize_t
372    components[4],
373    y;
374
375  /*
376    Open image file.
377  */
378  assert(image_info != (const ImageInfo *) NULL);
379  assert(image_info->signature == MagickSignature);
380  if (image_info->debug != MagickFalse)
381    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
382      image_info->filename);
383  assert(exception != (ExceptionInfo *) NULL);
384  assert(exception->signature == MagickSignature);
385  image=AcquireImage(image_info);
386  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
387  if (status == MagickFalse)
388    {
389      image=DestroyImageList(image);
390      return((Image *) NULL);
391    }
392  /*
393    Initialize JPEG 2000 API.
394  */
395  jp2_stream=JP2StreamManager(image);
396  if (jp2_stream == (jas_stream_t *) NULL)
397    ThrowReaderException(DelegateError,"UnableToManageJP2Stream");
398  jp2_image=jas_image_decode(jp2_stream,-1,0);
399  if (jp2_image == (jas_image_t *) NULL)
400    {
401      (void) jas_stream_close(jp2_stream);
402      ThrowReaderException(DelegateError,"UnableToDecodeImageFile");
403    }
404  image->columns=jas_image_width(jp2_image);
405  image->rows=jas_image_height(jp2_image);
406  image->compression=JPEG2000Compression;
407  switch (jas_clrspc_fam(jas_image_clrspc(jp2_image)))
408  {
409    case JAS_CLRSPC_FAM_RGB:
410    {
411      SetImageColorspace(image,RGBColorspace);
412      components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_R);
413      components[1]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_G);
414      components[2]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_B);
415      if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
416        {
417          (void) jas_stream_close(jp2_stream);
418          jas_image_destroy(jp2_image);
419          ThrowReaderException(CorruptImageError,"MissingImageChannel");
420        }
421      number_components=3;
422      components[3]=jas_image_getcmptbytype(jp2_image,3);
423      if (components[3] > 0)
424        {
425          image->matte=MagickTrue;
426          number_components++;
427        }
428      break;
429    }
430    case JAS_CLRSPC_FAM_GRAY:
431    {
432      SetImageColorspace(image,GRAYColorspace);
433      components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_GRAY_Y);
434      if (components[0] < 0)
435        {
436          (void) jas_stream_close(jp2_stream);
437          jas_image_destroy(jp2_image);
438          ThrowReaderException(CorruptImageError,"MissingImageChannel");
439        }
440      number_components=1;
441      break;
442    }
443    case JAS_CLRSPC_FAM_YCBCR:
444    {
445      SetImageColorspace(image,YCbCrColorspace);
446      components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_Y);
447      components[1]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_CB);
448      components[2]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_CR);
449      if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
450        {
451          (void) jas_stream_close(jp2_stream);
452          jas_image_destroy(jp2_image);
453          ThrowReaderException(CorruptImageError,"MissingImageChannel");
454        }
455      number_components=3;
456      components[3]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_UNKNOWN);
457      if (components[3] > 0)
458        {
459          image->matte=MagickTrue;
460          number_components++;
461        }
462      break;
463    }
464    case JAS_CLRSPC_FAM_XYZ:
465    {
466      SetImageColorspace(image,XYZColorspace);
467      components[0]=jas_image_getcmptbytype(jp2_image,0);
468      components[1]=jas_image_getcmptbytype(jp2_image,1);
469      components[2]=jas_image_getcmptbytype(jp2_image,2);
470      if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
471        {
472          (void) jas_stream_close(jp2_stream);
473          jas_image_destroy(jp2_image);
474          ThrowReaderException(CorruptImageError,"MissingImageChannel");
475        }
476      number_components=3;
477      components[3]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_UNKNOWN);
478      if (components[3] > 0)
479        {
480          image->matte=MagickTrue;
481          number_components++;
482        }
483      break;
484    }
485    case JAS_CLRSPC_FAM_LAB:
486    {
487      SetImageColorspace(image,YCbCrColorspace);
488      components[0]=jas_image_getcmptbytype(jp2_image,0);
489      components[1]=jas_image_getcmptbytype(jp2_image,1);
490      components[2]=jas_image_getcmptbytype(jp2_image,2);
491      if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
492        {
493          (void) jas_stream_close(jp2_stream);
494          jas_image_destroy(jp2_image);
495          ThrowReaderException(CorruptImageError,"MissingImageChannel");
496        }
497      number_components=3;
498      components[3]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_UNKNOWN);
499      if (components[3] > 0)
500        {
501          image->matte=MagickTrue;
502          number_components++;
503        }
504      break;
505    }
506    default:
507    {
508      (void) jas_stream_close(jp2_stream);
509      jas_image_destroy(jp2_image);
510      ThrowReaderException(CoderError,"ColorspaceModelIsNotSupported");
511    }
512  }
513  for (i=0; i < (ssize_t) number_components; i++)
514  {
515    size_t
516      height,
517      width;
518
519    width=(size_t) (jas_image_cmptwidth(jp2_image,components[i])*
520      jas_image_cmpthstep(jp2_image,components[i]));
521    height=(size_t) (jas_image_cmptheight(jp2_image,components[i])*
522      jas_image_cmptvstep(jp2_image,components[i]));
523    x_step[i]=(unsigned int) jas_image_cmpthstep(jp2_image,components[i]);
524    y_step[i]=(unsigned int) jas_image_cmptvstep(jp2_image,components[i]);
525    if ((width != image->columns) || (height != image->rows) ||
526        (jas_image_cmpttlx(jp2_image,components[i]) != 0) ||
527        (jas_image_cmpttly(jp2_image,components[i]) != 0) ||
528        (jas_image_cmptsgnd(jp2_image,components[i]) != MagickFalse))
529      {
530        (void) jas_stream_close(jp2_stream);
531        jas_image_destroy(jp2_image);
532        ThrowReaderException(CoderError,"IrregularChannelGeometryNotSupported");
533      }
534  }
535  /*
536    Convert JPEG 2000 pixels.
537  */
538  image->matte=number_components > 3 ? MagickTrue : MagickFalse;
539  maximum_component_depth=0;
540  for (i=0; i < (ssize_t) number_components; i++)
541  {
542    maximum_component_depth=(unsigned int) MagickMax((size_t)
543      jas_image_cmptprec(jp2_image,components[i]),(size_t)
544      maximum_component_depth);
545    pixels[i]=jas_matrix_create(1,(int) (image->columns/x_step[i]));
546    if (pixels[i] == (jas_matrix_t *) NULL)
547      {
548        for (--i; i >= 0; i--)
549          jas_matrix_destroy(pixels[i]);
550        jas_image_destroy(jp2_image);
551        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
552      }
553  }
554  image->depth=maximum_component_depth;
555  if (image_info->ping != MagickFalse)
556    {
557      (void) jas_stream_close(jp2_stream);
558      jas_image_destroy(jp2_image);
559      return(GetFirstImageInList(image));
560    }
561  for (i=0; i < (ssize_t) number_components; i++)
562    range[i]=GetQuantumRange((size_t) jas_image_cmptprec(jp2_image,
563      components[i]));
564  for (y=0; y < (ssize_t) image->rows; y++)
565  {
566    q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
567    if (q == (PixelPacket *) NULL)
568      break;
569    for (i=0; i < (ssize_t) number_components; i++)
570      (void) jas_image_readcmpt(jp2_image,(short) components[i],0,
571        (jas_image_coord_t) (y/y_step[i]),(jas_image_coord_t) (image->columns/
572        x_step[i]),1,pixels[i]);
573    switch (number_components)
574    {
575      case 1:
576      {
577        /*
578          Grayscale.
579        */
580        for (x=0; x < (ssize_t) image->columns; x++)
581        {
582          pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
583          SetPixelRed(q,ScaleAnyToQuantum((QuantumAny) pixel,
584            range[0]));
585          SetPixelGreen(q,GetPixelRed(q));
586          SetPixelBlue(q,GetPixelRed(q));
587          q++;
588        }
589        break;
590      }
591      case 3:
592      {
593        /*
594          RGB.
595        */
596        for (x=0; x < (ssize_t) image->columns; x++)
597        {
598          pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
599          SetPixelRed(q,ScaleAnyToQuantum((QuantumAny) pixel,range[0]));
600          pixel=(QuantumAny) jas_matrix_getv(pixels[1],x/x_step[1]);
601          SetPixelGreen(q,ScaleAnyToQuantum((QuantumAny) pixel,range[1]));
602          pixel=(QuantumAny) jas_matrix_getv(pixels[2],x/x_step[2]);
603          SetPixelBlue(q,ScaleAnyToQuantum((QuantumAny) pixel,range[2]));
604          q++;
605        }
606        break;
607      }
608      case 4:
609      {
610        /*
611          RGBA.
612        */
613        for (x=0; x < (ssize_t) image->columns; x++)
614        {
615          pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
616          SetPixelRed(q,ScaleAnyToQuantum((QuantumAny) pixel,
617            range[0]));
618          pixel=(QuantumAny) jas_matrix_getv(pixels[1],x/x_step[1]);
619          SetPixelGreen(q,ScaleAnyToQuantum((QuantumAny) pixel,range[1]));
620          pixel=(QuantumAny) jas_matrix_getv(pixels[2],x/x_step[2]);
621          SetPixelBlue(q,ScaleAnyToQuantum((QuantumAny) pixel,range[2]));
622          pixel=(QuantumAny) jas_matrix_getv(pixels[3],x/x_step[3]);
623          SetPixelAlpha(q,ScaleAnyToQuantum((QuantumAny) pixel,range[3]));
624          q++;
625        }
626        break;
627      }
628    }
629    if (SyncAuthenticPixels(image,exception) == MagickFalse)
630      break;
631    status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
632      image->rows);
633    if (status == MagickFalse)
634      break;
635  }
636  cm_profile=jas_image_cmprof(jp2_image);
637  icc_profile=(jas_iccprof_t *) NULL;
638  if (cm_profile != (jas_cmprof_t *) NULL)
639    icc_profile=jas_iccprof_createfromcmprof(cm_profile);
640  if (icc_profile != (jas_iccprof_t *) NULL)
641    {
642      jas_stream_t
643        *icc_stream;
644
645      icc_stream=jas_stream_memopen(NULL,0);
646      if ((icc_stream != (jas_stream_t *) NULL) &&
647          (jas_iccprof_save(icc_profile,icc_stream) == 0) &&
648          (jas_stream_flush(icc_stream) == 0))
649        {
650          StringInfo
651            *icc_profile,
652            *profile;
653
654          jas_stream_memobj_t
655            *blob;
656
657          /*
658            Extract the icc profile, handle errors without much noise.
659          */
660          blob=(jas_stream_memobj_t *) icc_stream->obj_;
661          if (image->debug != MagickFalse)
662            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
663              "Profile: ICC, %.20g bytes",(double) blob->len_);
664          profile=BlobToStringInfo(blob->buf_,blob->len_);
665          if (profile == (StringInfo *) NULL)
666            ThrowReaderException(CorruptImageError,"MemoryAllocationFailed");
667          icc_profile=(StringInfo *) GetImageProfile(image,"icc");
668          if (icc_profile == (StringInfo *) NULL)
669            (void) SetImageProfile(image,"icc",profile);
670          else
671            (void) ConcatenateStringInfo(icc_profile,profile);
672          profile=DestroyStringInfo(profile);
673          (void) jas_stream_close(icc_stream);
674        }
675    }
676  (void) jas_stream_close(jp2_stream);
677  jas_image_destroy(jp2_image);
678  for (i=0; i < (ssize_t) number_components; i++)
679    jas_matrix_destroy(pixels[i]);
680  return(GetFirstImageInList(image));
681}
682#endif
683
684/*
685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
686%                                                                             %
687%                                                                             %
688%                                                                             %
689%   R e g i s t e r J P 2 I m a g e                                           %
690%                                                                             %
691%                                                                             %
692%                                                                             %
693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
694%
695%  RegisterJP2Image() adds attributes for the JP2 image format to the list of
696%  supported formats.  The attributes include the image format tag, a method
697%  method to read and/or write the format, whether the format supports the
698%  saving of more than one frame to the same file or blob, whether the format
699%  supports native in-memory I/O, and a brief description of the format.
700%
701%  The format of the RegisterJP2Image method is:
702%
703%      size_t RegisterJP2Image(void)
704%
705*/
706ModuleExport size_t RegisterJP2Image(void)
707{
708  MagickInfo
709    *entry;
710
711  entry=SetMagickInfo("JP2");
712  entry->description=ConstantString("JPEG-2000 File Format Syntax");
713  entry->module=ConstantString("JP2");
714  entry->magick=(IsImageFormatHandler *) IsJP2;
715  entry->adjoin=MagickFalse;
716  entry->seekable_stream=MagickTrue;
717  entry->thread_support=NoThreadSupport;
718#if defined(MAGICKCORE_JP2_DELEGATE)
719  entry->decoder=(DecodeImageHandler *) ReadJP2Image;
720  entry->encoder=(EncodeImageHandler *) WriteJP2Image;
721#endif
722  (void) RegisterMagickInfo(entry);
723  entry=SetMagickInfo("JPC");
724  entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
725  entry->module=ConstantString("JP2");
726  entry->magick=(IsImageFormatHandler *) IsJPC;
727  entry->adjoin=MagickFalse;
728  entry->seekable_stream=MagickTrue;
729  entry->thread_support=NoThreadSupport;
730#if defined(MAGICKCORE_JP2_DELEGATE)
731  entry->decoder=(DecodeImageHandler *) ReadJP2Image;
732  entry->encoder=(EncodeImageHandler *) WriteJP2Image;
733#endif
734  (void) RegisterMagickInfo(entry);
735  entry=SetMagickInfo("J2C");
736  entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
737  entry->module=ConstantString("JP2");
738  entry->magick=(IsImageFormatHandler *) IsJPC;
739  entry->adjoin=MagickFalse;
740  entry->seekable_stream=MagickTrue;
741  entry->thread_support=NoThreadSupport;
742#if defined(MAGICKCORE_JP2_DELEGATE)
743  entry->decoder=(DecodeImageHandler *) ReadJP2Image;
744  entry->encoder=(EncodeImageHandler *) WriteJP2Image;
745#endif
746  (void) RegisterMagickInfo(entry);
747  entry=SetMagickInfo("J2K");
748  entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
749  entry->module=ConstantString("JP2");
750  entry->magick=(IsImageFormatHandler *) IsJPC;
751  entry->adjoin=MagickFalse;
752  entry->seekable_stream=MagickTrue;
753  entry->thread_support=NoThreadSupport;
754#if defined(MAGICKCORE_JP2_DELEGATE)
755  entry->decoder=(DecodeImageHandler *) ReadJP2Image;
756  entry->encoder=(EncodeImageHandler *) WriteJP2Image;
757#endif
758  (void) RegisterMagickInfo(entry);
759  entry=SetMagickInfo("JPX");
760  entry->description=ConstantString("JPEG-2000 File Format Syntax");
761  entry->module=ConstantString("JP2");
762  entry->magick=(IsImageFormatHandler *) IsJPC;
763  entry->adjoin=MagickFalse;
764  entry->seekable_stream=MagickTrue;
765  entry->thread_support=NoThreadSupport;
766#if defined(MAGICKCORE_JP2_DELEGATE)
767  entry->decoder=(DecodeImageHandler *) ReadJP2Image;
768  entry->encoder=(EncodeImageHandler *) WriteJP2Image;
769#endif
770  (void) RegisterMagickInfo(entry);
771  entry=SetMagickInfo("PGX");
772  entry->description=ConstantString("JPEG-2000 VM Format");
773  entry->module=ConstantString("JP2");
774  entry->magick=(IsImageFormatHandler *) IsJPC;
775  entry->adjoin=MagickFalse;
776  entry->seekable_stream=MagickTrue;
777  entry->thread_support=NoThreadSupport;
778#if defined(MAGICKCORE_JP2_DELEGATE)
779  entry->decoder=(DecodeImageHandler *) ReadJP2Image;
780#endif
781  (void) RegisterMagickInfo(entry);
782#if defined(MAGICKCORE_JP2_DELEGATE)
783  if (instantiate_jp2 == MagickFalse)
784    {
785      jas_init();
786      instantiate_jp2=MagickTrue;
787    }
788#endif
789  return(MagickImageCoderSignature);
790}
791
792/*
793%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
794%                                                                             %
795%                                                                             %
796%                                                                             %
797%   U n r e g i s t e r J P 2 I m a g e                                       %
798%                                                                             %
799%                                                                             %
800%                                                                             %
801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
802%
803%  UnregisterJP2Image() removes format registrations made by the JP2 module
804%  from the list of supported formats.
805%
806%  The format of the UnregisterJP2Image method is:
807%
808%      UnregisterJP2Image(void)
809%
810*/
811ModuleExport void UnregisterJP2Image(void)
812{
813  (void) UnregisterMagickInfo("PGX");
814  (void) UnregisterMagickInfo("J2K");
815  (void) UnregisterMagickInfo("J2C");
816  (void) UnregisterMagickInfo("JPC");
817  (void) UnregisterMagickInfo("JP2");
818#if defined(MAGICKCORE_JP2_DELEGATE)
819  if (instantiate_jp2 != MagickFalse)
820    {
821      jas_cleanup();
822      instantiate_jp2=MagickFalse;
823    }
824#endif
825}
826
827#if defined(MAGICKCORE_JP2_DELEGATE)
828/*
829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830%                                                                             %
831%                                                                             %
832%                                                                             %
833%   W r i t e J P 2 I m a g e                                                 %
834%                                                                             %
835%                                                                             %
836%                                                                             %
837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
838%
839%  WriteJP2Image() writes an image in the JPEG 2000 image format.
840%
841%  JP2 support originally written by Nathan Brown, nathanbrown@letu.edu
842%
843%  The format of the WriteJP2Image method is:
844%
845%      MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
846%
847%  A description of each parameter follows.
848%
849%    o image_info: the image info.
850%
851%    o image:  The image.
852%
853*/
854static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
855{
856  char
857    *key,
858    magick[MaxTextExtent],
859    *options;
860
861  const char
862    *option;
863
864  jas_image_cmptparm_t
865    component_info[4];
866
867  jas_image_t
868    *jp2_image;
869
870  jas_matrix_t
871    *pixels[4];
872
873  jas_stream_t
874    *jp2_stream;
875
876  MagickBooleanType
877    status;
878
879  QuantumAny
880    range;
881
882  register const PixelPacket
883    *p;
884
885  register ssize_t
886    i,
887    x;
888
889  size_t
890    number_components;
891
892  ssize_t
893    format,
894    y;
895
896  /*
897    Open image file.
898  */
899  assert(image_info != (const ImageInfo *) NULL);
900  assert(image_info->signature == MagickSignature);
901  assert(image != (Image *) NULL);
902  assert(image->signature == MagickSignature);
903  if (image->debug != MagickFalse)
904    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
905  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
906  if (status == MagickFalse)
907    return(status);
908  /*
909    Initialize JPEG 2000 API.
910  */
911  if (IssRGBColorspace(image->colorspace) == MagickFalse)
912    (void) TransformImageColorspace(image,sRGBColorspace);
913  jp2_stream=JP2StreamManager(image);
914  if (jp2_stream == (jas_stream_t *) NULL)
915    ThrowWriterException(DelegateError,"UnableToManageJP2Stream");
916  number_components=image->matte ? 4UL : 3UL;
917  if (IsGrayColorspace(image->colorspace) != MagickFalse)
918    number_components=1;
919  if ((image->columns != (unsigned int) image->columns) ||
920      (image->rows != (unsigned int) image->rows))
921    ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
922  (void) ResetMagickMemory(&component_info,0,sizeof(component_info));
923  for (i=0; i < (ssize_t) number_components; i++)
924  {
925    component_info[i].tlx=0;
926    component_info[i].tly=0;
927    component_info[i].hstep=1;
928    component_info[i].vstep=1;
929    component_info[i].width=(unsigned int) image->columns;
930    component_info[i].height=(unsigned int) image->rows;
931    component_info[i].prec=(int) MagickMax(MagickMin(image->depth,16),2);
932    component_info[i].sgnd=MagickFalse;
933  }
934  jp2_image=jas_image_create((int) number_components,component_info,
935    JAS_CLRSPC_UNKNOWN);
936  if (jp2_image == (jas_image_t *) NULL)
937    ThrowWriterException(DelegateError,"UnableToCreateImage");
938  switch (image->colorspace)
939  {
940    case RGBColorspace:
941    case sRGBColorspace:
942    {
943      /*
944        RGB.
945      */
946      jas_image_setclrspc(jp2_image,JAS_CLRSPC_SRGB);
947      jas_image_setcmpttype(jp2_image,0,
948        (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
949      jas_image_setcmpttype(jp2_image,1,
950        (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
951      jas_image_setcmpttype(jp2_image,2,
952        (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
953      if (number_components == 4)
954        jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
955      break;
956    }
957    case GRAYColorspace:
958    {
959      /*
960        Grayscale.
961      */
962      jas_image_setclrspc(jp2_image,JAS_CLRSPC_SGRAY);
963      jas_image_setcmpttype(jp2_image,0,
964        JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
965      break;
966    }
967    case YCbCrColorspace:
968    {
969      /*
970        YCbCr.
971      */
972      jas_image_setclrspc(jp2_image,JAS_CLRSPC_SYCBCR);
973      jas_image_setcmpttype(jp2_image,0,(jas_image_cmpttype_t)
974        JAS_IMAGE_CT_COLOR(0));
975      jas_image_setcmpttype(jp2_image,1,(jas_image_cmpttype_t)
976        JAS_IMAGE_CT_COLOR(1));
977      jas_image_setcmpttype(jp2_image,2,(jas_image_cmpttype_t)
978        JAS_IMAGE_CT_COLOR(2));
979      if (number_components == 4)
980        jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
981      break;
982    }
983    case XYZColorspace:
984    {
985      /*
986        YCbCr.
987      */
988      jas_image_setclrspc(jp2_image,JAS_CLRSPC_CIEXYZ);
989      jas_image_setcmpttype(jp2_image,0,(jas_image_cmpttype_t)
990        JAS_IMAGE_CT_COLOR(0));
991      jas_image_setcmpttype(jp2_image,1,(jas_image_cmpttype_t)
992        JAS_IMAGE_CT_COLOR(1));
993      jas_image_setcmpttype(jp2_image,2,(jas_image_cmpttype_t)
994        JAS_IMAGE_CT_COLOR(2));
995      if (number_components == 4)
996        jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
997      break;
998    }
999    case LabColorspace:
1000    {
1001      /*
1002        Lab.
1003      */
1004      jas_image_setclrspc(jp2_image,JAS_CLRSPC_CIELAB);
1005      jas_image_setcmpttype(jp2_image,0,(jas_image_cmpttype_t)
1006        JAS_IMAGE_CT_COLOR(0));
1007      jas_image_setcmpttype(jp2_image,1,(jas_image_cmpttype_t)
1008        JAS_IMAGE_CT_COLOR(1));
1009      jas_image_setcmpttype(jp2_image,2,(jas_image_cmpttype_t)
1010        JAS_IMAGE_CT_COLOR(2));
1011      if (number_components == 4)
1012        jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
1013      break;
1014    }
1015    default:
1016    {
1017      /*
1018        Unknow.
1019      */
1020      jas_image_setclrspc(jp2_image,JAS_CLRSPC_UNKNOWN);
1021      jas_image_setcmpttype(jp2_image,0,(jas_image_cmpttype_t)
1022        JAS_IMAGE_CT_COLOR(0));
1023      jas_image_setcmpttype(jp2_image,1,(jas_image_cmpttype_t)
1024        JAS_IMAGE_CT_COLOR(1));
1025      jas_image_setcmpttype(jp2_image,2,(jas_image_cmpttype_t)
1026        JAS_IMAGE_CT_COLOR(2));
1027      if (number_components == 4)
1028        jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
1029      break;
1030    }
1031  }
1032  /*
1033    Convert to JPEG 2000 pixels.
1034  */
1035  for (i=0; i < (ssize_t) number_components; i++)
1036  {
1037    pixels[i]=jas_matrix_create(1,(int) image->columns);
1038    if (pixels[i] == (jas_matrix_t *) NULL)
1039      {
1040        for (x=0; x < i; x++)
1041          jas_matrix_destroy(pixels[x]);
1042        jas_image_destroy(jp2_image);
1043        ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1044      }
1045  }
1046  range=GetQuantumRange((size_t) component_info[0].prec);
1047  for (y=0; y < (ssize_t) image->rows; y++)
1048  {
1049    p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1050    if (p == (const PixelPacket *) NULL)
1051      break;
1052    for (x=0; x < (ssize_t) image->columns; x++)
1053    {
1054      if (number_components == 1)
1055        jas_matrix_setv(pixels[0],x,(jas_seqent_t) ScaleQuantumToAny(
1056          PixelIntensityToQuantum(p),range));
1057      else
1058        {
1059          jas_matrix_setv(pixels[0],x,(jas_seqent_t)
1060            ScaleQuantumToAny(GetPixelRed(p),range));
1061          jas_matrix_setv(pixels[1],x,(jas_seqent_t)
1062            ScaleQuantumToAny(GetPixelGreen(p),range));
1063          jas_matrix_setv(pixels[2],x,(jas_seqent_t)
1064            ScaleQuantumToAny(GetPixelBlue(p),range));
1065          if (number_components > 3)
1066            jas_matrix_setv(pixels[3],x,(jas_seqent_t)
1067              ScaleQuantumToAny((Quantum) (GetPixelAlpha(p)),range));
1068        }
1069      p++;
1070    }
1071    for (i=0; i < (ssize_t) number_components; i++)
1072      (void) jas_image_writecmpt(jp2_image,(short) i,0,(unsigned int) y,
1073        (unsigned int) image->columns,1,pixels[i]);
1074    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1075      image->rows);
1076    if (status == MagickFalse)
1077      break;
1078  }
1079  (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
1080  if (LocaleCompare(magick,"J2C") == 0)
1081    (void) CopyMagickString(magick,"JPC",MaxTextExtent);
1082  LocaleLower(magick);
1083  format=jas_image_strtofmt(magick);
1084  options=(char *) NULL;
1085  ResetImageOptionIterator(image_info);
1086  key=GetNextImageOption(image_info);
1087  for ( ; key != (char *) NULL; key=GetNextImageOption(image_info))
1088  {
1089    option=GetImageOption(image_info,key);
1090    if (option == (const char *) NULL)
1091      continue;
1092    if (LocaleNCompare(key,"jp2:",4) == 0)
1093      {
1094        (void) ConcatenateString(&options,key+4);
1095        if (*option != '\0')
1096          {
1097            (void) ConcatenateString(&options,"=");
1098            (void) ConcatenateString(&options,option);
1099          }
1100        (void) ConcatenateString(&options," ");
1101      }
1102  }
1103  option=GetImageOption(image_info,"jp2:rate");
1104  if ((option == (const char *) NULL) &&
1105      (image_info->compression != LosslessJPEGCompression) &&
1106      (image->quality != UndefinedCompressionQuality) &&
1107      ((double) image->quality <= 99.5) &&
1108      ((image->rows*image->columns) > 2500))
1109    {
1110      char
1111        option[MaxTextExtent];
1112
1113      double
1114        alpha,
1115        header_size,
1116        number_pixels,
1117        rate,
1118        target_size;
1119
1120      alpha=115.0-image->quality;
1121      rate=100.0/(alpha*alpha);
1122      header_size=550.0;
1123      header_size+=(number_components-1)*142;
1124      number_pixels=(double) image->rows*image->columns*number_components*
1125        (GetImageQuantumDepth(image,MagickTrue)/8);
1126      target_size=(number_pixels*rate)+header_size;
1127      rate=target_size/number_pixels;
1128      (void) FormatLocaleString(option,MaxTextExtent,"rate=%g",rate);
1129      (void) ConcatenateString(&options,option);
1130    }
1131  status=jas_image_encode(jp2_image,jp2_stream,format,options) != 0 ?
1132    MagickTrue : MagickFalse;
1133  if (options != (char *) NULL)
1134    options=DestroyString(options);
1135  (void) jas_stream_close(jp2_stream);
1136  for (i=0; i < (ssize_t) number_components; i++)
1137    jas_matrix_destroy(pixels[i]);
1138  jas_image_destroy(jp2_image);
1139  if (status != MagickFalse)
1140    ThrowWriterException(DelegateError,"UnableToEncodeImageFile");
1141  return(MagickTrue);
1142}
1143#endif
Note: See TracBrowser for help on using the repository browser.