From: cristy Date: Sat, 4 Jan 2014 18:03:30 +0000 (+0000) Subject: (no commit message) X-Git-Tag: 7.0.1-0~2978 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7ea349614d7582d3c7e54afc52360d8db73a8f67;p=imagemagick --- diff --git a/coders/jp2.c b/coders/jp2.c index a8bb80d8a..b1d887b31 100644 --- a/coders/jp2.c +++ b/coders/jp2.c @@ -61,6 +61,7 @@ #include "MagickCore/option.h" #include "MagickCore/pixel-accessor.h" #include "MagickCore/profile.h" +#include "MagickCore/property.h" #include "MagickCore/quantum-private.h" #include "MagickCore/static.h" #include "MagickCore/statistic.h" @@ -350,7 +351,7 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception) option=GetImageOption(image_info,"jp2:reduce-factor"); if (option != (const char *) NULL) parameters.cp_reduce=StringToInteger(option); - option=GetImageOption(image_info,"jp2:layer-number"); + option=GetImageOption(image_info,"jp2:quality-layers"); if (option != (const char *) NULL) parameters.cp_layer=StringToInteger(option); if (opj_setup_decoder(jp2_codec,¶meters) == 0) @@ -389,16 +390,8 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception) ThrowReaderException(DelegateError,"UnableToDecodeImageFile"); } } - if (image_info->number_scenes != 0) - jp2_status=opj_get_decoded_tile(jp2_codec,jp2_stream,jp2_image, - image_info->scene); - else - { - jp2_status=opj_decode(jp2_codec,jp2_stream,jp2_image); - if (jp2_status != 0) - jp2_status=opj_end_decompress(jp2_codec,jp2_stream); - } - if (jp2_status == 0) + if ((opj_decode(jp2_codec,jp2_stream,jp2_image) == 0) || + (opj_end_decompress(jp2_codec,jp2_stream) == 0)) { opj_stream_set_user_data(jp2_stream,NULL); opj_stream_destroy_v3(jp2_stream); @@ -687,9 +680,42 @@ ModuleExport void UnregisterJP2Image(void) static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image, ExceptionInfo *exception) { + const char + *value; + + int + jp2_status; + MagickBooleanType status; + opj_codec_t + *jp2_codec; + + OPJ_COLOR_SPACE + jp2_colorspace; + + opj_cparameters_t + parameters; + + opj_image_cmptparm_t + jp2_info[5]; + + opj_image_t + *jp2_image; + + opj_stream_t + *jp2_stream; + + register ssize_t + i; + + ssize_t + y; + + size_t + channels; + /* Open image file. */ @@ -699,16 +725,245 @@ static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image, assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickSignature); status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); if (status == MagickFalse) return(status); /* Initialize JPEG 2000 API. */ - if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse) - (void) TransformImageColorspace(image,sRGBColorspace,exception); - if (status != MagickFalse) + opj_set_default_encoder_parameters(¶meters); + for (i=1; i < 6; i++) + if (((1UL << (i+2)) > image->columns) && ((1UL << (i+2)) > image->rows)) + break; + parameters.numresolution=i; + parameters.tcp_numlayers=1; + parameters.tcp_distoratio[0]=(double) image->quality; + parameters.cp_fixed_quality=OPJ_TRUE; + if (image_info->extract != (char *) NULL) + { + RectangleInfo + geometry; + + int + flags; + + /* + Set tile size. + */ + flags=ParseAbsoluteGeometry(image_info->extract,&geometry); + parameters.cp_tdx=geometry.width; + parameters.cp_tdy=geometry.width; + if ((flags & HeightValue) != 0) + parameters.cp_tdy=geometry.height; + if ((flags & XValue) != 0) + parameters.cp_tx0=geometry.x; + if ((flags & YValue) != 0) + parameters.cp_ty0=geometry.y; + parameters.tile_size_on=OPJ_TRUE; + } + value=GetImageArtifact(image,"jp2:quality"); + if (value != (const char *) NULL) + { + register const char + *p; + + /* + Set quality PSNR. + */ + p=value; + for (i=1; sscanf(p,"%f",¶meters.tcp_distoratio[i]) == 1; i++) + { + if (i > 100) + break; + while ((*p != '\0') && (*p != ',')) + p++; + if (*p == '\0') + break; + p++; + } + parameters.tcp_numlayers=i; + parameters.cp_fixed_quality=OPJ_TRUE; + } + value=GetImageArtifact(image,"jp2:rate"); + if (value != (const char *) NULL) + { + register const char + *p; + + /* + Set compression rate. + */ + p=value; + for (i=1; sscanf(p,"%f",¶meters.tcp_rates[i]) == 1; i++) + { + if (i > 100) + break; + while ((*p != '\0') && (*p != ',')) + p++; + if (*p == '\0') + break; + p++; + } + parameters.tcp_numlayers=i; + parameters.cp_disto_alloc=OPJ_TRUE; + } + value=GetImageProperty(image,"comment",exception); + if (value != (const char *) NULL) + parameters.cp_comment=ConstantString(value); + channels=3; + jp2_colorspace=OPJ_CLRSPC_SRGB; + if (image->colorspace == YUVColorspace) + { + jp2_colorspace=OPJ_CLRSPC_SYCC; + parameters.subsampling_dx=2; + } + else + { + if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse) + (void) TransformImageColorspace(image,sRGBColorspace,exception); + if (IsGrayColorspace(image->colorspace) != MagickFalse) + { + channels=1; + jp2_colorspace=OPJ_CLRSPC_GRAY; + } + if (image->alpha_trait == BlendPixelTrait) + channels++; + } + ResetMagickMemory(jp2_info,0,sizeof(jp2_info)); + for (i=0; i < (ssize_t) channels; i++) + { + jp2_info[i].prec=image->depth; + jp2_info[i].bpp=image->depth; + if ((image->depth == 1) && + ((LocaleCompare(image_info->magick,"JPT") == 0) || + (LocaleCompare(image_info->magick,"JP2") == 0))) + { + jp2_info[i].prec++; /* OpenJPEG returns exception for depth @ 1 */ + jp2_info[i].bpp++; + } + jp2_info[i].sgnd=0; + jp2_info[i].dx=parameters.subsampling_dx; + jp2_info[i].dy=parameters.subsampling_dy; + jp2_info[i].w=image->columns; + jp2_info[i].h=image->rows; + } + jp2_image=opj_image_create(channels,jp2_info,jp2_colorspace); + if (jp2_image == (opj_image_t *) NULL) + ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); + jp2_image->x0=parameters.image_offset_x0; + jp2_image->y0=parameters.image_offset_y0; + jp2_image->x1=2*parameters.image_offset_x0+(image->columns-1)* + parameters.subsampling_dx+1; + jp2_image->y1=2*parameters.image_offset_y0+(image->rows-1)* + parameters.subsampling_dx+1; + /* + Convert to JP2 pixels. + */ + for (y=0; y < (ssize_t) image->rows; y++) + { + register const Quantum + *p; + + ssize_t + x; + + p=GetVirtualPixels(image,0,y,image->columns,1,exception); + if (p == (const Quantum *) NULL) + break; + for (x=0; x < (ssize_t) image->columns; x++) + { + for (i=0; i < (ssize_t) channels; i++) + { + double + scale; + + register int + *q; + + scale=(double) ((1UL << jp2_image->comps[i].prec)-1)/QuantumRange; + q=jp2_image->comps[i].data+(y/jp2_image->comps[i].dy* + image->columns/jp2_image->comps[i].dx+x/jp2_image->comps[i].dx); + switch (i) + { + case 0: + { + if (jp2_colorspace == OPJ_CLRSPC_GRAY) + { + *q=(int) (scale*GetPixelLuma(image,p)); + break; + } + *q=(int) (scale*GetPixelRed(image,p)); + break; + } + case 1: + { + if (jp2_colorspace == OPJ_CLRSPC_GRAY) + { + *q=(int) (scale*GetPixelAlpha(image,p)); + break; + } + *q=(int) (scale*GetPixelGreen(image,p)); + break; + } + case 2: + { + *q=(int) (scale*GetPixelBlue(image,p)); + break; + } + case 3: + { + *q=(int) (scale*GetPixelAlpha(image,p)); + break; + } + } + } + p++; + } + status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, + image->rows); + if (status == MagickFalse) + break; + } + if (LocaleCompare(image_info->magick,"JPT") == 0) + jp2_codec=opj_create_compress(OPJ_CODEC_JPT); + else + if (LocaleCompare(image_info->magick,"J2K") == 0) + jp2_codec=opj_create_compress(OPJ_CODEC_J2K); + else + jp2_codec=opj_create_compress(OPJ_CODEC_JP2); + opj_set_warning_handler(jp2_codec,JP2WarningHandler,exception); + opj_set_error_handler(jp2_codec,JP2ErrorHandler,exception); + opj_setup_encoder(jp2_codec,¶meters,jp2_image); + jp2_stream=opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE,OPJ_FALSE); + opj_stream_set_read_function(jp2_stream,JP2ReadHandler); + opj_stream_set_write_function(jp2_stream,JP2WriteHandler); + opj_stream_set_seek_function(jp2_stream,JP2SeekHandler); + opj_stream_set_skip_function(jp2_stream,JP2SkipHandler); + opj_stream_set_user_data(jp2_stream,image); + if (jp2_stream == (opj_stream_t *) NULL) + ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); + jp2_status=opj_start_compress(jp2_codec,jp2_image,jp2_stream); + if (jp2_status == 0) ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); + if ((opj_encode(jp2_codec,jp2_stream) == 0) || + (opj_end_compress(jp2_codec,jp2_stream) == 0)) + { + opj_stream_set_user_data(jp2_stream,NULL); + opj_stream_destroy_v3(jp2_stream); + opj_destroy_codec(jp2_codec); + opj_image_destroy(jp2_image); + ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); + } + /* + Free resources. + */ + opj_stream_set_user_data(jp2_stream,NULL); + opj_stream_destroy_v3(jp2_stream); + opj_destroy_codec(jp2_codec); + opj_image_destroy(jp2_image); + (void) CloseBlob(image); return(MagickTrue); } #endif