static int IntensityCompare(const void *x,const void *y) { const PixelPacket *color_1, *color_2; int intensity; color_1=(const PixelPacket *) x; color_2=(const PixelPacket *) y; intensity=(int) PixelIntensityToQuantum(color_2)- (int) PixelIntensityToQuantum(color_1); return(intensity); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d G R A D I E N T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method ReadGRADIENTImage creates a gradient image and initializes it to % the color range as specified by the filename. It allocates the memory % necessary for the new Image structure and returns a pointer to the new % image. % % The format of the ReadGRADIENTImage method is: % % Image *ReadGRADIENTImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image: Method ReadGRADIENTImage returns a pointer to the image after % creating it. A null image is returned if there is a memory shortage % or if the image cannot be read. % % o image_info: Specifies a pointer to a ImageInfo structure. % % o exception: return any errors or warnings in this structure. % % */ static Image *ReadGRADIENTImage(const ImageInfo *image_info, ExceptionInfo *exception) { char colorname[MaxTextExtent]; PixelPacket start_color, stop_color; Image *image; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AllocateImage(image_info); if ((image->columns == 0) || (image->rows == 0)) ThrowReaderException(OptionError,MustSpecifyImageSize,image); (void) SetImage(image,OpaqueOpacity); (void) strlcpy(image->filename,image_info->filename,MaxTextExtent); (void) strlcpy(colorname,image_info->filename,MaxTextExtent); (void) sscanf(image_info->filename,"%[^-]",colorname); if (!QueryColorDatabase(colorname,&start_color,exception)) { DestroyImage(image); return((Image *) NULL); } (void) strcpy(colorname,"white"); if (PixelIntensityToQuantum(&start_color) > (0.5*MaxRGB)) (void) strcpy(colorname,"black"); (void) sscanf(image_info->filename,"%*[^-]-%s",colorname); if (!QueryColorDatabase(colorname,&stop_color,exception)) { DestroyImage(image); return((Image *) NULL); } (void) GradientImage(image,&start_color,&stop_color); return(image); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d G R A D I E N T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadGRADIENTImage creates a gradient image and initializes it to % the color range as specified by the filename. It allocates the memory % necessary for the new Image structure and returns a pointer to the new % image. % % The format of the ReadGRADIENTImage method is: % % Image *ReadGRADIENTImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadGRADIENTImage(const ImageInfo *image_info, ExceptionInfo *exception) { char colorname[MaxTextExtent]; MagickBooleanType status; MagickPixelPacket start_pixel, stop_pixel; PixelPacket start_color, stop_color; Image *image; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); if ((image->columns == 0) || (image->rows == 0)) ThrowReaderException(OptionError,"MustSpecifyImageSize"); (void) SetImageOpacity(image,(Quantum) TransparentOpacity); (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent); (void) CopyMagickString(colorname,image_info->filename,MaxTextExtent); (void) sscanf(image_info->filename,"%[^-]",colorname); if (QueryColorDatabase(colorname,&start_color,exception) == MagickFalse) { image=DestroyImage(image); return((Image *) NULL); } (void) QueryMagickColor(colorname,&start_pixel,exception); (void) CopyMagickString(colorname,"white",MaxTextExtent); if (PixelIntensityToQuantum(image,&start_color) > (Quantum) (QuantumRange/2)) (void) CopyMagickString(colorname,"black",MaxTextExtent); (void) sscanf(image_info->filename,"%*[^-]-%s",colorname); if (QueryColorDatabase(colorname,&stop_color,exception) == MagickFalse) { image=DestroyImage(image); return((Image *) NULL); } (void) QueryMagickColor(colorname,&stop_pixel,exception); if (IssRGBColorspace(start_pixel.colorspace) != MagickFalse) { start_color.red=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* start_color.red)); start_color.green=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* start_color.green)); start_color.blue=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* start_color.blue)); } if (IssRGBColorspace(stop_pixel.colorspace) != MagickFalse) { stop_color.red=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* stop_color.red)); stop_color.green=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* stop_color.green)); stop_color.blue=ClampToQuantum(QuantumRange*DecompandsRGB(QuantumScale* stop_color.blue)); } status=GradientImage(image,LocaleCompare(image_info->magick,"GRADIENT") == 0 ? LinearGradient : RadialGradient,PadSpread,&start_color,&stop_color); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } (void) SetImageColorspace(image,start_pixel.colorspace); if ((start_pixel.matte == MagickFalse) && (stop_pixel.matte == MagickFalse)) (void) SetImageAlphaChannel(image,DeactivateAlphaChannel); if (IssRGBColorspace(start_pixel.colorspace) != MagickFalse) { (void) SetImageColorspace(image,RGBColorspace); (void) TransformImageColorspace(image,sRGBColorspace); } return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e J P 2 I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method WriteJP2Image writes an image in the JPEG 2000 image format. % % JP2 support originally written by Nathan Brown, [email protected] % % The format of the WriteJP2Image method is: % % MagickPassFail WriteJP2Image(const ImageInfo *image_info,Image *image) % % A description of each parameter follows. % % o status: Method WriteJP2Image return MagickTrue if the image is written. % MagickFalse is returned is there is a memory shortage or if the image file % fails to write. % % o image_info: Specifies a pointer to a ImageInfo structure. % % o image: A pointer to an Image structure. % % */ static MagickPassFail WriteJP2Image(const ImageInfo *image_info,Image *image) { char magick[MaxTextExtent], option_keyval[MaxTextExtent], *options = NULL; int format; long y; jas_image_cmptparm_t component_info; jas_image_t *jp2_image; jas_matrix_t *jp2_pixels; jas_stream_t *jp2_stream; register const PixelPacket *p; register int x; unsigned int rate_specified=False, status; int component, number_components; unsigned short *lut; ImageCharacteristics characteristics; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == False) ThrowWriterException(FileOpenError,UnableToOpenFile,image); /* Ensure that image is in RGB space. */ (void) TransformColorspace(image,RGBColorspace); /* Analyze image to be written. */ if (!GetImageCharacteristics(image,&characteristics, (OptimizeType == image_info->type), &image->exception)) { CloseBlob(image); return MagickFail; } /* Obtain a JP2 stream. */ jp2_stream=JP2StreamManager(image); if (jp2_stream == (jas_stream_t *) NULL) ThrowWriterException(DelegateError,UnableToManageJP2Stream,image); number_components=image->matte ? 4 : 3; if ((image_info->type != TrueColorType) && (characteristics.grayscale)) number_components=1; jp2_image=jas_image_create0(); if (jp2_image == (jas_image_t *) NULL) ThrowWriterException(DelegateError,UnableToCreateImage,image); for (component=0; component < number_components; component++) { (void) memset((void *)&component_info,0,sizeof(jas_image_cmptparm_t)); component_info.tlx=0; /* top left x ordinate */ component_info.tly=0; /* top left y ordinate */ component_info.hstep=1; /* horizontal pixels per step */ component_info.vstep=1; /* vertical pixels per step */ component_info.width=(unsigned int) image->columns; component_info.height=(unsigned int) image->rows; component_info.prec=(unsigned int) Max(2,Min(image->depth,16)); /* bits in range */ component_info.sgnd = false; /* range is signed value? */ if (jas_image_addcmpt(jp2_image, component,&component_info)) { jas_image_destroy(jp2_image); ThrowWriterException(DelegateError,UnableToCreateImageComponent,image); } } /* Allocate and compute LUT. */ { unsigned long i, max_value; double scale_to_component; lut=MagickAllocateArray(unsigned short *,MaxMap+1,sizeof(*lut)); if (lut == (unsigned short *) NULL) { jas_image_destroy(jp2_image); ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image); } max_value=MaxValueGivenBits(component_info.prec); scale_to_component=max_value/MaxRGBDouble; for(i=0; i <= MaxMap; i++) lut[i]=scale_to_component*i+0.5; } if (number_components == 1) { /* FIXME: If image has an attached ICC profile, then the profile should be transferred and the image colorspace set to JAS_CLRSPC_GENGRAY */ /* sRGB Grayscale */ (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Setting SGRAY colorspace"); jas_image_setclrspc(jp2_image, JAS_CLRSPC_SGRAY); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Setting GRAY channel to channel 0"); jas_image_setcmpttype(jp2_image,0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y)); } else { /* FIXME: If image has an attached ICC profile, then the profile should be transferred and the image colorspace set to JAS_CLRSPC_GENRGB */ /* sRGB */ (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Setting SRGB colorspace"); jas_image_setclrspc(jp2_image, JAS_CLRSPC_SRGB); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Setting RED channel to channel 0"); jas_image_setcmpttype(jp2_image,0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Setting GREEN channel to channel 1"); jas_image_setcmpttype(jp2_image,1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Setting BLUE channel to channel 2"); jas_image_setcmpttype(jp2_image,2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); if (number_components == 4 ) { (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Setting OPACITY channel to channel 3"); jas_image_setcmpttype(jp2_image,3, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY)); } } /* Convert to JPEG 2000 pixels. */ jp2_pixels=jas_matrix_create(1,(unsigned int) image->columns); if (jp2_pixels == (jas_matrix_t *) NULL) { MagickFreeMemory(lut); jas_image_destroy(jp2_image); ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image); } for (y=0; y < (long) image->rows; y++) { p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; if (number_components == 1) { for (x=0; x < (long) image->columns; x++) jas_matrix_setv(jp2_pixels,x,lut[ScaleQuantumToMap(PixelIntensityToQuantum(&p[x]))]); (void) jas_image_writecmpt(jp2_image,0,0,(unsigned int) y, (unsigned int) image->columns,1,jp2_pixels); } else { for (x=0; x < (long) image->columns; x++) jas_matrix_setv(jp2_pixels,x,lut[ScaleQuantumToMap(p[x].red)]); (void) jas_image_writecmpt(jp2_image,0,0,(unsigned int) y, (unsigned int) image->columns,1,jp2_pixels); for (x=0; x < (long) image->columns; x++) jas_matrix_setv(jp2_pixels,x,lut[ScaleQuantumToMap(p[x].green)]); (void) jas_image_writecmpt(jp2_image,1,0,(unsigned int) y, (unsigned int) image->columns,1,jp2_pixels); for (x=0; x < (long) image->columns; x++) jas_matrix_setv(jp2_pixels,x,lut[ScaleQuantumToMap(p[x].blue)]); (void) jas_image_writecmpt(jp2_image,2,0,(unsigned int) y, (unsigned int) image->columns,1,jp2_pixels); if (number_components > 3) for (x=0; x < (long) image->columns; x++) jas_matrix_setv(jp2_pixels,x,lut[ScaleQuantumToMap(MaxRGB-p[x].opacity)]); (void) jas_image_writecmpt(jp2_image,3,0,(unsigned int) y, (unsigned int) image->columns,1,jp2_pixels); } if (image->previous == (Image *) NULL) if (QuantumTick(y,image->rows)) if (!MagickMonitorFormatted(y,image->rows,&image->exception, SaveImageText,image->filename, image->columns,image->rows)) break; } (void) strlcpy(magick,image_info->magick,MaxTextExtent); /* J2C is an alias for JPC but Jasper only supports "JPC". */ if (LocaleCompare(magick,"j2c") == 0) (void) strlcpy(magick,"jpc",sizeof(magick)); LocaleLower(magick); format=jas_image_strtofmt(magick); /* Support passing Jasper options. */ { const char **option_name; static const char *jasper_options[] = { "imgareatlx", "imgareatly", "tilegrdtlx", "tilegrdtly", "tilewidth", "tileheight", "prcwidth", "prcheight", "cblkwidth", "cblkheight", "mode", "ilyrrates", "prg", "nomct", "numrlvls", "sop", "eph", "lazy", "rate", "termall", "segsym", "vcausal", "pterm", "resetprob", "numgbits", NULL }; for (option_name = jasper_options; *option_name != NULL; option_name++) { const char *value; if ((value=AccessDefinition(image_info,"jp2",*option_name)) != NULL) { if(LocaleCompare(*option_name,"rate") == 0) rate_specified=True; FormatString(option_keyval,"%s=%.1024s ",*option_name,value); ConcatenateString(&options,option_keyval); } } } /* Provide an emulation of IJG JPEG "quality" by default. */ if (rate_specified == False) { double rate=1.0; /* A rough approximation to JPEG v1 quality using JPEG-2000. Default "quality" 75 results in a request for 16:1 compression, which results in image sizes approximating that of JPEG v1. */ if ((image_info->quality < 99.5) && (image->rows*image->columns > 2500)) { double header_size, current_size, target_size, d; d=115-image_info->quality; /* Best number is 110-115 */ rate=100.0/(d*d); header_size=550.0; /* Base file size. */ header_size+=(number_components-1)*142; /* Additional components */ /* FIXME: Need to account for any ICC profiles here */ current_size=(double)((image->rows*image->columns*image->depth)/8)* number_components; target_size=(current_size*rate)+header_size; rate=target_size/current_size; } FormatString(option_keyval,"%s=%g ","rate",rate); ConcatenateString(&options,option_keyval); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Compression rate: %g (%3.2f:1)",rate,1.0/rate); } if (options) (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Jasper options: \"%s\"", options); (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Encoding image"); status=jas_image_encode(jp2_image,jp2_stream,format,options); (void) jas_stream_close(jp2_stream); MagickFreeMemory(options); MagickFreeMemory(lut); jas_matrix_destroy(jp2_pixels); jas_image_destroy(jp2_image); if (status) ThrowWriterException(DelegateError,UnableToEncodeImageFile,image); return(True); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % C o m b i n e I m a g e s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % CombineImages() combines one or more images into a single image. The % grayscale value of the pixels of each image in the sequence is assigned in % order to the specified channels of the combined image. The typical % ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc. % % The format of the CombineImages method is: % % Image *CombineImages(const Image *image,const ChannelType channel, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o exception: return any errors or warnings in this structure. % */ MagickExport Image *CombineImages(const Image *image,const ChannelType channel, ExceptionInfo *exception) { #define CombineImageTag "Combine/Image" CacheView *combine_view; const Image *next; Image *combine_image; MagickBooleanType status; MagickOffsetType progress; ssize_t y; /* Ensure the image are the same size. */ assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); for (next=image; next != (Image *) NULL; next=GetNextImageInList(next)) { if ((next->columns != image->columns) || (next->rows != image->rows)) ThrowImageException(OptionError,"ImagesAreNotTheSameSize"); } combine_image=CloneImage(image,0,0,MagickTrue,exception); if (combine_image == (Image *) NULL) return((Image *) NULL); if (SetImageStorageClass(combine_image,DirectClass) == MagickFalse) { InheritException(exception,&combine_image->exception); combine_image=DestroyImage(combine_image); return((Image *) NULL); } if (IsGrayColorspace(image->colorspace) != MagickFalse) (void) SetImageColorspace(combine_image,RGBColorspace); if ((channel & OpacityChannel) != 0) combine_image->matte=MagickTrue; (void) SetImageBackgroundColor(combine_image); /* Combine images. */ status=MagickTrue; progress=0; combine_view=AcquireAuthenticCacheView(combine_image,exception); for (y=0; y < (ssize_t) combine_image->rows; y++) { CacheView *image_view; const Image *next; PixelPacket *pixels; register const PixelPacket *restrict p; register PixelPacket *restrict q; register ssize_t x; if (status == MagickFalse) continue; pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns, 1,exception); if (pixels == (PixelPacket *) NULL) { status=MagickFalse; continue; } next=image; if (((channel & RedChannel) != 0) && (next != (Image *) NULL)) { image_view=AcquireVirtualCacheView(next,exception); p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); if (p == (const PixelPacket *) NULL) continue; q=pixels; for (x=0; x < (ssize_t) combine_image->columns; x++) { SetPixelRed(q,PixelIntensityToQuantum(image,p)); p++; q++; } image_view=DestroyCacheView(image_view); next=GetNextImageInList(next); } if (((channel & GreenChannel) != 0) && (next != (Image *) NULL)) { image_view=AcquireVirtualCacheView(next,exception); p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); if (p == (const PixelPacket *) NULL) continue; q=pixels; for (x=0; x < (ssize_t) combine_image->columns; x++) { SetPixelGreen(q,PixelIntensityToQuantum(image,p)); p++; q++; } image_view=DestroyCacheView(image_view); next=GetNextImageInList(next); } if (((channel & BlueChannel) != 0) && (next != (Image *) NULL)) { image_view=AcquireVirtualCacheView(next,exception); p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); if (p == (const PixelPacket *) NULL) continue; q=pixels; for (x=0; x < (ssize_t) combine_image->columns; x++) { SetPixelBlue(q,PixelIntensityToQuantum(image,p)); p++; q++; } image_view=DestroyCacheView(image_view); next=GetNextImageInList(next); } if (((channel & OpacityChannel) != 0) && (next != (Image *) NULL)) { image_view=AcquireVirtualCacheView(next,exception); p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); if (p == (const PixelPacket *) NULL) continue; q=pixels; for (x=0; x < (ssize_t) combine_image->columns; x++) { SetPixelAlpha(q,PixelIntensityToQuantum(image,p)); p++; q++; } image_view=DestroyCacheView(image_view); next=GetNextImageInList(next); } if (((channel & IndexChannel) != 0) && (image->colorspace == CMYKColorspace) && (next != (Image *) NULL)) { IndexPacket *indexes; image_view=AcquireVirtualCacheView(next,exception); p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); if (p == (const PixelPacket *) NULL) continue; indexes=GetCacheViewAuthenticIndexQueue(combine_view); for (x=0; x < (ssize_t) combine_image->columns; x++) { SetPixelIndex(indexes+x,PixelIntensityToQuantum(image,p)); p++; } image_view=DestroyCacheView(image_view); next=GetNextImageInList(next); } if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; proceed=SetImageProgress(image,CombineImageTag,progress++, combine_image->rows); if (proceed == MagickFalse) status=MagickFalse; } } combine_view=DestroyCacheView(combine_view); if (IsGrayColorspace(combine_image->colorspace) != MagickFalse) (void) TransformImageColorspace(combine_image,RGBColorspace); if (status == MagickFalse) combine_image=DestroyImage(combine_image); return(combine_image); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % S e p a r a t e I m a g e C h a n n e l % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SeparateImageChannel() separates a channel from the image and returns it as % a grayscale image. A channel is a particular color component of each pixel % in the image. % % The format of the SeparateImageChannel method is: % % MagickBooleanType SeparateImageChannel(Image *image, % const ChannelType channel) % % A description of each parameter follows: % % o image: the image. % % o channel: Identify which channel to extract: RedChannel, GreenChannel, % BlueChannel, OpacityChannel, CyanChannel, MagentaChannel, % YellowChannel, or BlackChannel. % */ MagickExport MagickBooleanType SeparateImageChannel(Image *image, const ChannelType channel) { #define SeparateImageTag "Separate/Image" CacheView *image_view; ExceptionInfo *exception; MagickBooleanType status; MagickOffsetType progress; ssize_t y; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if (SetImageStorageClass(image,DirectClass) == MagickFalse) return(MagickFalse); if (channel == GrayChannels) image->matte=MagickTrue; /* Separate image channels. */ status=MagickTrue; progress=0; exception=(&image->exception); image_view=AcquireAuthenticCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(progress,status) \ dynamic_number_threads(image,image->columns,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { register IndexPacket *restrict indexes; register PixelPacket *restrict q; register ssize_t x; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } indexes=GetCacheViewAuthenticIndexQueue(image_view); switch (channel) { case RedChannel: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelGreen(q,GetPixelRed(q)); SetPixelBlue(q,GetPixelRed(q)); q++; } break; } case GreenChannel: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,GetPixelGreen(q)); SetPixelBlue(q,GetPixelGreen(q)); q++; } break; } case BlueChannel: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,GetPixelBlue(q)); SetPixelGreen(q,GetPixelBlue(q)); q++; } break; } case OpacityChannel: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,GetPixelOpacity(q)); SetPixelGreen(q,GetPixelOpacity(q)); SetPixelBlue(q,GetPixelOpacity(q)); q++; } break; } case BlackChannel: { if ((image->storage_class != PseudoClass) && (image->colorspace != CMYKColorspace)) break; for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,GetPixelIndex(indexes+x)); SetPixelGreen(q,GetPixelIndex(indexes+x)); SetPixelBlue(q,GetPixelIndex(indexes+x)); q++; } break; } case TrueAlphaChannel: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,GetPixelAlpha(q)); SetPixelGreen(q,GetPixelAlpha(q)); SetPixelBlue(q,GetPixelAlpha(q)); q++; } break; } case GrayChannels: { for (x=0; x < (ssize_t) image->columns; x++) { SetPixelAlpha(q,PixelIntensityToQuantum(image,q)); q++; } break; } default: break; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_SeparateImageChannel) #endif proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows); if (proceed == MagickFalse) status=MagickFalse; } } image_view=DestroyCacheView(image_view); if (channel != GrayChannels) image->matte=MagickFalse; if (IssRGBColorspace(image->colorspace) == MagickFalse) (void) SetImageColorspace(image,GRAYColorspace); else (void) TransformImageColorspace(image,GRAYColorspace); return(status); }
static MagickBooleanType WritePS2Image(const ImageInfo *image_info,Image *image) { static const char *PostscriptProlog[]= { "%%%%BeginProlog", "%%", "%% Display a color image. The image is displayed in color on", "%% Postscript viewers or printers that support color, otherwise", "%% it is displayed as grayscale.", "%%", "/DirectClassImage", "{", " %%", " %% Display a DirectClass image.", " %%", " colorspace 0 eq", " {", " /DeviceRGB setcolorspace", " <<", " /ImageType 1", " /Width columns", " /Height rows", " /BitsPerComponent 8", " /Decode [0 1 0 1 0 1]", " /ImageMatrix [columns 0 0 rows neg 0 rows]", " compression 0 gt", " { /DataSource pixel_stream %s }", " { /DataSource pixel_stream %s } ifelse", " >> image", " }", " {", " /DeviceCMYK setcolorspace", " <<", " /ImageType 1", " /Width columns", " /Height rows", " /BitsPerComponent 8", " /Decode [1 0 1 0 1 0 1 0]", " /ImageMatrix [columns 0 0 rows neg 0 rows]", " compression 0 gt", " { /DataSource pixel_stream %s }", " { /DataSource pixel_stream %s } ifelse", " >> image", " } ifelse", "} bind def", "", "/PseudoClassImage", "{", " %%", " %% Display a PseudoClass image.", " %%", " %% Parameters:", " %% colors: number of colors in the colormap.", " %%", " currentfile buffer readline pop", " token pop /colors exch def pop", " colors 0 eq", " {", " %%", " %% Image is grayscale.", " %%", " currentfile buffer readline pop", " token pop /bits exch def pop", " /DeviceGray setcolorspace", " <<", " /ImageType 1", " /Width columns", " /Height rows", " /BitsPerComponent bits", " /Decode [0 1]", " /ImageMatrix [columns 0 0 rows neg 0 rows]", " compression 0 gt", " { /DataSource pixel_stream %s }", " {", " /DataSource pixel_stream %s", " <<", " /K "CCITTParam, " /Columns columns", " /Rows rows", " >> /CCITTFaxDecode filter", " } ifelse", " >> image", " }", " {", " %%", " %% Parameters:", " %% colormap: red, green, blue color packets.", " %%", " /colormap colors 3 mul string def", " currentfile colormap readhexstring pop pop", " currentfile buffer readline pop", " [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace", " <<", " /ImageType 1", " /Width columns", " /Height rows", " /BitsPerComponent 8", " /Decode [0 255]", " /ImageMatrix [columns 0 0 rows neg 0 rows]", " compression 0 gt", " { /DataSource pixel_stream %s }", " { /DataSource pixel_stream %s } ifelse", " >> image", " } ifelse", "} bind def", "", "/DisplayImage", "{", " %%", " %% Display a DirectClass or PseudoClass image.", " %%", " %% Parameters:", " %% x & y translation.", " %% x & y scale.", " %% label pointsize.", " %% image label.", " %% image columns & rows.", " %% class: 0-DirectClass or 1-PseudoClass.", " %% colorspace: 0-RGB or 1-CMYK.", " %% compression: 0-RLECompression or 1-NoCompression.", " %% hex color packets.", " %%", " gsave", " /buffer 512 string def", " /pixel_stream currentfile def", "", " currentfile buffer readline pop", " token pop /x exch def", " token pop /y exch def pop", " x y translate", " currentfile buffer readline pop", " token pop /x exch def", " token pop /y exch def pop", " currentfile buffer readline pop", " token pop /pointsize exch def pop", " /Helvetica findfont pointsize scalefont setfont", (char *) NULL }, *PostscriptEpilog[]= { " x y scale", " currentfile buffer readline pop", " token pop /columns exch def", " token pop /rows exch def pop", " currentfile buffer readline pop", " token pop /class exch def pop", " currentfile buffer readline pop", " token pop /colorspace exch def pop", " currentfile buffer readline pop", " token pop /compression exch def pop", " class 0 gt { PseudoClassImage } { DirectClassImage } ifelse", (char *) NULL }; char buffer[MaxTextExtent], date[MaxTextExtent], page_geometry[MaxTextExtent], **labels; CompressionType compression; const char **q, *value; double pointsize; GeometryInfo geometry_info; MagickOffsetType scene, start, stop; MagickBooleanType progress, status; MagickOffsetType offset; MagickSizeType number_pixels; MagickStatusType flags; PointInfo delta, resolution, scale; RectangleInfo geometry, media_info, page_info; register const IndexPacket *indexes; register const PixelPacket *p; register ssize_t x; register ssize_t i; SegmentInfo bounds; size_t length, page, text_size; ssize_t j, y; time_t timer; unsigned char *pixels; /* Open output image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == MagickFalse) return(status); compression=image->compression; if (image_info->compression != UndefinedCompression) compression=image_info->compression; switch (compression) { #if !defined(MAGICKCORE_JPEG_DELEGATE) case JPEGCompression: { compression=RLECompression; (void) ThrowMagickException(&image->exception,GetMagickModule(), MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)", image->filename); break; } #endif default: break; } (void) ResetMagickMemory(&bounds,0,sizeof(bounds)); page=1; scene=0; do { /* Scale relative to dots-per-inch. */ delta.x=DefaultResolution; delta.y=DefaultResolution; resolution.x=image->x_resolution; resolution.y=image->y_resolution; if ((resolution.x == 0.0) || (resolution.y == 0.0)) { flags=ParseGeometry(PSDensityGeometry,&geometry_info); resolution.x=geometry_info.rho; resolution.y=geometry_info.sigma; if ((flags & SigmaValue) == 0) resolution.y=resolution.x; } if (image_info->density != (char *) NULL) { flags=ParseGeometry(image_info->density,&geometry_info); resolution.x=geometry_info.rho; resolution.y=geometry_info.sigma; if ((flags & SigmaValue) == 0) resolution.y=resolution.x; } if (image->units == PixelsPerCentimeterResolution) { resolution.x=(size_t) (100.0*2.54*resolution.x+0.5)/100.0; resolution.y=(size_t) (100.0*2.54*resolution.y+0.5)/100.0; } SetGeometry(image,&geometry); (void) FormatLocaleString(page_geometry,MaxTextExtent,"%.20gx%.20g", (double) image->columns,(double) image->rows); if (image_info->page != (char *) NULL) (void) CopyMagickString(page_geometry,image_info->page,MaxTextExtent); else if ((image->page.width != 0) && (image->page.height != 0)) (void) FormatLocaleString(page_geometry,MaxTextExtent, "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,(double) image->page.height,(double) image->page.x,(double) image->page.y); else if ((image->gravity != UndefinedGravity) && (LocaleCompare(image_info->magick,"PS") == 0)) (void) CopyMagickString(page_geometry,PSPageGeometry,MaxTextExtent); (void) ConcatenateMagickString(page_geometry,">",MaxTextExtent); (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y, &geometry.width,&geometry.height); scale.x=(double) (geometry.width*delta.x)/resolution.x; geometry.width=(size_t) floor(scale.x+0.5); scale.y=(double) (geometry.height*delta.y)/resolution.y; geometry.height=(size_t) floor(scale.y+0.5); (void) ParseAbsoluteGeometry(page_geometry,&media_info); (void) ParseGravityGeometry(image,page_geometry,&page_info, &image->exception); if (image->gravity != UndefinedGravity) { geometry.x=(-page_info.x); geometry.y=(ssize_t) (media_info.height+page_info.y-image->rows); } pointsize=12.0; if (image_info->pointsize != 0.0) pointsize=image_info->pointsize; text_size=0; value=GetImageProperty(image,"label"); if (value != (const char *) NULL) text_size=(size_t) (MultilineCensus(value)*pointsize+12); if (page == 1) { /* Output Postscript header. */ if (LocaleCompare(image_info->magick,"PS2") == 0) (void) CopyMagickString(buffer,"%!PS-Adobe-3.0\n",MaxTextExtent); else (void) CopyMagickString(buffer,"%!PS-Adobe-3.0 EPSF-3.0\n", MaxTextExtent); (void) WriteBlobString(image,buffer); (void) WriteBlobString(image,"%%Creator: (ImageMagick)\n"); (void) FormatLocaleString(buffer,MaxTextExtent,"%%%%Title: (%s)\n", image->filename); (void) WriteBlobString(image,buffer); timer=time((time_t *) NULL); (void) FormatMagickTime(timer,MaxTextExtent,date); (void) FormatLocaleString(buffer,MaxTextExtent, "%%%%CreationDate: (%s)\n",date); (void) WriteBlobString(image,buffer); bounds.x1=(double) geometry.x; bounds.y1=(double) geometry.y; bounds.x2=(double) geometry.x+geometry.width; bounds.y2=(double) geometry.y+geometry.height+text_size; if ((image_info->adjoin != MagickFalse) && (GetNextImageInList(image) != (Image *) NULL)) (void) CopyMagickString(buffer,"%%BoundingBox: (atend)\n", MaxTextExtent); else { (void) FormatLocaleString(buffer,MaxTextExtent, "%%%%BoundingBox: %.20g %.20g %.20g %.20g\n",ceil(bounds.x1-0.5), ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent, "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1, bounds.y1,bounds.x2,bounds.y2); } (void) WriteBlobString(image,buffer); value=GetImageProperty(image,"label"); if (value != (const char *) NULL) (void) WriteBlobString(image, "%%DocumentNeededResources: font Helvetica\n"); (void) WriteBlobString(image,"%%LanguageLevel: 2\n"); if (LocaleCompare(image_info->magick,"PS2") != 0) (void) WriteBlobString(image,"%%Pages: 1\n"); else { (void) WriteBlobString(image,"%%Orientation: Portrait\n"); (void) WriteBlobString(image,"%%PageOrder: Ascend\n"); if (image_info->adjoin == MagickFalse) (void) CopyMagickString(buffer,"%%Pages: 1\n",MaxTextExtent); else (void) FormatLocaleString(buffer,MaxTextExtent, "%%%%Pages: %.20g\n",(double) GetImageListLength(image)); (void) WriteBlobString(image,buffer); } (void) WriteBlobString(image,"%%EndComments\n"); (void) WriteBlobString(image,"\n%%BeginDefaults\n"); (void) WriteBlobString(image,"%%EndDefaults\n\n"); /* Output Postscript commands. */ for (q=PostscriptProlog; *q; q++) { switch (compression) { case NoCompression: { (void) FormatLocaleString(buffer,MaxTextExtent,*q, "/ASCII85Decode filter"); break; } case JPEGCompression: { (void) FormatLocaleString(buffer,MaxTextExtent,*q, "/DCTDecode filter"); break; } case LZWCompression: { (void) FormatLocaleString(buffer,MaxTextExtent,*q, "/LZWDecode filter"); break; } case FaxCompression: case Group4Compression: { (void) FormatLocaleString(buffer,MaxTextExtent,*q," "); break; } default: { (void) FormatLocaleString(buffer,MaxTextExtent,*q, "/RunLengthDecode filter"); break; } } (void) WriteBlobString(image,buffer); (void) WriteBlobByte(image,'\n'); } value=GetImageProperty(image,"label"); if (value != (const char *) NULL) for (j=(ssize_t) MultilineCensus(value)-1; j >= 0; j--) { (void) WriteBlobString(image," /label 512 string def\n"); (void) WriteBlobString(image," currentfile label readline pop\n"); (void) FormatLocaleString(buffer,MaxTextExtent, " 0 y %g add moveto label show pop\n",j*pointsize+12); (void) WriteBlobString(image,buffer); } for (q=PostscriptEpilog; *q; q++) { (void) FormatLocaleString(buffer,MaxTextExtent,"%s\n",*q); (void) WriteBlobString(image,buffer); } if (LocaleCompare(image_info->magick,"PS2") == 0) (void) WriteBlobString(image," showpage\n"); (void) WriteBlobString(image,"} bind def\n"); (void) WriteBlobString(image,"%%EndProlog\n"); } (void) FormatLocaleString(buffer,MaxTextExtent,"%%%%Page: 1 %.20g\n", (double) page++); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent, "%%%%PageBoundingBox: %.20g %.20g %.20g %.20g\n",(double) geometry.x, (double) geometry.y,geometry.x+(double) geometry.width,geometry.y+(double) (geometry.height+text_size)); (void) WriteBlobString(image,buffer); if ((double) geometry.x < bounds.x1) bounds.x1=(double) geometry.x; if ((double) geometry.y < bounds.y1) bounds.y1=(double) geometry.y; if ((double) (geometry.x+geometry.width-1) > bounds.x2) bounds.x2=(double) geometry.x+geometry.width-1; if ((double) (geometry.y+(geometry.height+text_size)-1) > bounds.y2) bounds.y2=(double) geometry.y+(geometry.height+text_size)-1; value=GetImageProperty(image,"label"); if (value != (const char *) NULL) (void) WriteBlobString(image,"%%PageResources: font Times-Roman\n"); if (LocaleCompare(image_info->magick,"PS2") != 0) (void) WriteBlobString(image,"userdict begin\n"); start=TellBlob(image); (void) FormatLocaleString(buffer,MaxTextExtent, "%%%%BeginData:%13ld %s Bytes\n",0L, compression == NoCompression ? "ASCII" : "Binary"); (void) WriteBlobString(image,buffer); stop=TellBlob(image); (void) WriteBlobString(image,"DisplayImage\n"); /* Output image data. */ (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n%g %g\n%g\n", (double) geometry.x,(double) geometry.y,scale.x,scale.y,pointsize); (void) WriteBlobString(image,buffer); labels=(char **) NULL; value=GetImageProperty(image,"label"); if (value != (const char *) NULL) labels=StringToList(value); if (labels != (char **) NULL) { for (i=0; labels[i] != (char *) NULL; i++) { (void) FormatLocaleString(buffer,MaxTextExtent,"%s \n", labels[i]); (void) WriteBlobString(image,buffer); labels[i]=DestroyString(labels[i]); } labels=(char **) RelinquishMagickMemory(labels); } number_pixels=(MagickSizeType) image->columns*image->rows; if (number_pixels != (MagickSizeType) ((size_t) number_pixels)) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); if ((compression == FaxCompression) || (compression == Group4Compression) || ((image_info->type != TrueColorType) && (IsGrayImage(image,&image->exception) != MagickFalse))) { (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n1\n%d\n", (double) image->columns,(double) image->rows,(int) (image->colorspace == CMYKColorspace)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n", (int) ((compression != FaxCompression) && (compression != Group4Compression))); (void) WriteBlobString(image,buffer); (void) WriteBlobString(image,"0\n"); (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n", (compression == FaxCompression) || (compression == Group4Compression) ? 1 : 8); (void) WriteBlobString(image,buffer); switch (compression) { case FaxCompression: case Group4Compression: { if (LocaleCompare(CCITTParam,"0") == 0) { (void) HuffmanEncodeImage(image_info,image,image); break; } (void) Huffman2DEncodeImage(image_info,image,image); break; } case JPEGCompression: { status=InjectImageBlob(image_info,image,image,"jpeg", &image->exception); if (status == MagickFalse) ThrowWriterException(CoderError,image->exception.reason); break; } case RLECompression: default: { register unsigned char *q; /* Allocate pixel array. */ length=(size_t) number_pixels; pixels=(unsigned char *) AcquireQuantumMemory(length, sizeof(*pixels)); if (pixels == (unsigned char *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); /* Dump Runlength encoded pixels. */ q=pixels; for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1, &image->exception); if (p == (const PixelPacket *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { *q++=ScaleQuantumToChar(PixelIntensityToQuantum(p)); p++; } progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (progress == MagickFalse) break; } length=(size_t) (q-pixels); if (compression == LZWCompression) status=LZWEncodeImage(image,length,pixels); else status=PackbitsEncodeImage(image,length,pixels); pixels=(unsigned char *) RelinquishMagickMemory(pixels); if (status == MagickFalse) { (void) CloseBlob(image); return(MagickFalse); } break; } case NoCompression: { /* Dump uncompressed PseudoColor packets. */ Ascii85Initialize(image); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1, &image->exception); if (p == (const PixelPacket *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { Ascii85Encode(image,ScaleQuantumToChar( PixelIntensityToQuantum(p))); p++; } progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); if (progress == MagickFalse) break; } Ascii85Flush(image); break; } } } else if ((image->storage_class == DirectClass) || (image->colors > 256) || (compression == JPEGCompression) || (image->matte != MagickFalse)) { (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n0\n%d\n", (double) image->columns,(double) image->rows,(int) (image->colorspace == CMYKColorspace)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n", (int) (compression == NoCompression)); (void) WriteBlobString(image,buffer); switch (compression) { case JPEGCompression: { status=InjectImageBlob(image_info,image,image,"jpeg", &image->exception); if (status == MagickFalse) ThrowWriterException(CoderError,image->exception.reason); break; } case RLECompression: default: { register unsigned char *q; /* Allocate pixel array. */ length=(size_t) number_pixels; pixels=(unsigned char *) AcquireQuantumMemory(length, 4*sizeof(*pixels)); if (pixels == (unsigned char *) NULL) ThrowWriterException(ResourceLimitError, "MemoryAllocationFailed"); /* Dump Packbit encoded pixels. */ q=pixels; for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1, &image->exception); if (p == (const PixelPacket *) NULL) break; indexes=GetVirtualIndexQueue(image); for (x=0; x < (ssize_t) image->columns; x++) { if ((image->matte != MagickFalse) && (GetPixelOpacity(p) == (Quantum) TransparentOpacity)) { *q++=ScaleQuantumToChar((Quantum) QuantumRange); *q++=ScaleQuantumToChar((Quantum) QuantumRange); *q++=ScaleQuantumToChar((Quantum) QuantumRange); } else if (image->colorspace != CMYKColorspace) { *q++=ScaleQuantumToChar(GetPixelRed(p)); *q++=ScaleQuantumToChar(GetPixelGreen(p)); *q++=ScaleQuantumToChar(GetPixelBlue(p)); } else { *q++=ScaleQuantumToChar(GetPixelRed(p)); *q++=ScaleQuantumToChar(GetPixelGreen(p)); *q++=ScaleQuantumToChar(GetPixelBlue(p)); *q++=ScaleQuantumToChar(GetPixelIndex( indexes+x)); } p++; } progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); if (progress == MagickFalse) break; } length=(size_t) (q-pixels); if (compression == LZWCompression) status=LZWEncodeImage(image,length,pixels); else status=PackbitsEncodeImage(image,length,pixels); if (status == MagickFalse) { (void) CloseBlob(image); return(MagickFalse); } pixels=(unsigned char *) RelinquishMagickMemory(pixels); break; } case NoCompression: { /* Dump uncompressed DirectColor packets. */ Ascii85Initialize(image); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1, &image->exception); if (p == (const PixelPacket *) NULL) break; indexes=GetVirtualIndexQueue(image); for (x=0; x < (ssize_t) image->columns; x++) { if ((image->matte != MagickFalse) && (GetPixelOpacity(p) == (Quantum) TransparentOpacity)) { Ascii85Encode(image,ScaleQuantumToChar((Quantum) QuantumRange)); Ascii85Encode(image,ScaleQuantumToChar((Quantum) QuantumRange)); Ascii85Encode(image,ScaleQuantumToChar((Quantum) QuantumRange)); } else if (image->colorspace != CMYKColorspace) { Ascii85Encode(image,ScaleQuantumToChar( GetPixelRed(p))); Ascii85Encode(image,ScaleQuantumToChar( GetPixelGreen(p))); Ascii85Encode(image,ScaleQuantumToChar( GetPixelBlue(p))); } else { Ascii85Encode(image,ScaleQuantumToChar( GetPixelRed(p))); Ascii85Encode(image,ScaleQuantumToChar( GetPixelGreen(p))); Ascii85Encode(image,ScaleQuantumToChar( GetPixelBlue(p))); Ascii85Encode(image,ScaleQuantumToChar( GetPixelIndex(indexes+x))); } p++; } progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); if (progress == MagickFalse) break; } Ascii85Flush(image); break; } } } else { /* Dump number of colors and colormap. */ (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n1\n%d\n", (double) image->columns,(double) image->rows,(int) (image->colorspace == CMYKColorspace)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n", (int) (compression == NoCompression)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double) image->colors); (void) WriteBlobString(image,buffer); for (i=0; i < (ssize_t) image->colors; i++) { (void) FormatLocaleString(buffer,MaxTextExtent,"%02X%02X%02X\n", ScaleQuantumToChar(image->colormap[i].red), ScaleQuantumToChar(image->colormap[i].green), ScaleQuantumToChar(image->colormap[i].blue)); (void) WriteBlobString(image,buffer); } switch (compression) { case RLECompression: default: { register unsigned char *q; /* Allocate pixel array. */ length=(size_t) number_pixels; pixels=(unsigned char *) AcquireQuantumMemory(length, sizeof(*pixels)); if (pixels == (unsigned char *) NULL) ThrowWriterException(ResourceLimitError, "MemoryAllocationFailed"); /* Dump Runlength encoded pixels. */ q=pixels; for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1, &image->exception); if (p == (const PixelPacket *) NULL) break; indexes=GetVirtualIndexQueue(image); for (x=0; x < (ssize_t) image->columns; x++) *q++=(unsigned char) GetPixelIndex(indexes+x); progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); if (progress == MagickFalse) break; } length=(size_t) (q-pixels); if (compression == LZWCompression) status=LZWEncodeImage(image,length,pixels); else status=PackbitsEncodeImage(image,length,pixels); pixels=(unsigned char *) RelinquishMagickMemory(pixels); if (status == MagickFalse) { (void) CloseBlob(image); return(MagickFalse); } break; } case NoCompression: { /* Dump uncompressed PseudoColor packets. */ Ascii85Initialize(image); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1, &image->exception); if (p == (const PixelPacket *) NULL) break; indexes=GetVirtualIndexQueue(image); for (x=0; x < (ssize_t) image->columns; x++) Ascii85Encode(image,(unsigned char) GetPixelIndex( indexes+x)); progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); if (progress == MagickFalse) break; } Ascii85Flush(image); break; } } } (void) WriteBlobByte(image,'\n'); length=(size_t) (TellBlob(image)-stop); stop=TellBlob(image); offset=SeekBlob(image,start,SEEK_SET); if (offset < 0) ThrowWriterException(CorruptImageError,"ImproperImageHeader"); (void) FormatLocaleString(buffer,MaxTextExtent, "%%%%BeginData:%13ld %s Bytes\n",(long) length, compression == NoCompression ? "ASCII" : "Binary"); (void) WriteBlobString(image,buffer); offset=SeekBlob(image,stop,SEEK_SET); (void) WriteBlobString(image,"%%EndData\n"); if (LocaleCompare(image_info->magick,"PS2") != 0) (void) WriteBlobString(image,"end\n"); (void) WriteBlobString(image,"%%PageTrailer\n"); if (GetNextImageInList(image) == (Image *) NULL) break; image=SyncNextImageInList(image); status=SetImageProgress(image,SaveImagesTag,scene++, GetImageListLength(image)); if (status == MagickFalse) break; } while (image_info->adjoin != MagickFalse); (void) WriteBlobString(image,"%%Trailer\n"); if (page > 1) { (void) FormatLocaleString(buffer,MaxTextExtent, "%%%%BoundingBox: %.20g %.20g %.20g %.20g\n",ceil(bounds.x1-0.5), ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent, "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1,bounds.y1, bounds.x2,bounds.y2); (void) WriteBlobString(image,buffer); } (void) WriteBlobString(image,"%%EOF\n"); (void) CloseBlob(image); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e J P 2 I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteJP2Image() writes an image in the JPEG 2000 image format. % % JP2 support originally written by Nathan Brown, [email protected] % % The format of the WriteJP2Image method is: % % MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image) % % A description of each parameter follows. % % o image_info: the image info. % % o image: The image. % */ static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image) { char *key, magick[MaxTextExtent], *options; const char *option; ssize_t format, y; jas_image_cmptparm_t component_info[4]; jas_image_t *jp2_image; jas_matrix_t *pixels[4]; jas_stream_t *jp2_stream; MagickBooleanType status; QuantumAny range; register const PixelPacket *p; register ssize_t i, x; size_t number_components; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == MagickFalse) return(status); /* Intialize JPEG 2000 API. */ if (image->colorspace != RGBColorspace) (void) TransformImageColorspace(image,RGBColorspace); jp2_stream=JP2StreamManager(image); if (jp2_stream == (jas_stream_t *) NULL) ThrowWriterException(DelegateError,"UnableToManageJP2Stream"); number_components=image->matte ? 4UL : 3UL; if ((image_info->type != TrueColorType) && (IsGrayImage(image,&image->exception) != MagickFalse)) number_components=1; if ((image->columns != (unsigned int) image->columns) || (image->rows != (unsigned int) image->rows)) ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); (void) ResetMagickMemory(&component_info,0,sizeof(component_info)); for (i=0; i < (ssize_t) number_components; i++) { component_info[i].tlx=0; component_info[i].tly=0; component_info[i].hstep=1; component_info[i].vstep=1; component_info[i].width=(unsigned int) image->columns; component_info[i].height=(unsigned int) image->rows; component_info[i].prec=(int) MagickMax(MagickMin(image->depth,16),2); component_info[i].sgnd=MagickFalse; } jp2_image=jas_image_create((int) number_components,component_info, JAS_CLRSPC_UNKNOWN); if (jp2_image == (jas_image_t *) NULL) ThrowWriterException(DelegateError,"UnableToCreateImage"); if (number_components == 1) { /* sRGB Grayscale. */ jas_image_setclrspc(jp2_image,JAS_CLRSPC_SGRAY); jas_image_setcmpttype(jp2_image,0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y)); } else { /* sRGB. */ jas_image_setclrspc(jp2_image,JAS_CLRSPC_SRGB); jas_image_setcmpttype(jp2_image,0, (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); jas_image_setcmpttype(jp2_image,1, (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); jas_image_setcmpttype(jp2_image,2, (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); if (number_components == 4) jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY); } /* Convert to JPEG 2000 pixels. */ for (i=0; i < (ssize_t) number_components; i++) { pixels[i]=jas_matrix_create(1,(int) image->columns); if (pixels[i] == (jas_matrix_t *) NULL) { for (x=0; x < i; x++) jas_matrix_destroy(pixels[x]); jas_image_destroy(jp2_image); ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); } } range=GetQuantumRange((size_t) component_info[0].prec); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { if (number_components == 1) jas_matrix_setv(pixels[0],x,(jas_seqent_t) ScaleQuantumToAny( PixelIntensityToQuantum(p),range)); else { jas_matrix_setv(pixels[0],x,(jas_seqent_t) ScaleQuantumToAny(p->red,range)); jas_matrix_setv(pixels[1],x,(jas_seqent_t) ScaleQuantumToAny(p->green,range)); jas_matrix_setv(pixels[2],x,(jas_seqent_t) ScaleQuantumToAny(p->blue,range)); if (number_components > 3) jas_matrix_setv(pixels[3],x,(jas_seqent_t) ScaleQuantumToAny((Quantum) (GetAlphaPixelComponent(p)),range)); } p++; } for (i=0; i < (ssize_t) number_components; i++) (void) jas_image_writecmpt(jp2_image,(short) i,0,(unsigned int) y, (unsigned int) image->columns,1,pixels[i]); status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } (void) CopyMagickString(magick,image_info->magick,MaxTextExtent); if (LocaleCompare(magick,"J2C") == 0) (void) CopyMagickString(magick,"JPC",MaxTextExtent); LocaleLower(magick); format=jas_image_strtofmt(magick); options=(char *) NULL; ResetImageOptionIterator(image_info); key=GetNextImageOption(image_info); for ( ; key != (char *) NULL; key=GetNextImageOption(image_info)) { option=GetImageOption(image_info,key); if (option == (const char *) NULL) continue; if (LocaleNCompare(key,"jp2:",4) == 0) { (void) ConcatenateString(&options,key+4); if (*option != '\0') { (void) ConcatenateString(&options,"="); (void) ConcatenateString(&options,option); } (void) ConcatenateString(&options," "); } } option=GetImageOption(image_info,"jp2:rate"); if ((option == (const char *) NULL) && (image_info->compression != LosslessJPEGCompression) && (image->quality != UndefinedCompressionQuality) && ((double) image->quality <= 99.5) && ((image->rows*image->columns) > 2500)) { char option[MaxTextExtent]; double alpha, header_size, number_pixels, rate, target_size; alpha=115.0-image->quality; rate=100.0/(alpha*alpha); header_size=550.0; header_size+=(number_components-1)*142; number_pixels=(double) image->rows*image->columns*number_components* (GetImageQuantumDepth(image,MagickTrue)/8); target_size=(number_pixels*rate)+header_size; rate=target_size/number_pixels; (void) FormatMagickString(option,MaxTextExtent,"rate=%g",rate); (void) ConcatenateString(&options,option); } status=jas_image_encode(jp2_image,jp2_stream,format,options) != 0 ? MagickTrue : MagickFalse; (void) jas_stream_close(jp2_stream); for (i=0; i < (ssize_t) number_components; i++) jas_matrix_destroy(pixels[i]); jas_image_destroy(jp2_image); if (status != MagickFalse) ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); return(MagickTrue); }
MagickExport Image *OilPaintImage(const Image *image,const double radius, ExceptionInfo *exception) { #define NumberPaintBins 256 #define OilPaintImageTag "OilPaint/Image" CacheView *image_view, *paint_view; Image *paint_image; MagickBooleanType status; MagickOffsetType progress; size_t **restrict histograms, width; ssize_t y; /* Initialize painted image attributes. */ assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); width=GetOptimalKernelWidth2D(radius,0.5); paint_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception); if (paint_image == (Image *) NULL) return((Image *) NULL); if (SetImageStorageClass(paint_image,DirectClass) == MagickFalse) { InheritException(exception,&paint_image->exception); paint_image=DestroyImage(paint_image); return((Image *) NULL); } histograms=AcquireHistogramThreadSet(NumberPaintBins); if (histograms == (size_t **) NULL) { paint_image=DestroyImage(paint_image); ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); } /* Oil paint image. */ status=MagickTrue; progress=0; image_view=AcquireVirtualCacheView(image,exception); paint_view=AcquireAuthenticCacheView(paint_image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(progress,status) \ IsConcurrentDos(image->columns,image->rows,64) #endif for (y=0; y < (ssize_t) image->rows; y++) { register const IndexPacket *restrict indexes; register const PixelPacket *restrict p; register IndexPacket *restrict paint_indexes; register ssize_t x; register PixelPacket *restrict q; register size_t *histogram; if (status == MagickFalse) continue; p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t) (width/2L),image->columns+width,width,exception); q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1, exception); if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) { status=MagickFalse; continue; } indexes=GetCacheViewVirtualIndexQueue(image_view); paint_indexes=GetCacheViewAuthenticIndexQueue(paint_view); histogram=histograms[GetOpenMPThreadId()]; for (x=0; x < (ssize_t) image->columns; x++) { register ssize_t i, u; size_t count; ssize_t j, k, v; /* Assign most frequent color. */ i=0; j=0; count=0; (void) ResetMagickMemory(histogram,0,NumberPaintBins*sizeof(*histogram)); for (v=0; v < (ssize_t) width; v++) { for (u=0; u < (ssize_t) width; u++) { k=(ssize_t) ScaleQuantumToChar(PixelIntensityToQuantum(p+u+i)); histogram[k]++; if (histogram[k] > count) { j=i+u; count=histogram[k]; } } i+=(ssize_t) (image->columns+width); } *q=(*(p+j)); if (image->colorspace == CMYKColorspace) SetPixelIndex(paint_indexes+x,GetPixelIndex( indexes+x+j)); p++; q++; } if (SyncCacheViewAuthenticPixels(paint_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_OilPaintImage) #endif proceed=SetImageProgress(image,OilPaintImageTag,progress++,image->rows); if (proceed == MagickFalse) status=MagickFalse; } } paint_view=DestroyCacheView(paint_view); image_view=DestroyCacheView(image_view); histograms=DestroyHistogramThreadSet(histograms); if (status == MagickFalse) paint_image=DestroyImage(paint_image); return(paint_image); }
static MagickBooleanType WriteCIPImage(const ImageInfo *image_info,Image *image) { char buffer[MaxTextExtent]; const char *value; MagickBooleanType status; register const PixelPacket *p; register ssize_t i, x; ssize_t y; unsigned char byte; /* Open output image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == MagickFalse) return(status); (void) WriteBlobString(image,"<CiscoIPPhoneImage>\n"); value=GetImageProperty(image,"label"); if (value != (const char *) NULL) (void) FormatLocaleString(buffer,MaxTextExtent,"<Title>%s</Title>\n",value); else { char basename[MaxTextExtent]; GetPathComponent(image->filename,BasePath,basename); (void) FormatLocaleString(buffer,MaxTextExtent,"<Title>%s</Title>\n", basename); } (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent, "<LocationX>%.20g</LocationX>\n",(double) image->page.x); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent, "<LocationY>%.20g</LocationY>\n",(double) image->page.y); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent,"<Width>%.20g</Width>\n", (double) (image->columns+(image->columns % 2))); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent,"<Height>%.20g</Height>\n", (double) image->rows); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent,"<Depth>2</Depth>\n"); (void) WriteBlobString(image,buffer); (void) WriteBlobString(image,"<Data>"); if (IsRGBColorspace(image->colorspace) == MagickFalse) (void) TransformImageColorspace(image,sRGBColorspace); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; for (x=0; x < ((ssize_t) image->columns-3); x+=4) { byte=(unsigned char) ((((size_t) (4*PixelIntensityToQuantum(p+3)/QuantumRange) & 0x03) << 6) | (((size_t) (4*PixelIntensityToQuantum(p+2)/QuantumRange) & 0x03) << 4) | (((size_t) (4*PixelIntensityToQuantum(p+1)/QuantumRange) & 0x03) << 2) | (((size_t) (4*PixelIntensityToQuantum(p+0)/QuantumRange) & 0x03) << 0)); (void) FormatLocaleString(buffer,MaxTextExtent,"%02x",byte); (void) WriteBlobString(image,buffer); p+=4; } if ((image->columns % 4) != 0) { i=(ssize_t) image->columns % 4; byte=(unsigned char) ((((size_t) (4*PixelIntensityToQuantum(p+MagickMin(i,3))/QuantumRange) & 0x03) << 6) | (((size_t) (4*PixelIntensityToQuantum(p+MagickMin(i,2))/QuantumRange) & 0x03) << 4) | (((size_t) (4*PixelIntensityToQuantum(p+MagickMin(i,1))/QuantumRange) & 0x03) << 2) | (((size_t) (4*PixelIntensityToQuantum(p+MagickMin(i,0))/QuantumRange) & 0x03) << 0)); (void) FormatLocaleString(buffer,MaxTextExtent,"%02x",~byte); (void) WriteBlobString(image,buffer); } status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } (void) WriteBlobString(image,"</Data>\n"); (void) WriteBlobString(image,"</CiscoIPPhoneImage>\n"); (void) CloseBlob(image); return(MagickTrue); }
static MagickBooleanType SerializeImageChannel(const ImageInfo *image_info, Image *image,unsigned char **pixels,size_t *length) { long y; MagickBooleanType status; register const PixelPacket *p; register long x; register unsigned char *q; unsigned char code, bit; unsigned long pack, padded_columns; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); status=MagickTrue; pack=IsMonochromeImage(image,&image->exception) == MagickFalse ? 1UL : 8UL; padded_columns=((image->columns+pack-1)/pack)*pack; *length=(size_t) padded_columns*image->rows/pack; *pixels=(unsigned char *) AcquireQuantumMemory(*length,sizeof(**pixels)); if (*pixels == (unsigned char *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); q=(*pixels); for (y=0; y < (long) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; if (pack == 1) for (x=0; x < (long) image->columns; x++) { *q++=ScaleQuantumToChar(PixelIntensityToQuantum(p)); p++; } else { code='\0'; for (x=0; x < (long) padded_columns; x++) { bit=(unsigned char) 0x00; if (x < (long) image->columns) bit=(unsigned char) (PixelIntensityToQuantum(p) == (Quantum) TransparentOpacity ? 0x01 : 0x00); code=(code << 1)+bit; if (((x+1) % pack) == 0) { *q++=code; code='\0'; } p++; } } status=SetImageProgress(image,SaveImageTag,y,image->rows); if (status == MagickFalse) break; } if (status == MagickFalse) *pixels=(unsigned char *) RelinquishMagickMemory(*pixels); return(status); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e C I P I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure WriteCIPImage() writes an image to a file in the Cisco IP phone % image format. % % The format of the WriteCIPImage method is: % % MagickBooleanType WriteCIPImage(const ImageInfo *image_info,Image *image) % % A description of each parameter follows. % % o image_info: The image info. % % o image: The image. % % */ static MagickBooleanType WriteCIPImage(const ImageInfo *image_info,Image *image) { char buffer[MaxTextExtent]; const ImageAttribute *attribute; long y; MagickBooleanType status; register const PixelPacket *p; register long i, x; unsigned char byte; /* Open output image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == MagickFalse) return(status); (void) WriteBlobString(image,"<CiscoIPPhoneImage>\n"); attribute=GetImageAttribute(image,"Label"); if (attribute != (const ImageAttribute *) NULL) (void) FormatMagickString(buffer,MaxTextExtent,"<Title>%s</Title>\n", attribute->value); else { char basename[MaxTextExtent]; GetPathComponent(image->filename,BasePath,basename); (void) FormatMagickString(buffer,MaxTextExtent,"<Title>%s</Title>\n", basename); } (void) WriteBlobString(image,buffer); (void) FormatMagickString(buffer,MaxTextExtent,"<LocationX>%ld</LocationX>\n", image->page.x); (void) WriteBlobString(image,buffer); (void) FormatMagickString(buffer,MaxTextExtent,"<LocationY>%ld</LocationY>\n", image->page.y); (void) WriteBlobString(image,buffer); (void) FormatMagickString(buffer,MaxTextExtent,"<Width>%lu</Width>\n", image->columns+(image->columns % 2)); (void) WriteBlobString(image,buffer); (void) FormatMagickString(buffer,MaxTextExtent,"<Height>%lu</Height>\n", image->rows); (void) WriteBlobString(image,buffer); (void) FormatMagickString(buffer,MaxTextExtent,"<Depth>2</Depth>\n"); (void) WriteBlobString(image,buffer); (void) WriteBlobString(image,"<Data>"); (void) SetImageColorspace(image,RGBColorspace); for (y=0; y < (long) image->rows; y++) { p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; for (x=0; x < ((long) image->columns-3); x+=4) { byte=(unsigned char) (((4*PixelIntensityToQuantum(p+3)/QuantumRange) & 0x03) << 6) | (((4*PixelIntensityToQuantum(p+2)/QuantumRange) & 0x03) << 4) | (((4*PixelIntensityToQuantum(p+1)/QuantumRange) & 0x03) << 2) | (((4*PixelIntensityToQuantum(p+0)/QuantumRange) & 0x03) << 0); (void) FormatMagickString(buffer,MaxTextExtent,"%02x",byte); (void) WriteBlobString(image,buffer); p+=4; } if ((image->columns % 4) != 0) { i=(long) image->columns % 4; byte=(unsigned char) ((((4*PixelIntensityToQuantum(p+Min(i,3))/QuantumRange) & 0x03) << 6) | (((4*PixelIntensityToQuantum(p+Min(i,2))/QuantumRange) & 0x03) << 4) | (((4*PixelIntensityToQuantum(p+Min(i,1))/QuantumRange) & 0x03) << 2) | (((4*PixelIntensityToQuantum(p+Min(i,0))/QuantumRange) & 0x03) << 0)); (void) FormatMagickString(buffer,MaxTextExtent,"%02x",~byte); (void) WriteBlobString(image,buffer); } if ((image->progress_monitor != (MagickProgressMonitor) NULL) && (QuantumTick(y,image->rows) != MagickFalse)) { status=image->progress_monitor(SaveImageTag,y,image->rows, image->client_data); if (status == MagickFalse) break; } } (void) WriteBlobString(image,"</Data>\n"); (void) WriteBlobString(image,"</CiscoIPPhoneImage>\n"); CloseBlob(image); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e U I L I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure WriteUILImage() writes an image to a file in the X-Motif UIL table % format. % % The format of the WriteUILImage method is: % % MagickBooleanType WriteUILImage(const ImageInfo *image_info,Image *image) % % A description of each parameter follows. % % o image_info: the image info. % % o image: The image. % */ static MagickBooleanType WriteUILImage(const ImageInfo *image_info,Image *image) { #define MaxCixels 92 char basename[MaxTextExtent], buffer[MaxTextExtent], name[MaxTextExtent], *symbol; ExceptionInfo *exception; int j; MagickBooleanType status, transparent; MagickPixelPacket pixel; MagickSizeType number_pixels; register const IndexPacket *indexes; register const PixelPacket *p; register ssize_t i, x; size_t characters_per_pixel, colors; ssize_t k, y; static const char Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; /* Open output image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == MagickFalse) return(status); if (IsRGBColorspace(image->colorspace) == MagickFalse) (void) TransformImageColorspace(image,RGBColorspace); exception=(&image->exception); transparent=MagickFalse; i=0; p=(const PixelPacket *) NULL; if (image->storage_class == PseudoClass) colors=image->colors; else { unsigned char *matte_image; /* Convert DirectClass to PseudoClass image. */ matte_image=(unsigned char *) NULL; if (image->matte != MagickFalse) { /* Map all the transparent pixels. */ number_pixels=(MagickSizeType) image->columns*image->rows; if (number_pixels != ((MagickSizeType) (size_t) number_pixels)) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); matte_image=(unsigned char *) AcquireQuantumMemory(image->columns, image->rows*sizeof(*matte_image)); if (matte_image == (unsigned char *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const PixelPacket *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { matte_image[i]=(unsigned char) (GetPixelOpacity(p) == (Quantum) TransparentOpacity ? 1 : 0); if (matte_image[i] != 0) transparent=MagickTrue; i++; p++; } } } (void) SetImageType(image,PaletteType); colors=image->colors; if (transparent != MagickFalse) { register IndexPacket *indexes; register PixelPacket *q; colors++; for (y=0; y < (ssize_t) image->rows; y++) { q=GetAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; indexes=GetAuthenticIndexQueue(image); for (x=0; x < (ssize_t) image->columns; x++) { if (matte_image[i] != 0) SetPixelIndex(indexes+x,image->colors); p++; } } } if (matte_image != (unsigned char *) NULL) matte_image=(unsigned char *) RelinquishMagickMemory(matte_image); } /* Compute the character per pixel. */ characters_per_pixel=1; for (k=MaxCixels; (ssize_t) colors > k; k*=MaxCixels) characters_per_pixel++; /* UIL header. */ symbol=AcquireString(""); (void) WriteBlobString(image,"/* UIL */\n"); GetPathComponent(image->filename,BasePath,basename); (void) FormatLocaleString(buffer,MaxTextExtent, "value\n %s_ct : color_table(\n",basename); (void) WriteBlobString(image,buffer); GetMagickPixelPacket(image,&pixel); for (i=0; i < (ssize_t) colors; i++) { /* Define UIL color. */ SetMagickPixelPacket(image,image->colormap+i,(IndexPacket *) NULL,&pixel); pixel.colorspace=RGBColorspace; pixel.depth=8; pixel.opacity=(MagickRealType) OpaqueOpacity; GetColorTuple(&pixel,MagickTrue,name); if (transparent != MagickFalse) if (i == (ssize_t) (colors-1)) (void) CopyMagickString(name,"None",MaxTextExtent); /* Write UIL color. */ k=i % MaxCixels; symbol[0]=Cixel[k]; for (j=1; j < (int) characters_per_pixel; j++) { k=((i-k)/MaxCixels) % MaxCixels; symbol[j]=Cixel[k]; } symbol[j]='\0'; (void) SubstituteString(&symbol,"'","''"); if (LocaleCompare(name,"None") == 0) (void) FormatLocaleString(buffer,MaxTextExtent, " background color = '%s'",symbol); else (void) FormatLocaleString(buffer,MaxTextExtent, " color('%s',%s) = '%s'",name, PixelIntensityToQuantum(image->colormap+i) < ((Quantum) QuantumRange/2) ? "background" : "foreground",symbol); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MaxTextExtent,"%s", (i == (ssize_t) (colors-1) ? ");\n" : ",\n")); (void) WriteBlobString(image,buffer); } /* Define UIL pixels. */ GetPathComponent(image->filename,BasePath,basename); (void) FormatLocaleString(buffer,MaxTextExtent, " %s_icon : icon(color_table = %s_ct,\n",basename,basename); (void) WriteBlobString(image,buffer); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; indexes=GetVirtualIndexQueue(image); (void) WriteBlobString(image," \""); for (x=0; x < (ssize_t) image->columns; x++) { k=((ssize_t) GetPixelIndex(indexes+x) % MaxCixels); symbol[0]=Cixel[k]; for (j=1; j < (int) characters_per_pixel; j++) { k=(((int) GetPixelIndex(indexes+x)-k)/MaxCixels) % MaxCixels; symbol[j]=Cixel[k]; } symbol[j]='\0'; (void) CopyMagickString(buffer,symbol,MaxTextExtent); (void) WriteBlobString(image,buffer); p++; } (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s\n", (y == (ssize_t) (image->rows-1) ? ");" : ",")); (void) WriteBlobString(image,buffer); status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } symbol=DestroyString(symbol); (void) CloseBlob(image); return(MagickTrue); }