+ opj_set_default_encoder_parameters(¶meters);
+ for (i=1; i < 6; i++)
+ if (((1U << (i+2)) > image->columns) && ((1U << (i+2)) > image->rows))
+ break;
+ parameters.numresolution=i;
+ option=GetImageOption(image_info,"jp2:number-resolutions");
+ if (option != (const char *) NULL)
+ parameters.numresolution=StringToInteger(option);
+ parameters.tcp_numlayers=1;
+ parameters.tcp_rates[0]=0; /* lossless */
+ parameters.cp_disto_alloc=1;
+ if (image->quality != 0)
+ {
+ 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=(int) geometry.width;
+ parameters.cp_tdy=(int) geometry.width;
+ if ((flags & HeightValue) != 0)
+ parameters.cp_tdy=(int) 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;
+ }
+ option=GetImageOption(image_info,"jp2:quality");
+ if (option != (const char *) NULL)
+ {
+ register const char
+ *p;
+
+ /*
+ Set quality PSNR.
+ */
+ p=option;
+ for (i=0; 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+1;
+ parameters.cp_fixed_quality=OPJ_TRUE;
+ }
+ option=GetImageOption(image_info,"jp2:progression-order");
+ if (option != (const char *) NULL)
+ {
+ if (LocaleCompare(option,"LRCP") == 0)
+ parameters.prog_order=OPJ_LRCP;
+ if (LocaleCompare(option,"RLCP") == 0)
+ parameters.prog_order=OPJ_RLCP;
+ if (LocaleCompare(option,"RPCL") == 0)
+ parameters.prog_order=OPJ_RPCL;
+ if (LocaleCompare(option,"PCRL") == 0)
+ parameters.prog_order=OPJ_PCRL;
+ if (LocaleCompare(option,"CPRL") == 0)
+ parameters.prog_order=OPJ_CPRL;
+ }
+ option=GetImageOption(image_info,"jp2:rate");
+ if (option != (const char *) NULL)
+ {
+ register const char
+ *p;
+
+ /*
+ Set compression rate.
+ */
+ p=option;
+ for (i=0; 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+1;
+ parameters.cp_disto_alloc=OPJ_TRUE;
+ }
+ if (image_info->sampling_factor != (const char *) NULL)
+ (void) sscanf(image_info->sampling_factor,"%d,%d",
+ ¶meters.subsampling_dx,¶meters.subsampling_dy);
+ property=GetImageProperty(image,"comment",exception);
+ if (property != (const char *) NULL)
+ parameters.cp_comment=ConstantString(property);
+ channels=3;
+ jp2_colorspace=OPJ_CLRSPC_SRGB;
+ if (image->colorspace == YUVColorspace)
+ {
+ jp2_colorspace=OPJ_CLRSPC_SYCC;
+ parameters.subsampling_dx=2;
+ }
+ else
+ {
+ (void) TransformImageColorspace(image,sRGBColorspace,exception);
+ if (IsGrayColorspace(image->colorspace) != MagickFalse)
+ {
+ channels=1;
+ jp2_colorspace=OPJ_CLRSPC_GRAY;
+ }
+ if (image->alpha_trait != UndefinedPixelTrait)
+ channels++;
+ }
+ parameters.tcp_mct=channels == 3 ? 1 : 0;
+ ResetMagickMemory(jp2_info,0,sizeof(jp2_info));
+ for (i=0; i < (ssize_t) channels; i++)
+ {
+ jp2_info[i].prec=(OPJ_UINT32) image->depth;
+ jp2_info[i].bpp=(OPJ_UINT32) 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=(OPJ_UINT32) image->columns;
+ jp2_info[i].h=(OPJ_UINT32) image->rows;
+ }
+ jp2_image=opj_image_create((OPJ_UINT32) channels,jp2_info,jp2_colorspace);
+ if (jp2_image == (opj_image_t *) NULL)