/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e F I T S I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteFITSImage() writes a Flexible Image Transport System image to a % file as gray scale intensities [0..255]. % % The format of the WriteFITSImage method is: % % MagickBooleanType WriteFITSImage(const ImageInfo *image_info, % Image *image) % % A description of each parameter follows. % % o image_info: the image info. % % o image: The image. % */ static MagickBooleanType WriteFITSImage(const ImageInfo *image_info, Image *image) { char header[FITSBlocksize], *fits_info; MagickBooleanType status; QuantumInfo *quantum_info; register const PixelPacket *p; size_t length; ssize_t count, offset, y; 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); (void) TransformImageColorspace(image,sRGBColorspace); /* Allocate image memory. */ fits_info=(char *) AcquireQuantumMemory(FITSBlocksize,sizeof(*fits_info)); if (fits_info == (char *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); (void) ResetMagickMemory(fits_info,' ',FITSBlocksize*sizeof(*fits_info)); /* Initialize image header. */ image->depth=GetImageQuantumDepth(image,MagickFalse); image->endian=MSBEndian; quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image); if (quantum_info == (QuantumInfo *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); offset=0; (void) FormatLocaleString(header,FITSBlocksize, "SIMPLE = T"); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; (void) FormatLocaleString(header,FITSBlocksize,"BITPIX = %10ld", (long) ((quantum_info->format == FloatingPointQuantumFormat ? -1 : 1)* image->depth)); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; (void) FormatLocaleString(header,FITSBlocksize,"NAXIS = %10lu", IsGrayImage(image,&image->exception) != MagickFalse ? 2UL : 3UL); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; (void) FormatLocaleString(header,FITSBlocksize,"NAXIS1 = %10lu", (unsigned long) image->columns); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; (void) FormatLocaleString(header,FITSBlocksize,"NAXIS2 = %10lu", (unsigned long) image->rows); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; if (IsGrayImage(image,&image->exception) == MagickFalse) { (void) FormatLocaleString(header,FITSBlocksize, "NAXIS3 = %10lu",3UL); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; } (void) FormatLocaleString(header,FITSBlocksize,"BSCALE = %E",1.0); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; (void) FormatLocaleString(header,FITSBlocksize,"BZERO = %E", image->depth > 8 ? GetFITSPixelRange(image->depth)/2.0 : 0.0); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; (void) FormatLocaleString(header,FITSBlocksize,"DATAMAX = %E", 1.0*((MagickOffsetType) GetQuantumRange(image->depth))); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; (void) FormatLocaleString(header,FITSBlocksize,"DATAMIN = %E",0.0); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; if (image->endian == LSBEndian) { (void) FormatLocaleString(header,FITSBlocksize,"XENDIAN = 'SMALL'"); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; } (void) FormatLocaleString(header,FITSBlocksize,"HISTORY %.72s", GetMagickVersion((size_t *) NULL)); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; (void) strncpy(header,"END",FITSBlocksize); (void) strncpy(fits_info+offset,header,strlen(header)); offset+=80; (void) WriteBlob(image,FITSBlocksize,(unsigned char *) fits_info); /* Convert image to fits scale PseudoColor class. */ pixels=GetQuantumPixels(quantum_info); if (IsGrayImage(image,&image->exception) != MagickFalse) { length=GetQuantumExtent(image,quantum_info,GrayQuantum); for (y=(ssize_t) image->rows-1; y >= 0; y--) { p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info, GrayQuantum,pixels,&image->exception); if (image->depth == 16) SetFITSUnsignedPixels(image->columns,image->depth,image->endian, pixels); if (((image->depth == 32) || (image->depth == 64)) && (quantum_info->format != FloatingPointQuantumFormat)) SetFITSUnsignedPixels(image->columns,image->depth,image->endian, pixels); count=WriteBlob(image,length,pixels); if (count != (ssize_t) length) break; status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } else { length=GetQuantumExtent(image,quantum_info,RedQuantum); for (y=(ssize_t) image->rows-1; y >= 0; y--) { p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info, RedQuantum,pixels,&image->exception); if (image->depth == 16) SetFITSUnsignedPixels(image->columns,image->depth,image->endian, pixels); if (((image->depth == 32) || (image->depth == 64)) && (quantum_info->format != FloatingPointQuantumFormat)) SetFITSUnsignedPixels(image->columns,image->depth,image->endian, pixels); count=WriteBlob(image,length,pixels); if (count != (ssize_t) length) break; status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } length=GetQuantumExtent(image,quantum_info,GreenQuantum); for (y=(ssize_t) image->rows-1; y >= 0; y--) { p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info, GreenQuantum,pixels,&image->exception); if (image->depth == 16) SetFITSUnsignedPixels(image->columns,image->depth,image->endian, pixels); if (((image->depth == 32) || (image->depth == 64)) && (quantum_info->format != FloatingPointQuantumFormat)) SetFITSUnsignedPixels(image->columns,image->depth,image->endian, pixels); count=WriteBlob(image,length,pixels); if (count != (ssize_t) length) break; status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } length=GetQuantumExtent(image,quantum_info,BlueQuantum); for (y=(ssize_t) image->rows-1; y >= 0; y--) { p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info, BlueQuantum,pixels,&image->exception); if (image->depth == 16) SetFITSUnsignedPixels(image->columns,image->depth,image->endian, pixels); if (((image->depth == 32) || (image->depth == 64)) && (quantum_info->format != FloatingPointQuantumFormat)) SetFITSUnsignedPixels(image->columns,image->depth,image->endian, pixels); count=WriteBlob(image,length,pixels); if (count != (ssize_t) length) break; status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } quantum_info=DestroyQuantumInfo(quantum_info); length=(size_t) (FITSBlocksize-TellBlob(image) % FITSBlocksize); if (length != 0) { (void) ResetMagickMemory(fits_info,0,length*sizeof(*fits_info)); (void) WriteBlob(image,length,(unsigned char *) fits_info); } fits_info=DestroyString(fits_info); (void) CloseBlob(image); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % P a r s e G r a v i t y G e o m e t r y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ParseGravityGeometry() returns a region as defined by the geometry string % with respect to the given image page (canvas) dimensions and the images % gravity setting. % % This is typically used for specifing a area within a given image for % cropping images to a smaller size, chopping out rows and or columns, or % resizing and positioning overlay images. % % Percentages are relative to image size and not page size, and are set to % nearest integer (pixel) size. % % The format of the ParseGravityGeometry method is: % % MagickStatusType ParseGravityGeometry(Image *image,const char *geometry, % RectangeInfo *region_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o geometry: The geometry string (e.g. "100x100+10+10"). % % o region_info: the region as defined by the geometry string with respect % to the image dimensions and its gravity. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickStatusType ParseGravityGeometry(const Image *image, const char *geometry,RectangleInfo *region_info,ExceptionInfo *exception) { MagickStatusType flags; size_t height, width; SetGeometry(image,region_info); if (image->page.width != 0) region_info->width=image->page.width; if (image->page.height != 0) region_info->height=image->page.height; flags=ParseAbsoluteGeometry(geometry,region_info); if (flags == NoValue) { (void) ThrowMagickException(exception,GetMagickModule(),OptionError, "InvalidGeometry","`%s'",geometry); return(flags); } if ((flags & PercentValue) != 0) { GeometryInfo geometry_info; MagickStatusType status; PointInfo scale; /* Geometry is a percentage of the image size, not canvas size */ if (image->gravity != UndefinedGravity) flags|=XValue | YValue; status=ParseGeometry(geometry,&geometry_info); scale.x=geometry_info.rho; if ((status & RhoValue) == 0) scale.x=100.0; scale.y=geometry_info.sigma; if ((status & SigmaValue) == 0) scale.y=scale.x; region_info->width=(size_t) floor((scale.x*image->columns/100.0)+0.5); region_info->height=(size_t) floor((scale.y*image->rows/100.0)+0.5); } /* Adjust offset according to gravity setting. */ width=region_info->width; height=region_info->height; if (width == 0) region_info->width=image->page.width | image->columns; if (height == 0) region_info->height=image->page.height | image->rows; GravityAdjustGeometry(image->columns,image->rows,image->gravity,region_info); region_info->width=width; region_info->height=height; return(flags); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % S e t G e o m e t r y I n f o % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SetGeometryInfo sets the GeometryInfo structure to its default values. % % The format of the SetGeometryInfo method is: % % SetGeometryInfo(GeometryInfo *geometry_info) % % A description of each parameter follows: % % o geometry_info: the geometry info structure. % */ MagickExport void SetGeometryInfo(GeometryInfo *geometry_info) { assert(geometry_info != (GeometryInfo *) NULL); (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); (void) ResetMagickMemory(geometry_info,0,sizeof(*geometry_info)); }
MagickExport MagickBooleanType AccelerateConvolveImage(const Image *image, const KernelInfo *kernel,Image *convolve_image,ExceptionInfo *exception) { assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(kernel != (KernelInfo *) NULL); assert(kernel->signature == MagickSignature); assert(convolve_image != (Image *) NULL); assert(convolve_image->signature == MagickSignature); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); if ((image->storage_class != DirectClass) || (image->colorspace == CMYKColorspace)) if ((GetImageVirtualPixelMethod(image) != UndefinedVirtualPixelMethod) && (GetImageVirtualPixelMethod(image) != EdgeVirtualPixelMethod)) return(MagickFalse); #if !defined(MAGICKCORE_OPENCL_SUPPORT) return(MagickFalse); #else { const void *pixels; ConvolveInfo *convolve_info; MagickBooleanType status; MagickSizeType length; void *convolve_pixels; convolve_info=GetConvolveInfo(image,"Convolve",ConvolveKernel,exception); if (convolve_info == (ConvolveInfo *) NULL) return(MagickFalse); pixels=AcquirePixelCachePixels(image,&length,exception); if (pixels == (const void *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(),CacheError, "UnableToReadPixelCache","`%s'",image->filename); convolve_info=DestroyConvolveInfo(convolve_info); return(MagickFalse); } convolve_pixels=GetPixelCachePixels(convolve_image,&length,exception); if (convolve_pixels == (void *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(),CacheError, "UnableToReadPixelCache","`%s'",image->filename); convolve_info=DestroyConvolveInfo(convolve_info); return(MagickFalse); } status=BindConvolveParameters(convolve_info,image,pixels,kernel->values, kernel->width,kernel->height,convolve_pixels); if (status == MagickFalse) { DestroyConvolveBuffers(convolve_info); convolve_info=DestroyConvolveInfo(convolve_info); return(MagickFalse); } status=EnqueueConvolveKernel(convolve_info,image,pixels,kernel->values, kernel->width,kernel->height,convolve_pixels); if (status == MagickFalse) { DestroyConvolveBuffers(convolve_info); convolve_info=DestroyConvolveInfo(convolve_info); return(MagickFalse); } DestroyConvolveBuffers(convolve_info); convolve_info=DestroyConvolveInfo(convolve_info); return(MagickTrue); } #endif }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d X C F I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadXCFImage() reads a GIMP (GNU Image Manipulation Program) image % file and returns it. It allocates the memory necessary for the new Image % structure and returns a pointer to the new image. % % The format of the ReadXCFImage method is: % % image=ReadXCFImage(image_info) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % % */ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception) { char magick[14]; Image *image; int foundPropEnd = 0; MagickBooleanType status; MagickOffsetType offset; register long i; size_t length; ssize_t count; unsigned long image_type; XCFDocInfo doc_info; /* Open image file. */ 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); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } count=ReadBlob(image,14,(unsigned char *) magick); if ((count == 0) || (LocaleNCompare((char *) magick,"gimp xcf",8) != 0)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); (void) ResetMagickMemory(&doc_info,0,sizeof(XCFDocInfo)); doc_info.exception=exception; doc_info.width=ReadBlobMSBLong(image); doc_info.height=ReadBlobMSBLong(image); if ((doc_info.width > 262144) || (doc_info.height > 262144)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); doc_info.image_type=ReadBlobMSBLong(image); /* Initialize image attributes. */ image->columns=doc_info.width; image->rows=doc_info.height; image_type=doc_info.image_type; doc_info.file_size=GetBlobSize(image); image->compression=NoCompression; image->depth=8; if (image_type == GIMP_RGB) image->colorspace=RGBColorspace; else if (image_type == GIMP_GRAY) image->colorspace=GRAYColorspace; else if (image_type == GIMP_INDEXED) ThrowReaderException(CoderError,"ColormapTypeNotSupported"); (void) SetImageBackgroundColor(image); image->matte=MagickTrue; /* Read properties. */ while ((foundPropEnd == MagickFalse) && (EOFBlob(image) == MagickFalse)) { PropType prop_type = (PropType) ReadBlobMSBLong(image); unsigned long prop_size = ReadBlobMSBLong(image); switch (prop_type) { case PROP_END: foundPropEnd=1; break; case PROP_COLORMAP: { /* Cannot rely on prop_size here--the value is set incorrectly by some Gimp versions. */ unsigned long num_colours = ReadBlobMSBLong(image); for (i=0; i < (long) (3L*num_colours); i++ ) (void) ReadBlobByte(image); /* if (info->file_version == 0) { gint i; g_message (_("XCF warning: version 0 of XCF file format\n" "did not save indexed colormaps correctly.\n" "Substituting grayscale map.")); info->cp += xcf_read_int32 (info->fp, (guint32*) &gimage->num_cols, 1); gimage->cmap = g_new (guchar, gimage->num_cols*3); xcf_seek_pos (info, info->cp + gimage->num_cols); for (i = 0; i<gimage->num_cols; i++) { gimage->cmap[i*3+0] = i; gimage->cmap[i*3+1] = i; gimage->cmap[i*3+2] = i; } } else { info->cp += xcf_read_int32 (info->fp, (guint32*) &gimage->num_cols, 1); gimage->cmap = g_new (guchar, gimage->num_cols*3); info->cp += xcf_read_int8 (info->fp, (guint8*) gimage->cmap, gimage->num_cols*3); } */ break; } case PROP_COMPRESSION: { doc_info.compression = ReadBlobByte(image); if ((doc_info.compression != COMPRESS_NONE) && (doc_info.compression != COMPRESS_RLE) && (doc_info.compression != COMPRESS_ZLIB) && (doc_info.compression != COMPRESS_FRACTAL)) ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression"); } break; case PROP_GUIDES: { /* just skip it - we don't care about guides */ for (i=0; i < (long) prop_size; i++ ) if (ReadBlobByte(image) == EOF) ThrowFileException(exception,CorruptImageError, "UnexpectedEndOfFile",image->filename); } break; case PROP_RESOLUTION: { /* float xres = (float) */ (void) ReadBlobMSBLong(image); /* float yres = (float) */ (void) ReadBlobMSBLong(image); /* if (xres < GIMP_MIN_RESOLUTION || xres > GIMP_MAX_RESOLUTION || yres < GIMP_MIN_RESOLUTION || yres > GIMP_MAX_RESOLUTION) { g_message ("Warning, resolution out of range in XCF file"); xres = gimage->gimp->config->default_xresolution; yres = gimage->gimp->config->default_yresolution; } */ /* BOGUS: we don't write these yet because we aren't reading them properly yet :( image->x_resolution = xres; image->y_resolution = yres; */ } break; case PROP_TATTOO: { /* we need to read it, even if we ignore it */ /*unsigned long tattoo_state = */ (void) ReadBlobMSBLong(image); } break; case PROP_PARASITES: { /* BOGUS: we may need these for IPTC stuff */ for (i=0; i < (long) prop_size; i++ ) if (ReadBlobByte(image) == EOF) ThrowFileException(exception,CorruptImageError, "UnexpectedEndOfFile",image->filename); /* glong base = info->cp; GimpParasite *p; while (info->cp - base < prop_size) { p = xcf_load_parasite (info); gimp_image_parasite_attach (gimage, p); gimp_parasite_free (p); } if (info->cp - base != prop_size) g_message ("Error detected while loading an image's parasites"); */ } break; case PROP_UNIT: { /* BOGUS: ignore for now... */ /*unsigned long unit = */ (void) ReadBlobMSBLong(image); } break; case PROP_PATHS: { /* BOGUS: just skip it for now */ for (i=0; i< (long) prop_size; i++ ) if (ReadBlobByte(image) == EOF) ThrowFileException(exception,CorruptImageError, "UnexpectedEndOfFile",image->filename); /* PathList *paths = xcf_load_bzpaths (gimage, info); gimp_image_set_paths (gimage, paths); */ } break; case PROP_USER_UNIT: { char unit_string[1000]; /*BOGUS: ignored for now */ /*float factor = (float) */ (void) ReadBlobMSBLong(image); /* unsigned long digits = */ (void) ReadBlobMSBLong(image); for (i=0; i<5; i++) (void) ReadBlobStringWithLongSize(image, unit_string, sizeof(unit_string)); } break; default: { int buf[16]; long amount; /* read over it... */ while ((prop_size > 0) && (EOFBlob(image) == MagickFalse)) { amount=(long) MagickMin(16, prop_size); amount=(long) ReadBlob(image,(size_t) amount,(unsigned char *) &buf); if (!amount) ThrowReaderException(CorruptImageError,"CorruptImage"); prop_size -= (unsigned long) MagickMin(16,(size_t) amount); } } break; } } if (foundPropEnd == MagickFalse) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) { ; /* do nothing, were just pinging! */ } else { int current_layer = 0, foundAllLayers = MagickFalse, number_layers = 0; MagickOffsetType oldPos=TellBlob(image); XCFLayerInfo *layer_info; /* the read pointer */ do { long offset = (long) ReadBlobMSBLong(image); if (offset == 0) foundAllLayers=MagickTrue; else number_layers++; if (EOFBlob(image) != MagickFalse) { ThrowFileException(exception,CorruptImageError, "UnexpectedEndOfFile",image->filename); break; } } while (foundAllLayers == MagickFalse); offset=SeekBlob(image,oldPos,SEEK_SET); /* restore the position! */ if (offset < 0) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); /* allocate our array of layer info blocks */ length=(size_t) number_layers; layer_info=(XCFLayerInfo *) AcquireQuantumMemory(length, sizeof(*layer_info)); if (layer_info == (XCFLayerInfo *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); (void) ResetMagickMemory(layer_info,0,number_layers*sizeof(XCFLayerInfo)); for ( ; ; ) { MagickBooleanType layer_ok; MagickOffsetType offset, saved_pos; /* read in the offset of the next layer */ offset=(MagickOffsetType) ReadBlobMSBLong(image); /* if the offset is 0 then we are at the end * of the layer list. */ if (offset == 0) break; /* save the current position as it is where the * next layer offset is stored. */ saved_pos=TellBlob(image); /* seek to the layer offset */ offset=SeekBlob(image,offset,SEEK_SET); /* read in the layer */ layer_ok=ReadOneLayer(image,&doc_info,&layer_info[current_layer]); if (layer_ok == MagickFalse) { int j; for (j=0; j < current_layer; j++) layer_info[j].image=DestroyImage(layer_info[j].image); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } /* restore the saved position so we'll be ready to * read the next offset. */ offset=SeekBlob(image, saved_pos, SEEK_SET); current_layer++; } if (number_layers == 1) { /* Composite the layer data onto the main image, dispose the layer. */ (void) CompositeImage(image,OverCompositeOp,layer_info[0].image, layer_info[0].offset_x,layer_info[0].offset_y); layer_info[0].image =DestroyImage( layer_info[0].image); } else { #if 0 { /* NOTE: XCF layers are REVERSED from composite order! */ signed int j; for (j=number_layers-1; j>=0; j--) { /* BOGUS: need to consider layer blending modes!! */ if ( layer_info[j].visible ) { /* only visible ones, please! */ CompositeImage(image, OverCompositeOp, layer_info[j].image, layer_info[j].offset_x, layer_info[j].offset_y ); layer_info[j].image =DestroyImage( layer_info[j].image ); /* Bob says that if we do this, we'll get REAL gray images! */ if ( image_type == GIMP_GRAY ) { QuantizeInfo qi; GetQuantizeInfo(&qi); qi.colorspace = GRAYColorspace; QuantizeImage( &qi, layer_info[j].image ); } } } } #else { /* NOTE: XCF layers are REVERSED from composite order! */ signed int j; /* first we copy the last layer on top of the main image */ (void) CompositeImage(image,CopyCompositeOp, layer_info[number_layers-1].image, layer_info[number_layers-1].offset_x, layer_info[number_layers-1].offset_y); layer_info[number_layers-1].image=DestroyImage( layer_info[number_layers-1].image); /* now reverse the order of the layers as they are put into subimages */ j=number_layers-2; image->next=layer_info[j].image; layer_info[j].image->previous=image; layer_info[j].image->page.x=layer_info[j].offset_x; layer_info[j].image->page.y=layer_info[j].offset_y; layer_info[j].image->page.width=layer_info[j].width; layer_info[j].image->page.height=layer_info[j].height; for (j=number_layers-3; j>=0; j--) { if (j > 0) layer_info[j].image->next=layer_info[j-1].image; if (j < (number_layers-1)) layer_info[j].image->previous=layer_info[j+1].image; layer_info[j].image->page.x=layer_info[j].offset_x; layer_info[j].image->page.y=layer_info[j].offset_y; layer_info[j].image->page.width=layer_info[j].width; layer_info[j].image->page.height=layer_info[j].height; } } #endif } layer_info=(XCFLayerInfo *) RelinquishMagickMemory(layer_info); #if 0 /* BOGUS: do we need the channels?? */ while (MagickTrue) { /* read in the offset of the next channel */ info->cp += xcf_read_int32 (info->fp, &offset, 1); /* if the offset is 0 then we are at the end * of the channel list. */ if (offset == 0) break; /* save the current position as it is where the * next channel offset is stored. */ saved_pos = info->cp; /* seek to the channel offset */ xcf_seek_pos (info, offset); /* read in the layer */ channel = xcf_load_channel (info, gimage); if (channel == 0) goto error; num_successful_elements++; /* add the channel to the image if its not the selection */ if (channel != gimage->selection_mask) gimp_image_add_channel (gimage, channel, -1); /* restore the saved position so we'll be ready to * read the next offset. */ xcf_seek_pos (info, saved_pos); } #endif } (void) CloseBlob(image); if (image_type == GIMP_GRAY) image->type=GrayscaleType; return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d R L E I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadRLEImage() reads a run-length encoded Utah Raster Toolkit % image file and returns it. It allocates the memory necessary for the new % Image structure and returns a pointer to the new image. % % The format of the ReadRLEImage method is: % % Image *ReadRLEImage(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 *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception) { #define SkipLinesOp 0x01 #define SetColorOp 0x02 #define SkipPixelsOp 0x03 #define ByteDataOp 0x05 #define RunDataOp 0x06 #define EOFOp 0x07 char magick[12]; Image *image; int opcode, operand, status; MagickStatusType flags; MagickSizeType number_pixels; register IndexPacket *indexes; register ssize_t x; register PixelPacket *q; register ssize_t i; register unsigned char *p; size_t bits_per_pixel, map_length, number_colormaps, number_planes, one; ssize_t count, y; unsigned char background_color[256], *colormap, pixel, plane, *rle_pixels; /* Open image file. */ 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); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } /* Determine if this a RLE file. */ count=ReadBlob(image,2,(unsigned char *) magick); if ((count == 0) || (memcmp(magick,"\122\314",2) != 0)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); do { /* Read image header. */ (void) ReadBlobLSBShort(image); (void) ReadBlobLSBShort(image); image->columns=ReadBlobLSBShort(image); image->rows=ReadBlobLSBShort(image); flags=(MagickStatusType) ReadBlobByte(image); image->matte=flags & 0x04 ? MagickTrue : MagickFalse; number_planes=1UL*ReadBlobByte(image); bits_per_pixel=1UL*ReadBlobByte(image); number_colormaps=1UL*ReadBlobByte(image); one=1; map_length=one << ReadBlobByte(image); if ((number_planes == 0) || (number_planes == 2) || (bits_per_pixel != 8) || (image->columns == 0)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); if (flags & 0x02) { /* No background color-- initialize to black. */ for (i=0; i < (ssize_t) number_planes; i++) background_color[i]=0; (void) ReadBlobByte(image); } else { /* Initialize background color. */ p=background_color; for (i=0; i < (ssize_t) number_planes; i++) *p++=(unsigned char) ReadBlobByte(image); } if ((number_planes & 0x01) == 0) (void) ReadBlobByte(image); colormap=(unsigned char *) NULL; if (number_colormaps != 0) { /* Read image colormaps. */ colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps, map_length*sizeof(*colormap)); if (colormap == (unsigned char *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); p=colormap; for (i=0; i < (ssize_t) number_colormaps; i++) for (x=0; x < (ssize_t) map_length; x++) *p++=(unsigned char) ScaleShortToQuantum(ReadBlobLSBShort(image)); } if ((flags & 0x08) != 0) { char *comment; size_t length; /* Read image comment. */ length=ReadBlobLSBShort(image); if (length != 0) { comment=(char *) AcquireQuantumMemory(length,sizeof(*comment)); if (comment == (char *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); count=ReadBlob(image,length-1,(unsigned char *) comment); comment[length-1]='\0'; (void) SetImageProperty(image,"comment",comment); comment=DestroyString(comment); if ((length & 0x01) == 0) (void) ReadBlobByte(image); } } if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) if (image->scene >= (image_info->scene+image_info->number_scenes-1)) break; /* Allocate RLE pixels. */ if (image->matte != MagickFalse) number_planes++; number_pixels=(MagickSizeType) image->columns*image->rows; if ((number_pixels*number_planes) != (size_t) (number_pixels*number_planes)) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); rle_pixels=(unsigned char *) AcquireQuantumMemory(image->columns, image->rows*number_planes*sizeof(*rle_pixels)); if (rle_pixels == (unsigned char *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); if ((flags & 0x01) && !(flags & 0x02)) { ssize_t j; /* Set background color. */ p=rle_pixels; for (i=0; i < (ssize_t) number_pixels; i++) { if (image->matte == MagickFalse) for (j=0; j < (ssize_t) number_planes; j++) *p++=background_color[j]; else { for (j=0; j < (ssize_t) (number_planes-1); j++) *p++=background_color[j]; *p++=0; /* initialize matte channel */ } } } /* Read runlength-encoded image. */ plane=0; x=0; y=0; opcode=ReadBlobByte(image); do { switch (opcode & 0x3f) { case SkipLinesOp: { operand=ReadBlobByte(image); if (opcode & 0x40) operand=(int) ReadBlobLSBShort(image); x=0; y+=operand; break; } case SetColorOp: { operand=ReadBlobByte(image); plane=(unsigned char) operand; if (plane == 255) plane=(unsigned char) (number_planes-1); x=0; break; } case SkipPixelsOp: { operand=ReadBlobByte(image); if (opcode & 0x40) operand=(int) ReadBlobLSBShort(image); x+=operand; break; } case ByteDataOp: { operand=ReadBlobByte(image); if (opcode & 0x40) operand=(int) ReadBlobLSBShort(image); p=rle_pixels+((image->rows-y-1)*image->columns*number_planes)+ x*number_planes+plane; operand++; for (i=0; i < (ssize_t) operand; i++) { pixel=(unsigned char) ReadBlobByte(image); if ((y < (ssize_t) image->rows) && ((x+i) < (ssize_t) image->columns)) *p=pixel; p+=number_planes; } if (operand & 0x01) (void) ReadBlobByte(image); x+=operand; break; } case RunDataOp: { operand=ReadBlobByte(image); if (opcode & 0x40) operand=(int) ReadBlobLSBShort(image); pixel=(unsigned char) ReadBlobByte(image); (void) ReadBlobByte(image); operand++; p=rle_pixels+((image->rows-y-1)*image->columns*number_planes)+ x*number_planes+plane; for (i=0; i < (ssize_t) operand; i++) { if ((y < (ssize_t) image->rows) && ((x+i) < (ssize_t) image->columns)) *p=pixel; p+=number_planes; } x+=operand; break; } default: break; } opcode=ReadBlobByte(image); } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF)); if (number_colormaps != 0) { MagickStatusType mask; /* Apply colormap affineation to image. */ mask=(MagickStatusType) (map_length-1); p=rle_pixels; if (number_colormaps == 1) for (i=0; i < (ssize_t) number_pixels; i++) { *p=colormap[*p & mask]; p++; } else if ((number_planes >= 3) && (number_colormaps >= 3)) for (i=0; i < (ssize_t) number_pixels; i++) for (x=0; x < (ssize_t) number_planes; x++) { *p=colormap[x*map_length+(*p & mask)]; p++; } } /* Initialize image structure. */ if (number_planes >= 3) { /* Convert raster image to DirectClass pixel packets. */ p=rle_pixels; for (y=0; y < (ssize_t) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,ScaleCharToQuantum(*p++)); SetPixelGreen(q,ScaleCharToQuantum(*p++)); SetPixelBlue(q,ScaleCharToQuantum(*p++)); if (image->matte != MagickFalse) SetPixelAlpha(q,ScaleCharToQuantum(*p++)); q++; } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } } else { /* Create colormap. */ if (number_colormaps == 0) map_length=256; if (AcquireImageColormap(image,map_length) == MagickFalse) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); p=colormap; if (number_colormaps == 1) for (i=0; i < (ssize_t) image->colors; i++) { /* Pseudocolor. */ image->colormap[i].red=ScaleCharToQuantum((unsigned char) i); image->colormap[i].green=ScaleCharToQuantum((unsigned char) i); image->colormap[i].blue=ScaleCharToQuantum((unsigned char) i); } else if (number_colormaps > 1) for (i=0; i < (ssize_t) image->colors; i++) { image->colormap[i].red=ScaleCharToQuantum(*p); image->colormap[i].green=ScaleCharToQuantum(*(p+map_length)); image->colormap[i].blue=ScaleCharToQuantum(*(p+map_length*2)); p++; } p=rle_pixels; if (image->matte == MagickFalse) { /* Convert raster image to PseudoClass pixel packets. */ for (y=0; y < (ssize_t) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; indexes=GetAuthenticIndexQueue(image); for (x=0; x < (ssize_t) image->columns; x++) SetPixelIndex(indexes+x,*p++); if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,image->rows); if (status == MagickFalse) break; } } (void) SyncImage(image); } else { /* Image has a matte channel-- promote to DirectClass. */ for (y=0; y < (ssize_t) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { SetPixelRed(q,image->colormap[*p++].red); SetPixelGreen(q,image->colormap[*p++].green); SetPixelBlue(q,image->colormap[*p++].blue); SetPixelAlpha(q,ScaleCharToQuantum(*p++)); q++; } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,image->rows); if (status == MagickFalse) break; } } image->colormap=(PixelPacket *) RelinquishMagickMemory( image->colormap); image->storage_class=DirectClass; image->colors=0; } } if (number_colormaps != 0) colormap=(unsigned char *) RelinquishMagickMemory(colormap); rle_pixels=(unsigned char *) RelinquishMagickMemory(rle_pixels); if (EOFBlob(image) != MagickFalse) { ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", image->filename); break; } /* Proceed to next image. */ if (image_info->number_scenes != 0) if (image->scene >= (image_info->scene+image_info->number_scenes-1)) break; (void) ReadBlobByte(image); count=ReadBlob(image,2,(unsigned char *) magick); if ((count != 0) && (memcmp(magick,"\122\314",2) == 0)) { /* Allocate next image structure. */ AcquireNextImage(image_info,image); if (GetNextImageInList(image) == (Image *) NULL) { image=DestroyImageList(image); return((Image *) NULL); } image=SyncNextImageInList(image); status=SetImageProgress(image,LoadImagesTag,TellBlob(image), GetBlobSize(image)); if (status == MagickFalse) break; } } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0)); (void) CloseBlob(image); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d S C T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadSCTImage() reads a Scitex image file and returns it. It allocates % the memory necessary for the new Image structure and returns a pointer to % the new image. % % The format of the ReadSCTImage method is: % % Image *ReadSCTImage(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 *ReadSCTImage(const ImageInfo *image_info,ExceptionInfo *exception) { char magick[2]; Image *image; long y; MagickBooleanType status; MagickRealType height, width; Quantum pixel; register IndexPacket *indexes; register long i, x; register PixelPacket *q; ssize_t count; unsigned char buffer[768]; unsigned long separations, separations_mask, units; /* Open image file. */ 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); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } /* Read control block. */ count=ReadBlob(image,80,buffer); count=ReadBlob(image,2,(unsigned char *) magick); if ((LocaleNCompare((char *) magick,"CT",2) != 0) && (LocaleNCompare((char *) magick,"LW",2) != 0) && (LocaleNCompare((char *) magick,"BM",2) != 0) && (LocaleNCompare((char *) magick,"PG",2) != 0) && (LocaleNCompare((char *) magick,"TX",2) != 0)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); if ((LocaleNCompare((char *) magick,"LW",2) == 0) || (LocaleNCompare((char *) magick,"BM",2) == 0) || (LocaleNCompare((char *) magick,"PG",2) == 0) || (LocaleNCompare((char *) magick,"TX",2) == 0)) ThrowReaderException(CoderError,"OnlyContinuousTonePictureSupported"); count=ReadBlob(image,174,buffer); count=ReadBlob(image,768,buffer); /* Read paramter block. */ units=1UL*ReadBlobByte(image); if (units == 0) image->units=PixelsPerCentimeterResolution; separations=1UL*ReadBlobByte(image); separations_mask=ReadBlobMSBShort(image); count=ReadBlob(image,14,buffer); buffer[14]='\0'; height=StringToDouble((char *) buffer); count=ReadBlob(image,14,buffer); width=StringToDouble((char *) buffer); count=ReadBlob(image,12,buffer); buffer[12]='\0'; image->rows=StringToUnsignedLong((char *) buffer); count=ReadBlob(image,12,buffer); image->columns=StringToUnsignedLong((char *) buffer); count=ReadBlob(image,200,buffer); count=ReadBlob(image,768,buffer); if (separations_mask == 0x0f) image->colorspace=CMYKColorspace; image->x_resolution=1.0*image->columns/width; image->y_resolution=1.0*image->rows/height; if (image_info->ping != MagickFalse) { (void) CloseBlob(image); return(GetFirstImageInList(image)); } /* Convert SCT raster image to pixel packets. */ for (y=0; y < (long) image->rows; y++) { for (i=0; i < (long) separations; i++) { q=GetAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; indexes=GetAuthenticIndexQueue(image); for (x=0; x < (long) image->columns; x++) { pixel=(Quantum) ScaleCharToQuantum((unsigned char) ReadBlobByte(image)); if (image->colorspace == CMYKColorspace) pixel=(Quantum) (QuantumRange-pixel); switch (i) { case 0: { q->red=pixel; q->green=pixel; q->blue=pixel; break; } case 1: { q->green=pixel; break; } case 2: { q->blue=pixel; break; break; } case 3: { if (image->colorspace == CMYKColorspace) indexes[x]=(IndexPacket) pixel; break; } } q++; } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if ((image->columns % 2) != 0) (void) ReadBlobByte(image); /* pad */ } status=SetImageProgress(image,LoadImageTag,y,image->rows); if (status == MagickFalse) break; } if (EOFBlob(image) != MagickFalse) ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", image->filename); (void) CloseBlob(image); return(GetFirstImageInList(image)); }
static MagickBooleanType LoadCoderList(const char *xml,const char *filename, const size_t depth,ExceptionInfo *exception) { char keyword[MaxTextExtent], *token; const char *q; CoderInfo *coder_info; MagickBooleanType status; /* Load the coder map file. */ (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), "Loading coder configuration file \"%s\" ...",filename); if (xml == (const char *) NULL) return(MagickFalse); if (coder_list == (SplayTreeInfo *) NULL) { coder_list=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory, DestroyCoderNode); if (coder_list == (SplayTreeInfo *) NULL) { ThrowFileException(exception,ResourceLimitError, "MemoryAllocationFailed",filename); return(MagickFalse); } } status=MagickTrue; coder_info=(CoderInfo *) NULL; token=AcquireString(xml); for (q=(char *) xml; *q != '\0'; ) { /* Interpret XML. */ GetMagickToken(q,&q,token); if (*token == '\0') break; (void) CopyMagickString(keyword,token,MaxTextExtent); if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0) { /* Doctype element. */ while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0')) GetMagickToken(q,&q,token); continue; } if (LocaleNCompare(keyword,"<!--",4) == 0) { /* Comment element. */ while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0')) GetMagickToken(q,&q,token); continue; } if (LocaleCompare(keyword,"<include") == 0) { /* Include element. */ while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0')) { (void) CopyMagickString(keyword,token,MaxTextExtent); GetMagickToken(q,&q,token); if (*token != '=') continue; GetMagickToken(q,&q,token); if (LocaleCompare(keyword,"file") == 0) { if (depth > 200) (void) ThrowMagickException(exception,GetMagickModule(), ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token); else { char path[MaxTextExtent], *xml; GetPathComponent(filename,HeadPath,path); if (*path != '\0') (void) ConcatenateMagickString(path,DirectorySeparator, MaxTextExtent); if (*token == *DirectorySeparator) (void) CopyMagickString(path,token,MaxTextExtent); else (void) ConcatenateMagickString(path,token,MaxTextExtent); xml=FileToString(path,~0,exception); if (xml != (char *) NULL) { status=LoadCoderList(xml,path,depth+1,exception); xml=(char *) RelinquishMagickMemory(xml); } } } } continue; } if (LocaleCompare(keyword,"<coder") == 0) { /* Coder element. */ coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info)); if (coder_info == (CoderInfo *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info)); coder_info->path=ConstantString(filename); coder_info->exempt=MagickFalse; coder_info->signature=MagickSignature; continue; } if (coder_info == (CoderInfo *) NULL) continue; if (LocaleCompare(keyword,"/>") == 0) { status=AddValueToSplayTree(coder_list,ConstantString( coder_info->magick),coder_info); if (status == MagickFalse) (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'", coder_info->magick); coder_info=(CoderInfo *) NULL; } GetMagickToken(q,(const char **) NULL,token); if (*token != '=') continue; GetMagickToken(q,&q,token); GetMagickToken(q,&q,token); switch (*keyword) { case 'M': case 'm': { if (LocaleCompare((char *) keyword,"magick") == 0) { coder_info->magick=ConstantString(token); break; } break; } case 'N': case 'n': { if (LocaleCompare((char *) keyword,"name") == 0) { coder_info->name=ConstantString(token); break; } break; } case 'S': case 's': { if (LocaleCompare((char *) keyword,"stealth") == 0) { coder_info->stealth=IsMagickTrue(token); break; } break; } default: break; } } token=(char *) RelinquishMagickMemory(token); return(status); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % L o a d C o d e r L i s t s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % LoadCoderLists() loads one or more coder configuration file which % provides a mapping between coder attributes and a coder name. % % The format of the LoadCoderLists coder is: % % MagickBooleanType LoadCoderLists(const char *filename, % ExceptionInfo *exception) % % A description of each parameter follows: % % o filename: the font file name. % % o exception: return any errors or warnings in this structure. % */ static MagickBooleanType LoadCoderLists(const char *filename, ExceptionInfo *exception) { const StringInfo *option; LinkedListInfo *options; MagickStatusType status; register ssize_t i; /* Load built-in coder map. */ status=MagickFalse; if (coder_list == (SplayTreeInfo *) NULL) { coder_list=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory, DestroyCoderNode); if (coder_list == (SplayTreeInfo *) NULL) { ThrowFileException(exception,ResourceLimitError, "MemoryAllocationFailed",filename); return(MagickFalse); } } for (i=0; i < (ssize_t) (sizeof(CoderMap)/sizeof(*CoderMap)); i++) { CoderInfo *coder_info; register const CoderMapInfo *p; p=CoderMap+i; coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info)); if (coder_info == (CoderInfo *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",coder_info->name); continue; } (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info)); coder_info->path=(char *) "[built-in]"; coder_info->magick=(char *) p->magick; coder_info->name=(char *) p->name; coder_info->exempt=MagickTrue; coder_info->signature=MagickSignature; status=AddValueToSplayTree(coder_list,ConstantString(coder_info->magick), coder_info); if (status == MagickFalse) (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",coder_info->name); } /* Load external coder map. */ options=GetConfigureOptions(filename,exception); option=(const StringInfo *) GetNextValueInLinkedList(options); while (option != (const StringInfo *) NULL) { status|=LoadCoderList((const char *) GetStringInfoDatum(option), GetStringInfoPath(option),0,exception); option=(const StringInfo *) GetNextValueInLinkedList(options); } options=DestroyConfigureOptions(options); return(status != 0 ? MagickTrue : MagickFalse); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e I N L I N E I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteINLINEImage() writes an image to a file in INLINE format (Base64). % % The format of the WriteINLINEImage method is: % % MagickBooleanType WriteINLINEImage(const ImageInfo *image_info, % Image *image,ExceptionInfo *exception) % % A description of each parameter follows. % % o image_info: the image info. % % o image: The image. % % o exception: return any errors or warnings in this structure. % */ static MagickBooleanType WriteINLINEImage(const ImageInfo *image_info, Image *image,ExceptionInfo *exception) { char *base64, message[MagickPathExtent]; const MagickInfo *magick_info; Image *write_image; ImageInfo *write_info; MagickBooleanType status; size_t blob_length, encode_length; unsigned char *blob; /* Convert image to base64-encoding. */ 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); write_info=CloneImageInfo(image_info); (void) SetImageInfo(write_info,1,exception); if (LocaleCompare(write_info->magick,"INLINE") == 0) (void) CopyMagickString(write_info->magick,image->magick,MagickPathExtent); magick_info=GetMagickInfo(write_info->magick,exception); if ((magick_info == (const MagickInfo *) NULL) || (GetMagickMimeType(magick_info) == (const char *) NULL)) ThrowWriterException(CorruptImageError,"ImageTypeNotSupported"); (void) CopyMagickString(image->filename,write_info->filename,MagickPathExtent); blob_length=2048; write_image=CloneImage(image,0,0,MagickTrue,exception); if (write_image == (Image *) NULL) { write_info=DestroyImageInfo(write_info); return(MagickTrue); } blob=(unsigned char *) ImageToBlob(write_info,write_image,&blob_length, exception); write_image=DestroyImage(write_image); write_info=DestroyImageInfo(write_info); if (blob == (unsigned char *) NULL) return(MagickFalse); encode_length=0; base64=Base64Encode(blob,blob_length,&encode_length); blob=(unsigned char *) RelinquishMagickMemory(blob); if (base64 == (char *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); /* Write base64-encoded image. */ status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); if (status == MagickFalse) { base64=DestroyString(base64); return(status); } (void) FormatLocaleString(message,MagickPathExtent,"data:%s;base64,", GetMagickMimeType(magick_info)); (void) WriteBlobString(image,message); (void) WriteBlobString(image,base64); base64=DestroyString(base64); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d I N L I N E I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadINLINEImage() reads base64-encoded inlines images. % % The format of the ReadINLINEImage method is: % % Image *ReadINLINEImage(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 *ReadINLINEImage(const ImageInfo *image_info, ExceptionInfo *exception) { Image *image; MagickBooleanType status; register size_t i; size_t quantum; ssize_t count; unsigned char *inline_image; /* Open image file. */ 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); if (LocaleNCompare(image_info->filename,"data:",5) == 0) return(ReadInlineImage(image_info,image_info->filename,exception)); image=AcquireImage(image_info,exception); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } quantum=MagickMin((size_t) GetBlobSize(image),MagickMaxBufferExtent); if (quantum == 0) quantum=MagickMaxBufferExtent; inline_image=(unsigned char *) AcquireQuantumMemory(quantum, sizeof(*inline_image)); count=0; for (i=0; inline_image != (unsigned char *) NULL; i+=count) { count=(ssize_t) ReadBlob(image,quantum,inline_image+i); if (count <= 0) { count=0; if (errno != EINTR) break; } if (~((size_t) i) < (quantum+1)) { inline_image=(unsigned char *) RelinquishMagickMemory(inline_image); break; } inline_image=(unsigned char *) ResizeQuantumMemory(inline_image,i+count+ quantum+1,sizeof(*inline_image)); } if (inline_image == (unsigned char *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); return((Image *) NULL); } inline_image[i+count]='\0'; image=DestroyImageList(image); image=ReadInlineImage(image_info,(char *) inline_image,exception); inline_image=(unsigned char *) RelinquishMagickMemory(inline_image); return(image); }
static Image *ReadXWDImage(const ImageInfo *image_info,ExceptionInfo *exception) { char *comment = (char *) NULL; Image *image; IndexPacket index_val; int status; long y; register IndexPacket *indexes; register long x; register PixelPacket *q; register unsigned long pixel; size_t count, length; unsigned long lsb_first; XColor *colors = (XColor *) NULL; XImage *ximage = (XImage *) NULL; XWDFileHeader header; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AllocateImage(image_info); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == False) ThrowXWDReaderException(FileOpenError,UnableToOpenFile,image); /* Read in header information. XWDFileHeader is defined in /usr/include/X11/XWDFile.h All elements are 32-bit unsigned storage but non-mask properties in XImage use 32-bit signed values. */ count=ReadBlob(image,sz_XWDheader,(char *) &header); if (count != sz_XWDheader) ThrowXWDReaderException(CorruptImageError,UnableToReadImageHeader,image); /* Ensure the header byte-order is most-significant byte first. */ lsb_first=1; if (*(char *) &lsb_first) MSBOrderLong((unsigned char *) &header,sz_XWDheader); (void) LogMagickEvent(CoderEvent,GetMagickModule(), "XWDFileHeader:\n" " header_size : %u\n" " file_version : %u\n" " pixmap_format : %s\n" " pixmap_depth : %u\n" " pixmap_width : %u\n" " pixmap_height : %u\n" " xoffset : %u\n" " byte_order : %s\n" " bitmap_unit : %u\n" " bitmap_bit_order : %s\n" " bitmap_pad : %u\n" " bits_per_pixel : %u\n" " bytes_per_line : %u\n" " visual_class : %s\n" " red_mask : 0x%06X\n" " green_mask : 0x%06X\n" " blue_mask : 0x%06X\n" " bits_per_rgb : %u\n" " colormap_entries : %u\n" " ncolors : %u\n" " window_width : %u\n" " window_height : %u\n" " window_x : %u\n" " window_y : %u\n" " window_bdrwidth : %u", (unsigned int) header.header_size, (unsigned int) header.file_version, /* (unsigned int) header.pixmap_format, */ (header.pixmap_format == XYBitmap ? "XYBitmap" : (header.pixmap_format == XYPixmap ? "XYPixmap" : (header.pixmap_format == ZPixmap ? "ZPixmap" : "?"))), (unsigned int) header.pixmap_depth, (unsigned int) header.pixmap_width, (unsigned int) header.pixmap_height, (unsigned int) header.xoffset, (header.byte_order == MSBFirst? "MSBFirst" : (header.byte_order == LSBFirst ? "LSBFirst" : "?")), (unsigned int) header.bitmap_unit, (header.bitmap_bit_order == MSBFirst? "MSBFirst" : (header.bitmap_bit_order == LSBFirst ? "LSBFirst" : "?")), (unsigned int) header.bitmap_pad, (unsigned int) header.bits_per_pixel, (unsigned int) header.bytes_per_line, (header.visual_class == StaticGray ? "StaticGray" : (header.visual_class == GrayScale ? "GrayScale" : (header.visual_class == StaticColor ? "StaticColor" : (header.visual_class == PseudoColor ? "PseudoColor" : (header.visual_class == TrueColor ? "TrueColor" : (header.visual_class == DirectColor ? "DirectColor" : "?")))))), (unsigned int) header.red_mask, (unsigned int) header.green_mask, (unsigned int) header.blue_mask, (unsigned int) header.bits_per_rgb, (unsigned int) header.colormap_entries, (unsigned int) header.ncolors, (unsigned int) header.window_width, (unsigned int) header.window_height, (unsigned int) header.window_x, (unsigned int) header.window_y, (unsigned int) header.window_bdrwidth ); /* Check to see if the dump file is in the proper format. */ if (header.file_version != XWD_FILE_VERSION) ThrowXWDReaderException(CorruptImageError,InvalidFileFormatVersion,image); if (header.header_size < sz_XWDheader) ThrowXWDReaderException(CorruptImageError,CorruptImage,image); switch (header.visual_class) { case StaticGray: case GrayScale: case StaticColor: case PseudoColor: case TrueColor: case DirectColor: break; default: { ThrowXWDReaderException(CorruptImageError,CorruptImage,image); } } switch (header.pixmap_format) { case XYBitmap: case XYPixmap: case ZPixmap: break; default: { ThrowXWDReaderException(CorruptImageError,CorruptImage,image); } } /* Retrieve comment (if any) */ length=header.header_size-sz_XWDheader; if (length > ((~0UL)/sizeof(*comment))) ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); comment=MagickAllocateMemory(char *,length+1); if (comment == (char *) NULL) ThrowXWDReaderException(ResourceLimitError,MemoryAllocationFailed,image); count=ReadBlob(image,length,comment); if (count != length) ThrowXWDReaderException(CorruptImageError,UnableToReadWindowNameFromDumpFile, image); comment[length]='\0'; (void) SetImageAttribute(image,"comment",comment); MagickFreeMemory(comment); /* Initialize the X image. */ ximage=MagickAllocateMemory(XImage *,sizeof(XImage)); if (ximage == (XImage *) NULL) ThrowXWDReaderException(ResourceLimitError,MemoryAllocationFailed,image); ximage->depth=(int) header.pixmap_depth; ximage->format=(int) header.pixmap_format; ximage->xoffset=(int) header.xoffset; ximage->data=(char *) NULL; ximage->width=(int) header.pixmap_width; ximage->height=(int) header.pixmap_height; ximage->bitmap_pad=(int) header.bitmap_pad; ximage->bytes_per_line=(int) header.bytes_per_line; ximage->byte_order=(int) header.byte_order; ximage->bitmap_unit=(int) header.bitmap_unit; ximage->bitmap_bit_order=(int) header.bitmap_bit_order; ximage->bits_per_pixel=(int) header.bits_per_pixel; ximage->red_mask=header.red_mask; ximage->green_mask=header.green_mask; ximage->blue_mask=header.blue_mask; /* XImage uses signed integers rather than unsigned. Check for overflow due to assignment. */ if (ximage->width < 0 || ximage->height < 0 || ximage->format < 0 || ximage->byte_order < 0 || ximage->bitmap_unit < 0 || ximage->bitmap_bit_order < 0 || ximage->bitmap_pad < 0 || ximage->depth < 0 || ximage->bytes_per_line < 0 || ximage->bits_per_pixel < 0) ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); /* Guard against buffer overflow in libX11. */ if (ximage->bits_per_pixel > 32 || ximage->bitmap_unit > 32) ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); status=XInitImage(ximage); if (status == False) ThrowXWDReaderException(CorruptImageError,UnrecognizedXWDHeader,image); image->columns=ximage->width; image->rows=ximage->height; if (!image_info->ping) if (CheckImagePixelLimits(image, exception) != MagickPass) ThrowXWDReaderException(ResourceLimitError,ImagePixelLimitExceeded,image); image->depth=8; if ((header.ncolors == 0U) || ((ximage->red_mask != 0) || (ximage->green_mask != 0) || (ximage->blue_mask != 0))) { image->storage_class=DirectClass; if (!image_info->ping) if ((ximage->red_mask == 0) || (ximage->green_mask == 0) || (ximage->blue_mask == 0)) ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); } else { image->storage_class=PseudoClass; } image->colors=header.ncolors; if (!image_info->ping) { /* Read colormap. */ colors=(XColor *) NULL; if (header.ncolors != 0) { XWDColor color; register long i; length=(size_t) header.ncolors; if (length > ((~0UL)/sizeof(*colors))) ThrowXWDReaderException(CorruptImageError,ImproperImageHeader,image); colors=MagickAllocateArray(XColor *,length,sizeof(XColor)); if (colors == (XColor *) NULL) ThrowXWDReaderException(ResourceLimitError,MemoryAllocationFailed, image); for (i=0; i < (long) header.ncolors; i++) { count=ReadBlob(image,sz_XWDColor,(char *) &color); if (count != sz_XWDColor) ThrowXWDReaderException(CorruptImageError, UnableToReadColormapFromDumpFile,image); colors[i].pixel=color.pixel; colors[i].red=color.red; colors[i].green=color.green; colors[i].blue=color.blue; colors[i].flags=color.flags; } /* Ensure the header byte-order is most-significant byte first. */ lsb_first=1; if (*(char *) &lsb_first) for (i=0; i < (long) header.ncolors; i++) { MSBOrderLong((unsigned char *) &colors[i].pixel, sizeof(unsigned long)); MSBOrderShort((unsigned char *) &colors[i].red, 3*sizeof(unsigned short)); } }
MagickExport MagickBooleanType GetImageChannelDistortion(Image *image, const Image *reconstruct_image,const ChannelType channel, const MetricType metric,double *distortion,ExceptionInfo *exception) { assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(reconstruct_image != (const Image *) NULL); assert(reconstruct_image->signature == MagickSignature); assert(distortion != (double *) NULL); *distortion=0.0; if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if ((reconstruct_image->columns != image->columns) || (reconstruct_image->rows != image->rows)) ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename); /* Get image distortion. */ switch (metric) { case AbsoluteErrorMetric: { *distortion=(double) GetAbsoluteError(image,reconstruct_image,exception); break; } case MeanAbsoluteErrorMetric: { *distortion=(double) GetMeanAbsoluteError(image,reconstruct_image,channel, exception); break; } case MeanErrorPerPixelMetric: { *distortion=(double) GetMeanErrorPerPixel(image,reconstruct_image,channel, exception); break; } case MeanSquaredErrorMetric: { *distortion=(double) GetMeanSquaredError(image,reconstruct_image,channel, exception); break; } case PeakAbsoluteErrorMetric: default: { *distortion=(double) GetPeakAbsoluteError(image,reconstruct_image,channel, exception); break; } case PeakSignalToNoiseRatioMetric: { *distortion=(double) GetPeakSignalToNoiseRatio(image,reconstruct_image, channel,exception); break; } case RootMeanSquaredErrorMetric: { *distortion=(double) GetRootMeanSquaredError(image,reconstruct_image, channel,exception); break; } } return(MagickTrue); }
MagickExport Image *CompareImageChannels(Image *image, const Image *reconstruct_image,const ChannelType channel, const MetricType metric,double *distortion,ExceptionInfo *exception) { Image *difference_image; long y; MagickPixelPacket composite, red, source, white; MagickStatusType difference; register const IndexPacket *indexes, *reconstruct_indexes; register const PixelPacket *p, *q; register IndexPacket *difference_indexes; register long x; register PixelPacket *r; ViewInfo *difference_view, *image_view, *reconstruct_view; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(reconstruct_image != (const Image *) NULL); assert(reconstruct_image->signature == MagickSignature); assert(distortion != (double *) NULL); *distortion=0.0; if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if ((reconstruct_image->columns != image->columns) || (reconstruct_image->rows != image->rows)) ThrowImageException(ImageError,"ImageSizeDiffers"); difference_image=CloneImage(image,image->columns,image->rows,MagickTrue, exception); if (difference_image == (Image *) NULL) return((Image *) NULL); if (SetImageStorageClass(difference_image,DirectClass) == MagickFalse) { InheritException(exception,&difference_image->exception); difference_image=DestroyImage(difference_image); return((Image *) NULL); } (void) QueryMagickColor("#f1001e",&red,exception); (void) QueryMagickColor("#ffffff",&white,exception); if (difference_image->colorspace == CMYKColorspace) { ConvertRGBToCMYK(&red); ConvertRGBToCMYK(&white); } /* Generate difference image. */ GetMagickPixelPacket(reconstruct_image,&source); GetMagickPixelPacket(difference_image,&composite); image_view=OpenCacheView(image); reconstruct_view=OpenCacheView(reconstruct_image); difference_view=OpenCacheView(difference_image); for (y=0; y < (long) image->rows; y++) { p=AcquireCacheViewPixels(image_view,0,y,image->columns,1,exception); q=AcquireCacheViewPixels(reconstruct_view,0,y,reconstruct_image->columns,1, exception); r=SetCacheView(difference_view,0,y,difference_image->columns,1); if ((p == (const PixelPacket *) NULL) || (q == (const PixelPacket *) NULL) || (r == (PixelPacket *) NULL)) break; indexes=AcquireCacheViewIndexes(image_view); reconstruct_indexes=AcquireCacheViewIndexes(reconstruct_view); difference_indexes=GetCacheViewIndexes(difference_view); for (x=0; x < (long) image->columns; x++) { difference=MagickFalse; if ((channel & RedChannel) != 0) if (p->red != q->red) difference=MagickTrue; if ((channel & GreenChannel) != 0) if (p->green != q->green) difference=MagickTrue; if ((channel & BlueChannel) != 0) if (p->blue != q->blue) difference=MagickTrue; if ((channel & OpacityChannel) != 0) if (p->opacity != q->opacity) difference=MagickTrue; if (((channel & IndexChannel) != 0) && (image->colorspace == CMYKColorspace) && (reconstruct_image->colorspace == CMYKColorspace)) if (indexes[x] != reconstruct_indexes[x]) difference=MagickTrue; SetMagickPixelPacket(reconstruct_image,q,reconstruct_indexes+x,&source); if (difference != MagickFalse) MagickPixelCompositeOver(&source,7.5*QuantumRange/10.0,&red, (MagickRealType) red.opacity,&composite); else MagickPixelCompositeOver(&source,7.5*QuantumRange/10.0,&white, (MagickRealType) white.opacity,&composite); SetPixelPacket(difference_image,&composite,r,difference_indexes+x); p++; q++; r++; } if (SyncCacheView(difference_view) == MagickFalse) break; } difference_view=CloseCacheView(difference_view); reconstruct_view=CloseCacheView(reconstruct_view); image_view=CloseCacheView(image_view); (void) GetImageChannelDistortion(image,reconstruct_image,channel,metric, distortion,exception); return(difference_image); }
static Image *ReadDPSImage(const ImageInfo *image_info,ExceptionInfo *exception) { const char *client_name; Display *display; float pixels_per_point; Image *image; int sans, status; long x, y; Pixmap pixmap; register IndexPacket *indexes; register long i; register PixelPacket *q; register unsigned long pixel; Screen *screen; XColor *colors; XImage *dps_image; XRectangle page, bits_per_pixel; XResourceInfo resource_info; XrmDatabase resource_database; XStandardColormap *map_info; XVisualInfo *visual_info; /* Open X server connection. */ 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); display=XOpenDisplay(image_info->server_name); if (display == (Display *) NULL) return((Image *) NULL); /* Set our forgiving exception handler. */ (void) XSetErrorHandler(XError); /* Open image file. */ image=AcquireImage(image_info); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) return((Image *) NULL); /* Get user defaults from X resource database. */ client_name=GetClientName(); resource_database=XGetResourceDatabase(display,client_name); XGetResourceInfo(image_info,resource_database,client_name,&resource_info); /* Allocate standard colormap. */ map_info=XAllocStandardColormap(); visual_info=(XVisualInfo *) NULL; if (map_info == (XStandardColormap *) NULL) ThrowReaderException(ResourceLimitError,"UnableToCreateStandardColormap") else { /* Initialize visual info. */ (void) CloneString(&resource_info.visual_type,"default"); visual_info=XBestVisualInfo(display,map_info,&resource_info); map_info->colormap=(Colormap) NULL; } if ((map_info == (XStandardColormap *) NULL) || (visual_info == (XVisualInfo *) NULL)) { image=DestroyImage(image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } /* Create a pixmap the appropriate size for the image. */ screen=ScreenOfDisplay(display,visual_info->screen); pixels_per_point=XDPSPixelsPerPoint(screen); if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0)) pixels_per_point=MagickMin(image->x_resolution,image->y_resolution)/ DefaultResolution; status=XDPSCreatePixmapForEPSF((DPSContext) NULL,screen, GetBlobFileHandle(image),visual_info->depth,pixels_per_point,&pixmap, &bits_per_pixel,&page); if ((status == dps_status_failure) || (status == dps_status_no_extension)) { image=DestroyImage(image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } /* Rasterize the file into the pixmap. */ status=XDPSImageFileIntoDrawable((DPSContext) NULL,screen,pixmap, GetBlobFileHandle(image),(int) bits_per_pixel.height,visual_info->depth, &page,-page.x,-page.y,pixels_per_point,MagickTrue,MagickFalse,MagickTrue, &sans); if (status != dps_status_success) { image=DestroyImage(image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } /* Initialize DPS X image. */ dps_image=XGetImage(display,pixmap,0,0,bits_per_pixel.width, bits_per_pixel.height,AllPlanes,ZPixmap); (void) XFreePixmap(display,pixmap); if (dps_image == (XImage *) NULL) { image=DestroyImage(image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } /* Get the colormap colors. */ colors=(XColor *) AcquireQuantumMemory(visual_info->colormap_size, sizeof(*colors)); if (colors == (XColor *) NULL) { image=DestroyImage(image); XDestroyImage(dps_image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } if ((visual_info->klass != DirectColor) && (visual_info->klass != TrueColor)) for (i=0; i < visual_info->colormap_size; i++) { colors[i].pixel=(unsigned long) i; colors[i].pad=0; } else { unsigned long blue, blue_bit, green, green_bit, red, red_bit; /* DirectColor or TrueColor visual. */ red=0; green=0; blue=0; red_bit=visual_info->red_mask & (~(visual_info->red_mask)+1); green_bit=visual_info->green_mask & (~(visual_info->green_mask)+1); blue_bit=visual_info->blue_mask & (~(visual_info->blue_mask)+1); for (i=0; i < visual_info->colormap_size; i++) { colors[i].pixel=red | green | blue; colors[i].pad=0; red+=red_bit; if (red > visual_info->red_mask) red=0; green+=green_bit; if (green > visual_info->green_mask) green=0; blue+=blue_bit; if (blue > visual_info->blue_mask) blue=0; } } (void) XQueryColors(display,XDefaultColormap(display,visual_info->screen), colors,visual_info->colormap_size); /* Convert X image to MIFF format. */ if ((visual_info->klass != TrueColor) && (visual_info->klass != DirectColor)) image->storage_class=PseudoClass; image->columns=(unsigned long) dps_image->width; image->rows=(unsigned long) dps_image->height; if (image_info->ping != MagickFalse) { (void) CloseBlob(image); return(GetFirstImageInList(image)); } switch (image->storage_class) { case DirectClass: default: { register unsigned long color, index; unsigned long blue_mask, blue_shift, green_mask, green_shift, red_mask, red_shift; /* Determine shift and mask for red, green, and blue. */ red_mask=visual_info->red_mask; red_shift=0; while ((red_mask != 0) && ((red_mask & 0x01) == 0)) { red_mask>>=1; red_shift++; } green_mask=visual_info->green_mask; green_shift=0; while ((green_mask != 0) && ((green_mask & 0x01) == 0)) { green_mask>>=1; green_shift++; } blue_mask=visual_info->blue_mask; blue_shift=0; while ((blue_mask != 0) && ((blue_mask & 0x01) == 0)) { blue_mask>>=1; blue_shift++; } /* Convert X image to DirectClass packets. */ if ((visual_info->colormap_size > 0) && (visual_info->klass == DirectColor)) for (y=0; y < (long) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; for (x=0; x < (long) image->columns; x++) { pixel=XGetPixel(dps_image,x,y); index=(pixel >> red_shift) & red_mask; q->red=ScaleShortToQuantum(colors[index].red); index=(pixel >> green_shift) & green_mask; q->green=ScaleShortToQuantum(colors[index].green); index=(pixel >> blue_shift) & blue_mask; q->blue=ScaleShortToQuantum(colors[index].blue); q++; } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse) break; } else for (y=0; y < (long) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; for (x=0; x < (long) image->columns; x++) { pixel=XGetPixel(dps_image,x,y); color=(pixel >> red_shift) & red_mask; color=(color*65535L)/red_mask; q->red=ScaleShortToQuantum((unsigned short) color); color=(pixel >> green_shift) & green_mask; color=(color*65535L)/green_mask; q->green=ScaleShortToQuantum((unsigned short) color); color=(pixel >> blue_shift) & blue_mask; color=(color*65535L)/blue_mask; q->blue=ScaleShortToQuantum((unsigned short) color); q++; } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse) break; } break; } case PseudoClass: { /* Create colormap. */ if (AcquireImageColormap(image,(unsigned long) visual_info->colormap_size) == MagickFalse) { image=DestroyImage(image); colors=(XColor *) RelinquishMagickMemory(colors); XDestroyImage(dps_image); XFreeResources(display,visual_info,map_info,(XPixelInfo *) NULL, (XFontStruct *) NULL,&resource_info,(XWindowInfo *) NULL); return((Image *) NULL); } for (i=0; i < (long) image->colors; i++) { image->colormap[colors[i].pixel].red=ScaleShortToQuantum(colors[i].red); image->colormap[colors[i].pixel].green= ScaleShortToQuantum(colors[i].green); image->colormap[colors[i].pixel].blue= ScaleShortToQuantum(colors[i].blue); } /* Convert X image to PseudoClass packets. */ for (y=0; y < (long) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; indexes=GetAuthenticIndexQueue(image); for (x=0; x < (long) image->columns; x++) indexes[x]=(unsigned short) XGetPixel(dps_image,x,y); if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse) break; } break; } }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % F l o o d f i l l P a i n t I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % FloodfillPaintImage() changes the color value of any pixel that matches % target and is an immediate neighbor. If the method FillToBorderMethod is % specified, the color value is changed for any neighbor pixel that does not % match the bordercolor member of image. % % By default target must match a particular pixel color exactly. However, % in many cases two colors may differ by a small amount. The fuzz member of % image defines how much tolerance is acceptable to consider two colors as % the same. For example, set fuzz to 10 and the color red at intensities of % 100 and 102 respectively are now interpreted as the same color for the % purposes of the floodfill. % % The format of the FloodfillPaintImage method is: % % MagickBooleanType FloodfillPaintImage(Image *image, % const DrawInfo *draw_info,const PixelInfo target, % const ssize_t x_offset,const ssize_t y_offset, % const MagickBooleanType invert,ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o draw_info: the draw info. % % o target: the RGB value of the target color. % % o x_offset,y_offset: the starting location of the operation. % % o invert: paint any pixel that does not match the target color. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType FloodfillPaintImage(Image *image, const DrawInfo *draw_info,const PixelInfo *target,const ssize_t x_offset, const ssize_t y_offset,const MagickBooleanType invert, ExceptionInfo *exception) { #define MaxStacksize 131072UL #define PushSegmentStack(up,left,right,delta) \ { \ if (s >= (segment_stack+MaxStacksize)) \ ThrowBinaryException(DrawError,"SegmentStackOverflow",image->filename) \ else \ { \ if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (ssize_t) image->rows)) \ { \ s->x1=(double) (left); \ s->y1=(double) (up); \ s->x2=(double) (right); \ s->y2=(double) (delta); \ s++; \ } \ } \ } CacheView *floodplane_view, *image_view; Image *floodplane_image; MagickBooleanType skip, status; PixelInfo fill_color, pixel; register SegmentInfo *s; SegmentInfo *segment_stack; ssize_t offset, start, x, x1, x2, y; /* Check boundary conditions. */ assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(draw_info != (DrawInfo *) NULL); assert(draw_info->signature == MagickSignature); if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns)) return(MagickFalse); if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows)) return(MagickFalse); if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) return(MagickFalse); if (IsGrayColorspace(image->colorspace) != MagickFalse) (void) TransformImageColorspace(image,sRGBColorspace,exception); if ((image->alpha_trait != BlendPixelTrait) && (draw_info->fill.alpha_trait == BlendPixelTrait)) (void) SetImageAlpha(image,OpaqueAlpha,exception); /* Set floodfill state. */ floodplane_image=CloneImage(image,image->columns,image->rows,MagickTrue, exception); if (floodplane_image == (Image *) NULL) return(MagickFalse); floodplane_image->alpha_trait=UndefinedPixelTrait; floodplane_image->colorspace=GRAYColorspace; (void) QueryColorCompliance("#000",AllCompliance, &floodplane_image->background_color,exception); (void) SetImageBackgroundColor(floodplane_image,exception); segment_stack=(SegmentInfo *) AcquireQuantumMemory(MaxStacksize, sizeof(*segment_stack)); if (segment_stack == (SegmentInfo *) NULL) { floodplane_image=DestroyImage(floodplane_image); ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); } /* Push initial segment on stack. */ status=MagickTrue; x=x_offset; y=y_offset; start=0; s=segment_stack; PushSegmentStack(y,x,x,1); PushSegmentStack(y+1,x,x,-1); GetPixelInfo(image,&pixel); image_view=AcquireVirtualCacheView(image,exception); floodplane_view=AcquireAuthenticCacheView(floodplane_image,exception); while (s > segment_stack) { register const Quantum *restrict p; register Quantum *restrict q; register ssize_t x; /* Pop segment off stack. */ s--; x1=(ssize_t) s->x1; x2=(ssize_t) s->x2; offset=(ssize_t) s->y2; y=(ssize_t) s->y1+offset; /* Recolor neighboring pixels. */ p=GetCacheViewVirtualPixels(image_view,0,y,(size_t) (x1+1),1,exception); q=GetCacheViewAuthenticPixels(floodplane_view,0,y,(size_t) (x1+1),1, exception); if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) break; p+=x1*GetPixelChannels(image); q+=x1*GetPixelChannels(floodplane_image); for (x=x1; x >= 0; x--) { if (GetPixelGray(floodplane_image,q) != 0) break; GetPixelInfoPixel(image,p,&pixel); if (IsFuzzyEquivalencePixelInfo(&pixel,target) == invert) break; SetPixelGray(floodplane_image,QuantumRange,q); p-=GetPixelChannels(image); q-=GetPixelChannels(floodplane_image); } if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse) break; skip=x >= x1 ? MagickTrue : MagickFalse; if (skip == MagickFalse) { start=x+1; if (start < x1) PushSegmentStack(y,start,x1-1,-offset); x=x1+1; } do { if (skip == MagickFalse) { if (x < (ssize_t) image->columns) { p=GetCacheViewVirtualPixels(image_view,x,y,image->columns-x,1, exception); q=GetCacheViewAuthenticPixels(floodplane_view,x,y,image->columns- x,1,exception); if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) break; for ( ; x < (ssize_t) image->columns; x++) { if (GetPixelGray(floodplane_image,q) != 0) break; GetPixelInfoPixel(image,p,&pixel); if (IsFuzzyEquivalencePixelInfo(&pixel,target) == invert) break; SetPixelGray(floodplane_image,QuantumRange,q); p+=GetPixelChannels(image); q+=GetPixelChannels(floodplane_image); } status=SyncCacheViewAuthenticPixels(floodplane_view,exception); if (status == MagickFalse) break; } PushSegmentStack(y,start,x-1,offset); if (x > (x2+1)) PushSegmentStack(y,x2+1,x-1,-offset); } skip=MagickFalse; x++; if (x <= x2) { p=GetCacheViewVirtualPixels(image_view,x,y,(size_t) (x2-x+1),1, exception); q=GetCacheViewAuthenticPixels(floodplane_view,x,y,(size_t) (x2-x+1),1, exception); if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) break; for ( ; x <= x2; x++) { if (GetPixelGray(floodplane_image,q) != 0) break; GetPixelInfoPixel(image,p,&pixel); if (IsFuzzyEquivalencePixelInfo(&pixel,target) != invert) break; p+=GetPixelChannels(image); q+=GetPixelChannels(floodplane_image); } } start=x; } while (x <= x2); } for (y=0; y < (ssize_t) image->rows; y++) { register const Quantum *restrict p; register Quantum *restrict q; register ssize_t x; /* Tile fill color onto floodplane. */ p=GetCacheViewVirtualPixels(floodplane_view,0,y,image->columns,1,exception); q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) break; for (x=0; x < (ssize_t) image->columns; x++) { if (GetPixelGray(floodplane_image,p) != 0) { (void) GetFillColor(draw_info,x,y,&fill_color,exception); SetPixelInfoPixel(image,&fill_color,q); } p+=GetPixelChannels(floodplane_image); q+=GetPixelChannels(image); } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) break; } floodplane_view=DestroyCacheView(floodplane_view); image_view=DestroyCacheView(image_view); segment_stack=(SegmentInfo *) RelinquishMagickMemory(segment_stack); floodplane_image=DestroyImage(floodplane_image); return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse); }
MagickExport ChannelFeatures *GetImageChannelFeatures(const Image *image, const size_t distance,ExceptionInfo *exception) { typedef struct _ChannelStatistics { DoublePixelPacket direction[4]; /* horizontal, vertical, left and right diagonals */ } ChannelStatistics; CacheView *image_view; ChannelFeatures *channel_features; ChannelStatistics **cooccurrence, correlation, *density_x, *density_xy, *density_y, entropy_x, entropy_xy, entropy_xy1, entropy_xy2, entropy_y, mean, **Q, *sum, sum_squares, variance; LongPixelPacket gray, *grays; MagickBooleanType status; register ssize_t i; size_t length; ssize_t y, z; unsigned int number_grays; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if ((image->columns < (distance+1)) || (image->rows < (distance+1))) return((ChannelFeatures *) NULL); length=CompositeChannels+1UL; channel_features=(ChannelFeatures *) AcquireQuantumMemory(length, sizeof(*channel_features)); if (channel_features == (ChannelFeatures *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); (void) ResetMagickMemory(channel_features,0,length* sizeof(*channel_features)); /* Form grays. */ grays=(LongPixelPacket *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*grays)); if (grays == (LongPixelPacket *) NULL) { channel_features=(ChannelFeatures *) RelinquishMagickMemory( channel_features); (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); return(channel_features); } for (i=0; i <= (ssize_t) MaxMap; i++) { grays[i].red=(~0U); grays[i].green=(~0U); grays[i].blue=(~0U); grays[i].opacity=(~0U); grays[i].index=(~0U); } status=MagickTrue; image_view=AcquireCacheView(image); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(status) #endif for (y=0; y < (ssize_t) image->rows; y++) { register const IndexPacket *restrict indexes; register const PixelPacket *restrict p; register ssize_t x; if (status == MagickFalse) continue; p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); if (p == (const PixelPacket *) NULL) { status=MagickFalse; continue; } indexes=GetCacheViewVirtualIndexQueue(image_view); for (x=0; x < (ssize_t) image->columns; x++) { grays[ScaleQuantumToMap(GetPixelRed(p))].red= ScaleQuantumToMap(GetPixelRed(p)); grays[ScaleQuantumToMap(GetPixelGreen(p))].green= ScaleQuantumToMap(GetPixelGreen(p)); grays[ScaleQuantumToMap(GetPixelBlue(p))].blue= ScaleQuantumToMap(GetPixelBlue(p)); if (image->colorspace == CMYKColorspace) grays[ScaleQuantumToMap(GetPixelIndex(indexes+x))].index= ScaleQuantumToMap(GetPixelIndex(indexes+x)); if (image->matte != MagickFalse) grays[ScaleQuantumToMap(GetPixelOpacity(p))].opacity= ScaleQuantumToMap(GetPixelOpacity(p)); p++; } } image_view=DestroyCacheView(image_view); if (status == MagickFalse) { grays=(LongPixelPacket *) RelinquishMagickMemory(grays); channel_features=(ChannelFeatures *) RelinquishMagickMemory( channel_features); return(channel_features); } (void) ResetMagickMemory(&gray,0,sizeof(gray)); for (i=0; i <= (ssize_t) MaxMap; i++) { if (grays[i].red != ~0U) grays[(ssize_t) gray.red++].red=grays[i].red; if (grays[i].green != ~0U) grays[(ssize_t) gray.green++].green=grays[i].green; if (grays[i].blue != ~0U) grays[(ssize_t) gray.blue++].blue=grays[i].blue; if (image->colorspace == CMYKColorspace) if (grays[i].index != ~0U) grays[(ssize_t) gray.index++].index=grays[i].index; if (image->matte != MagickFalse) if (grays[i].opacity != ~0U) grays[(ssize_t) gray.opacity++].opacity=grays[i].opacity; } /* Allocate spatial dependence matrix. */ number_grays=gray.red; if (gray.green > number_grays) number_grays=gray.green; if (gray.blue > number_grays) number_grays=gray.blue; if (image->colorspace == CMYKColorspace) if (gray.index > number_grays) number_grays=gray.index; if (image->matte != MagickFalse) if (gray.opacity > number_grays) number_grays=gray.opacity; cooccurrence=(ChannelStatistics **) AcquireQuantumMemory(number_grays, sizeof(*cooccurrence)); density_x=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), sizeof(*density_x)); density_xy=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), sizeof(*density_xy)); density_y=(ChannelStatistics *) AcquireQuantumMemory(2*(number_grays+1), sizeof(*density_y)); Q=(ChannelStatistics **) AcquireQuantumMemory(number_grays,sizeof(*Q)); sum=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(*sum)); if ((cooccurrence == (ChannelStatistics **) NULL) || (density_x == (ChannelStatistics *) NULL) || (density_xy == (ChannelStatistics *) NULL) || (density_y == (ChannelStatistics *) NULL) || (Q == (ChannelStatistics **) NULL) || (sum == (ChannelStatistics *) NULL)) { if (Q != (ChannelStatistics **) NULL) { for (i=0; i < (ssize_t) number_grays; i++) Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); Q=(ChannelStatistics **) RelinquishMagickMemory(Q); } if (sum != (ChannelStatistics *) NULL) sum=(ChannelStatistics *) RelinquishMagickMemory(sum); if (density_y != (ChannelStatistics *) NULL) density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); if (density_xy != (ChannelStatistics *) NULL) density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); if (density_x != (ChannelStatistics *) NULL) density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); if (cooccurrence != (ChannelStatistics **) NULL) { for (i=0; i < (ssize_t) number_grays; i++) cooccurrence[i]=(ChannelStatistics *) RelinquishMagickMemory(cooccurrence[i]); cooccurrence=(ChannelStatistics **) RelinquishMagickMemory( cooccurrence); } grays=(LongPixelPacket *) RelinquishMagickMemory(grays); channel_features=(ChannelFeatures *) RelinquishMagickMemory( channel_features); (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); return(channel_features); } (void) ResetMagickMemory(&correlation,0,sizeof(correlation)); (void) ResetMagickMemory(density_x,0,2*(number_grays+1)*sizeof(*density_x)); (void) ResetMagickMemory(density_xy,0,2*(number_grays+1)*sizeof(*density_xy)); (void) ResetMagickMemory(density_y,0,2*(number_grays+1)*sizeof(*density_y)); (void) ResetMagickMemory(&mean,0,sizeof(mean)); (void) ResetMagickMemory(sum,0,number_grays*sizeof(*sum)); (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares)); (void) ResetMagickMemory(density_xy,0,2*number_grays*sizeof(*density_xy)); (void) ResetMagickMemory(&entropy_x,0,sizeof(entropy_x)); (void) ResetMagickMemory(&entropy_xy,0,sizeof(entropy_xy)); (void) ResetMagickMemory(&entropy_xy1,0,sizeof(entropy_xy1)); (void) ResetMagickMemory(&entropy_xy2,0,sizeof(entropy_xy2)); (void) ResetMagickMemory(&entropy_y,0,sizeof(entropy_y)); (void) ResetMagickMemory(&variance,0,sizeof(variance)); for (i=0; i < (ssize_t) number_grays; i++) { cooccurrence[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays, sizeof(**cooccurrence)); Q[i]=(ChannelStatistics *) AcquireQuantumMemory(number_grays,sizeof(**Q)); if ((cooccurrence[i] == (ChannelStatistics *) NULL) || (Q[i] == (ChannelStatistics *) NULL)) break; (void) ResetMagickMemory(cooccurrence[i],0,number_grays* sizeof(**cooccurrence)); (void) ResetMagickMemory(Q[i],0,number_grays*sizeof(**Q)); } if (i < (ssize_t) number_grays) { for (i--; i >= 0; i--) { if (Q[i] != (ChannelStatistics *) NULL) Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); if (cooccurrence[i] != (ChannelStatistics *) NULL) cooccurrence[i]=(ChannelStatistics *) RelinquishMagickMemory(cooccurrence[i]); } Q=(ChannelStatistics **) RelinquishMagickMemory(Q); cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); sum=(ChannelStatistics *) RelinquishMagickMemory(sum); density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); grays=(LongPixelPacket *) RelinquishMagickMemory(grays); channel_features=(ChannelFeatures *) RelinquishMagickMemory( channel_features); (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); return(channel_features); } /* Initialize spatial dependence matrix. */ status=MagickTrue; image_view=AcquireCacheView(image); for (y=0; y < (ssize_t) image->rows; y++) { register const IndexPacket *restrict indexes; register const PixelPacket *restrict p; register ssize_t x; ssize_t i, offset, u, v; if (status == MagickFalse) continue; p=GetCacheViewVirtualPixels(image_view,-(ssize_t) distance,y,image->columns+ 2*distance,distance+2,exception); if (p == (const PixelPacket *) NULL) { status=MagickFalse; continue; } indexes=GetCacheViewVirtualIndexQueue(image_view); p+=distance; indexes+=distance; for (x=0; x < (ssize_t) image->columns; x++) { for (i=0; i < 4; i++) { switch (i) { case 0: default: { /* Horizontal adjacency. */ offset=(ssize_t) distance; break; } case 1: { /* Vertical adjacency. */ offset=(ssize_t) (image->columns+2*distance); break; } case 2: { /* Right diagonal adjacency. */ offset=(ssize_t) ((image->columns+2*distance)-distance); break; } case 3: { /* Left diagonal adjacency. */ offset=(ssize_t) ((image->columns+2*distance)+distance); break; } } u=0; v=0; while (grays[u].red != ScaleQuantumToMap(GetPixelRed(p))) u++; while (grays[v].red != ScaleQuantumToMap(GetPixelRed(p+offset))) v++; cooccurrence[u][v].direction[i].red++; cooccurrence[v][u].direction[i].red++; u=0; v=0; while (grays[u].green != ScaleQuantumToMap(GetPixelGreen(p))) u++; while (grays[v].green != ScaleQuantumToMap(GetPixelGreen(p+offset))) v++; cooccurrence[u][v].direction[i].green++; cooccurrence[v][u].direction[i].green++; u=0; v=0; while (grays[u].blue != ScaleQuantumToMap(GetPixelBlue(p))) u++; while (grays[v].blue != ScaleQuantumToMap((p+offset)->blue)) v++; cooccurrence[u][v].direction[i].blue++; cooccurrence[v][u].direction[i].blue++; if (image->colorspace == CMYKColorspace) { u=0; v=0; while (grays[u].index != ScaleQuantumToMap(GetPixelIndex(indexes+x))) u++; while (grays[v].index != ScaleQuantumToMap(GetPixelIndex(indexes+x+offset))) v++; cooccurrence[u][v].direction[i].index++; cooccurrence[v][u].direction[i].index++; } if (image->matte != MagickFalse) { u=0; v=0; while (grays[u].opacity != ScaleQuantumToMap(GetPixelOpacity(p))) u++; while (grays[v].opacity != ScaleQuantumToMap((p+offset)->opacity)) v++; cooccurrence[u][v].direction[i].opacity++; cooccurrence[v][u].direction[i].opacity++; } } p++; } } grays=(LongPixelPacket *) RelinquishMagickMemory(grays); image_view=DestroyCacheView(image_view); if (status == MagickFalse) { for (i=0; i < (ssize_t) number_grays; i++) cooccurrence[i]=(ChannelStatistics *) RelinquishMagickMemory(cooccurrence[i]); cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); channel_features=(ChannelFeatures *) RelinquishMagickMemory( channel_features); (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); return(channel_features); } /* Normalize spatial dependence matrix. */ for (i=0; i < 4; i++) { double normalize; register ssize_t y; switch (i) { case 0: default: { /* Horizontal adjacency. */ normalize=2.0*image->rows*(image->columns-distance); break; } case 1: { /* Vertical adjacency. */ normalize=2.0*(image->rows-distance)*image->columns; break; } case 2: { /* Right diagonal adjacency. */ normalize=2.0*(image->rows-distance)*(image->columns-distance); break; } case 3: { /* Left diagonal adjacency. */ normalize=2.0*(image->rows-distance)*(image->columns-distance); break; } } normalize=1.0/(fabs((double) normalize) <= MagickEpsilon ? 1.0 : normalize); for (y=0; y < (ssize_t) number_grays; y++) { register ssize_t x; for (x=0; x < (ssize_t) number_grays; x++) { cooccurrence[x][y].direction[i].red*=normalize; cooccurrence[x][y].direction[i].green*=normalize; cooccurrence[x][y].direction[i].blue*=normalize; if (image->colorspace == CMYKColorspace) cooccurrence[x][y].direction[i].index*=normalize; if (image->matte != MagickFalse) cooccurrence[x][y].direction[i].opacity*=normalize; } } } /* Compute texture features. */ #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(status) #endif for (i=0; i < 4; i++) { register ssize_t y; for (y=0; y < (ssize_t) number_grays; y++) { register ssize_t x; for (x=0; x < (ssize_t) number_grays; x++) { /* Angular second moment: measure of homogeneity of the image. */ channel_features[RedChannel].angular_second_moment[i]+= cooccurrence[x][y].direction[i].red* cooccurrence[x][y].direction[i].red; channel_features[GreenChannel].angular_second_moment[i]+= cooccurrence[x][y].direction[i].green* cooccurrence[x][y].direction[i].green; channel_features[BlueChannel].angular_second_moment[i]+= cooccurrence[x][y].direction[i].blue* cooccurrence[x][y].direction[i].blue; if (image->colorspace == CMYKColorspace) channel_features[BlackChannel].angular_second_moment[i]+= cooccurrence[x][y].direction[i].index* cooccurrence[x][y].direction[i].index; if (image->matte != MagickFalse) channel_features[OpacityChannel].angular_second_moment[i]+= cooccurrence[x][y].direction[i].opacity* cooccurrence[x][y].direction[i].opacity; /* Correlation: measure of linear-dependencies in the image. */ sum[y].direction[i].red+=cooccurrence[x][y].direction[i].red; sum[y].direction[i].green+=cooccurrence[x][y].direction[i].green; sum[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue; if (image->colorspace == CMYKColorspace) sum[y].direction[i].index+=cooccurrence[x][y].direction[i].index; if (image->matte != MagickFalse) sum[y].direction[i].opacity+=cooccurrence[x][y].direction[i].opacity; correlation.direction[i].red+=x*y*cooccurrence[x][y].direction[i].red; correlation.direction[i].green+=x*y* cooccurrence[x][y].direction[i].green; correlation.direction[i].blue+=x*y* cooccurrence[x][y].direction[i].blue; if (image->colorspace == CMYKColorspace) correlation.direction[i].index+=x*y* cooccurrence[x][y].direction[i].index; if (image->matte != MagickFalse) correlation.direction[i].opacity+=x*y* cooccurrence[x][y].direction[i].opacity; /* Inverse Difference Moment. */ channel_features[RedChannel].inverse_difference_moment[i]+= cooccurrence[x][y].direction[i].red/((y-x)*(y-x)+1); channel_features[GreenChannel].inverse_difference_moment[i]+= cooccurrence[x][y].direction[i].green/((y-x)*(y-x)+1); channel_features[BlueChannel].inverse_difference_moment[i]+= cooccurrence[x][y].direction[i].blue/((y-x)*(y-x)+1); if (image->colorspace == CMYKColorspace) channel_features[IndexChannel].inverse_difference_moment[i]+= cooccurrence[x][y].direction[i].index/((y-x)*(y-x)+1); if (image->matte != MagickFalse) channel_features[OpacityChannel].inverse_difference_moment[i]+= cooccurrence[x][y].direction[i].opacity/((y-x)*(y-x)+1); /* Sum average. */ density_xy[y+x+2].direction[i].red+= cooccurrence[x][y].direction[i].red; density_xy[y+x+2].direction[i].green+= cooccurrence[x][y].direction[i].green; density_xy[y+x+2].direction[i].blue+= cooccurrence[x][y].direction[i].blue; if (image->colorspace == CMYKColorspace) density_xy[y+x+2].direction[i].index+= cooccurrence[x][y].direction[i].index; if (image->matte != MagickFalse) density_xy[y+x+2].direction[i].opacity+= cooccurrence[x][y].direction[i].opacity; /* Entropy. */ channel_features[RedChannel].entropy[i]-= cooccurrence[x][y].direction[i].red* log10(cooccurrence[x][y].direction[i].red+MagickEpsilon); channel_features[GreenChannel].entropy[i]-= cooccurrence[x][y].direction[i].green* log10(cooccurrence[x][y].direction[i].green+MagickEpsilon); channel_features[BlueChannel].entropy[i]-= cooccurrence[x][y].direction[i].blue* log10(cooccurrence[x][y].direction[i].blue+MagickEpsilon); if (image->colorspace == CMYKColorspace) channel_features[IndexChannel].entropy[i]-= cooccurrence[x][y].direction[i].index* log10(cooccurrence[x][y].direction[i].index+MagickEpsilon); if (image->matte != MagickFalse) channel_features[OpacityChannel].entropy[i]-= cooccurrence[x][y].direction[i].opacity* log10(cooccurrence[x][y].direction[i].opacity+MagickEpsilon); /* Information Measures of Correlation. */ density_x[x].direction[i].red+=cooccurrence[x][y].direction[i].red; density_x[x].direction[i].green+=cooccurrence[x][y].direction[i].green; density_x[x].direction[i].blue+=cooccurrence[x][y].direction[i].blue; if (image->colorspace == CMYKColorspace) density_x[x].direction[i].index+= cooccurrence[x][y].direction[i].index; if (image->matte != MagickFalse) density_x[x].direction[i].opacity+= cooccurrence[x][y].direction[i].opacity; density_y[y].direction[i].red+=cooccurrence[x][y].direction[i].red; density_y[y].direction[i].green+=cooccurrence[x][y].direction[i].green; density_y[y].direction[i].blue+=cooccurrence[x][y].direction[i].blue; if (image->colorspace == CMYKColorspace) density_y[y].direction[i].index+= cooccurrence[x][y].direction[i].index; if (image->matte != MagickFalse) density_y[y].direction[i].opacity+= cooccurrence[x][y].direction[i].opacity; } mean.direction[i].red+=y*sum[y].direction[i].red; sum_squares.direction[i].red+=y*y*sum[y].direction[i].red; mean.direction[i].green+=y*sum[y].direction[i].green; sum_squares.direction[i].green+=y*y*sum[y].direction[i].green; mean.direction[i].blue+=y*sum[y].direction[i].blue; sum_squares.direction[i].blue+=y*y*sum[y].direction[i].blue; if (image->colorspace == CMYKColorspace) { mean.direction[i].index+=y*sum[y].direction[i].index; sum_squares.direction[i].index+=y*y*sum[y].direction[i].index; } if (image->matte != MagickFalse) { mean.direction[i].opacity+=y*sum[y].direction[i].opacity; sum_squares.direction[i].opacity+=y*y*sum[y].direction[i].opacity; } } /* Correlation: measure of linear-dependencies in the image. */ channel_features[RedChannel].correlation[i]= (correlation.direction[i].red-mean.direction[i].red* mean.direction[i].red)/(sqrt(sum_squares.direction[i].red- (mean.direction[i].red*mean.direction[i].red))*sqrt( sum_squares.direction[i].red-(mean.direction[i].red* mean.direction[i].red))); channel_features[GreenChannel].correlation[i]= (correlation.direction[i].green-mean.direction[i].green* mean.direction[i].green)/(sqrt(sum_squares.direction[i].green- (mean.direction[i].green*mean.direction[i].green))*sqrt( sum_squares.direction[i].green-(mean.direction[i].green* mean.direction[i].green))); channel_features[BlueChannel].correlation[i]= (correlation.direction[i].blue-mean.direction[i].blue* mean.direction[i].blue)/(sqrt(sum_squares.direction[i].blue- (mean.direction[i].blue*mean.direction[i].blue))*sqrt( sum_squares.direction[i].blue-(mean.direction[i].blue* mean.direction[i].blue))); if (image->colorspace == CMYKColorspace) channel_features[IndexChannel].correlation[i]= (correlation.direction[i].index-mean.direction[i].index* mean.direction[i].index)/(sqrt(sum_squares.direction[i].index- (mean.direction[i].index*mean.direction[i].index))*sqrt( sum_squares.direction[i].index-(mean.direction[i].index* mean.direction[i].index))); if (image->matte != MagickFalse) channel_features[OpacityChannel].correlation[i]= (correlation.direction[i].opacity-mean.direction[i].opacity* mean.direction[i].opacity)/(sqrt(sum_squares.direction[i].opacity- (mean.direction[i].opacity*mean.direction[i].opacity))*sqrt( sum_squares.direction[i].opacity-(mean.direction[i].opacity* mean.direction[i].opacity))); } /* Compute more texture features. */ #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(status) #endif for (i=0; i < 4; i++) { register ssize_t x; for (x=2; x < (ssize_t) (2*number_grays); x++) { /* Sum average. */ channel_features[RedChannel].sum_average[i]+= x*density_xy[x].direction[i].red; channel_features[GreenChannel].sum_average[i]+= x*density_xy[x].direction[i].green; channel_features[BlueChannel].sum_average[i]+= x*density_xy[x].direction[i].blue; if (image->colorspace == CMYKColorspace) channel_features[IndexChannel].sum_average[i]+= x*density_xy[x].direction[i].index; if (image->matte != MagickFalse) channel_features[OpacityChannel].sum_average[i]+= x*density_xy[x].direction[i].opacity; /* Sum entropy. */ channel_features[RedChannel].sum_entropy[i]-= density_xy[x].direction[i].red* log10(density_xy[x].direction[i].red+MagickEpsilon); channel_features[GreenChannel].sum_entropy[i]-= density_xy[x].direction[i].green* log10(density_xy[x].direction[i].green+MagickEpsilon); channel_features[BlueChannel].sum_entropy[i]-= density_xy[x].direction[i].blue* log10(density_xy[x].direction[i].blue+MagickEpsilon); if (image->colorspace == CMYKColorspace) channel_features[IndexChannel].sum_entropy[i]-= density_xy[x].direction[i].index* log10(density_xy[x].direction[i].index+MagickEpsilon); if (image->matte != MagickFalse) channel_features[OpacityChannel].sum_entropy[i]-= density_xy[x].direction[i].opacity* log10(density_xy[x].direction[i].opacity+MagickEpsilon); /* Sum variance. */ channel_features[RedChannel].sum_variance[i]+= (x-channel_features[RedChannel].sum_entropy[i])* (x-channel_features[RedChannel].sum_entropy[i])* density_xy[x].direction[i].red; channel_features[GreenChannel].sum_variance[i]+= (x-channel_features[GreenChannel].sum_entropy[i])* (x-channel_features[GreenChannel].sum_entropy[i])* density_xy[x].direction[i].green; channel_features[BlueChannel].sum_variance[i]+= (x-channel_features[BlueChannel].sum_entropy[i])* (x-channel_features[BlueChannel].sum_entropy[i])* density_xy[x].direction[i].blue; if (image->colorspace == CMYKColorspace) channel_features[IndexChannel].sum_variance[i]+= (x-channel_features[IndexChannel].sum_entropy[i])* (x-channel_features[IndexChannel].sum_entropy[i])* density_xy[x].direction[i].index; if (image->matte != MagickFalse) channel_features[OpacityChannel].sum_variance[i]+= (x-channel_features[OpacityChannel].sum_entropy[i])* (x-channel_features[OpacityChannel].sum_entropy[i])* density_xy[x].direction[i].opacity; } } /* Compute more texture features. */ #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(status) #endif for (i=0; i < 4; i++) { register ssize_t y; for (y=0; y < (ssize_t) number_grays; y++) { register ssize_t x; for (x=0; x < (ssize_t) number_grays; x++) { /* Sum of Squares: Variance */ variance.direction[i].red+=(y-mean.direction[i].red+1)* (y-mean.direction[i].red+1)*cooccurrence[x][y].direction[i].red; variance.direction[i].green+=(y-mean.direction[i].green+1)* (y-mean.direction[i].green+1)*cooccurrence[x][y].direction[i].green; variance.direction[i].blue+=(y-mean.direction[i].blue+1)* (y-mean.direction[i].blue+1)*cooccurrence[x][y].direction[i].blue; if (image->colorspace == CMYKColorspace) variance.direction[i].index+=(y-mean.direction[i].index+1)* (y-mean.direction[i].index+1)*cooccurrence[x][y].direction[i].index; if (image->matte != MagickFalse) variance.direction[i].opacity+=(y-mean.direction[i].opacity+1)* (y-mean.direction[i].opacity+1)* cooccurrence[x][y].direction[i].opacity; /* Sum average / Difference Variance. */ density_xy[MagickAbsoluteValue(y-x)].direction[i].red+= cooccurrence[x][y].direction[i].red; density_xy[MagickAbsoluteValue(y-x)].direction[i].green+= cooccurrence[x][y].direction[i].green; density_xy[MagickAbsoluteValue(y-x)].direction[i].blue+= cooccurrence[x][y].direction[i].blue; if (image->colorspace == CMYKColorspace) density_xy[MagickAbsoluteValue(y-x)].direction[i].index+= cooccurrence[x][y].direction[i].index; if (image->matte != MagickFalse) density_xy[MagickAbsoluteValue(y-x)].direction[i].opacity+= cooccurrence[x][y].direction[i].opacity; /* Information Measures of Correlation. */ entropy_xy.direction[i].red-=cooccurrence[x][y].direction[i].red* log10(cooccurrence[x][y].direction[i].red+MagickEpsilon); entropy_xy.direction[i].green-=cooccurrence[x][y].direction[i].green* log10(cooccurrence[x][y].direction[i].green+MagickEpsilon); entropy_xy.direction[i].blue-=cooccurrence[x][y].direction[i].blue* log10(cooccurrence[x][y].direction[i].blue+MagickEpsilon); if (image->colorspace == CMYKColorspace) entropy_xy.direction[i].index-=cooccurrence[x][y].direction[i].index* log10(cooccurrence[x][y].direction[i].index+MagickEpsilon); if (image->matte != MagickFalse) entropy_xy.direction[i].opacity-= cooccurrence[x][y].direction[i].opacity*log10( cooccurrence[x][y].direction[i].opacity+MagickEpsilon); entropy_xy1.direction[i].red-=(cooccurrence[x][y].direction[i].red* log10(density_x[x].direction[i].red*density_y[y].direction[i].red+ MagickEpsilon)); entropy_xy1.direction[i].green-=(cooccurrence[x][y].direction[i].green* log10(density_x[x].direction[i].green*density_y[y].direction[i].green+ MagickEpsilon)); entropy_xy1.direction[i].blue-=(cooccurrence[x][y].direction[i].blue* log10(density_x[x].direction[i].blue*density_y[y].direction[i].blue+ MagickEpsilon)); if (image->colorspace == CMYKColorspace) entropy_xy1.direction[i].index-=( cooccurrence[x][y].direction[i].index*log10( density_x[x].direction[i].index*density_y[y].direction[i].index+ MagickEpsilon)); if (image->matte != MagickFalse) entropy_xy1.direction[i].opacity-=( cooccurrence[x][y].direction[i].opacity*log10( density_x[x].direction[i].opacity*density_y[y].direction[i].opacity+ MagickEpsilon)); entropy_xy2.direction[i].red-=(density_x[x].direction[i].red* density_y[y].direction[i].red*log10(density_x[x].direction[i].red* density_y[y].direction[i].red+MagickEpsilon)); entropy_xy2.direction[i].green-=(density_x[x].direction[i].green* density_y[y].direction[i].green*log10(density_x[x].direction[i].green* density_y[y].direction[i].green+MagickEpsilon)); entropy_xy2.direction[i].blue-=(density_x[x].direction[i].blue* density_y[y].direction[i].blue*log10(density_x[x].direction[i].blue* density_y[y].direction[i].blue+MagickEpsilon)); if (image->colorspace == CMYKColorspace) entropy_xy2.direction[i].index-=(density_x[x].direction[i].index* density_y[y].direction[i].index*log10( density_x[x].direction[i].index*density_y[y].direction[i].index+ MagickEpsilon)); if (image->matte != MagickFalse) entropy_xy2.direction[i].opacity-=(density_x[x].direction[i].opacity* density_y[y].direction[i].opacity*log10( density_x[x].direction[i].opacity*density_y[y].direction[i].opacity+ MagickEpsilon)); } } channel_features[RedChannel].variance_sum_of_squares[i]= variance.direction[i].red; channel_features[GreenChannel].variance_sum_of_squares[i]= variance.direction[i].green; channel_features[BlueChannel].variance_sum_of_squares[i]= variance.direction[i].blue; if (image->colorspace == CMYKColorspace) channel_features[RedChannel].variance_sum_of_squares[i]= variance.direction[i].index; if (image->matte != MagickFalse) channel_features[RedChannel].variance_sum_of_squares[i]= variance.direction[i].opacity; } /* Compute more texture features. */ (void) ResetMagickMemory(&variance,0,sizeof(variance)); (void) ResetMagickMemory(&sum_squares,0,sizeof(sum_squares)); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(status) #endif for (i=0; i < 4; i++) { register ssize_t x; for (x=0; x < (ssize_t) number_grays; x++) { /* Difference variance. */ variance.direction[i].red+=density_xy[x].direction[i].red; variance.direction[i].green+=density_xy[x].direction[i].green; variance.direction[i].blue+=density_xy[x].direction[i].blue; if (image->colorspace == CMYKColorspace) variance.direction[i].index+=density_xy[x].direction[i].index; if (image->matte != MagickFalse) variance.direction[i].opacity+=density_xy[x].direction[i].opacity; sum_squares.direction[i].red+=density_xy[x].direction[i].red* density_xy[x].direction[i].red; sum_squares.direction[i].green+=density_xy[x].direction[i].green* density_xy[x].direction[i].green; sum_squares.direction[i].blue+=density_xy[x].direction[i].blue* density_xy[x].direction[i].blue; if (image->colorspace == CMYKColorspace) sum_squares.direction[i].index+=density_xy[x].direction[i].index* density_xy[x].direction[i].index; if (image->matte != MagickFalse) sum_squares.direction[i].opacity+=density_xy[x].direction[i].opacity* density_xy[x].direction[i].opacity; /* Difference entropy. */ channel_features[RedChannel].difference_entropy[i]-= density_xy[x].direction[i].red* log10(density_xy[x].direction[i].red+MagickEpsilon); channel_features[GreenChannel].difference_entropy[i]-= density_xy[x].direction[i].green* log10(density_xy[x].direction[i].green+MagickEpsilon); channel_features[BlueChannel].difference_entropy[i]-= density_xy[x].direction[i].blue* log10(density_xy[x].direction[i].blue+MagickEpsilon); if (image->colorspace == CMYKColorspace) channel_features[IndexChannel].difference_entropy[i]-= density_xy[x].direction[i].index* log10(density_xy[x].direction[i].index+MagickEpsilon); if (image->matte != MagickFalse) channel_features[OpacityChannel].difference_entropy[i]-= density_xy[x].direction[i].opacity* log10(density_xy[x].direction[i].opacity+MagickEpsilon); /* Information Measures of Correlation. */ entropy_x.direction[i].red-=(density_x[x].direction[i].red* log10(density_x[x].direction[i].red+MagickEpsilon)); entropy_x.direction[i].green-=(density_x[x].direction[i].green* log10(density_x[x].direction[i].green+MagickEpsilon)); entropy_x.direction[i].blue-=(density_x[x].direction[i].blue* log10(density_x[x].direction[i].blue+MagickEpsilon)); if (image->colorspace == CMYKColorspace) entropy_x.direction[i].index-=(density_x[x].direction[i].index* log10(density_x[x].direction[i].index+MagickEpsilon)); if (image->matte != MagickFalse) entropy_x.direction[i].opacity-=(density_x[x].direction[i].opacity* log10(density_x[x].direction[i].opacity+MagickEpsilon)); entropy_y.direction[i].red-=(density_y[x].direction[i].red* log10(density_y[x].direction[i].red+MagickEpsilon)); entropy_y.direction[i].green-=(density_y[x].direction[i].green* log10(density_y[x].direction[i].green+MagickEpsilon)); entropy_y.direction[i].blue-=(density_y[x].direction[i].blue* log10(density_y[x].direction[i].blue+MagickEpsilon)); if (image->colorspace == CMYKColorspace) entropy_y.direction[i].index-=(density_y[x].direction[i].index* log10(density_y[x].direction[i].index+MagickEpsilon)); if (image->matte != MagickFalse) entropy_y.direction[i].opacity-=(density_y[x].direction[i].opacity* log10(density_y[x].direction[i].opacity+MagickEpsilon)); } /* Difference variance. */ channel_features[RedChannel].difference_variance[i]= (((double) number_grays*number_grays*sum_squares.direction[i].red)- (variance.direction[i].red*variance.direction[i].red))/ ((double) number_grays*number_grays*number_grays*number_grays); channel_features[GreenChannel].difference_variance[i]= (((double) number_grays*number_grays*sum_squares.direction[i].green)- (variance.direction[i].green*variance.direction[i].green))/ ((double) number_grays*number_grays*number_grays*number_grays); channel_features[BlueChannel].difference_variance[i]= (((double) number_grays*number_grays*sum_squares.direction[i].blue)- (variance.direction[i].blue*variance.direction[i].blue))/ ((double) number_grays*number_grays*number_grays*number_grays); if (image->matte != MagickFalse) channel_features[OpacityChannel].difference_variance[i]= (((double) number_grays*number_grays*sum_squares.direction[i].opacity)- (variance.direction[i].opacity*variance.direction[i].opacity))/ ((double) number_grays*number_grays*number_grays*number_grays); if (image->colorspace == CMYKColorspace) channel_features[IndexChannel].difference_variance[i]= (((double) number_grays*number_grays*sum_squares.direction[i].index)- (variance.direction[i].index*variance.direction[i].index))/ ((double) number_grays*number_grays*number_grays*number_grays); /* Information Measures of Correlation. */ channel_features[RedChannel].measure_of_correlation_1[i]= (entropy_xy.direction[i].red-entropy_xy1.direction[i].red)/ (entropy_x.direction[i].red > entropy_y.direction[i].red ? entropy_x.direction[i].red : entropy_y.direction[i].red); channel_features[GreenChannel].measure_of_correlation_1[i]= (entropy_xy.direction[i].green-entropy_xy1.direction[i].green)/ (entropy_x.direction[i].green > entropy_y.direction[i].green ? entropy_x.direction[i].green : entropy_y.direction[i].green); channel_features[BlueChannel].measure_of_correlation_1[i]= (entropy_xy.direction[i].blue-entropy_xy1.direction[i].blue)/ (entropy_x.direction[i].blue > entropy_y.direction[i].blue ? entropy_x.direction[i].blue : entropy_y.direction[i].blue); if (image->colorspace == CMYKColorspace) channel_features[IndexChannel].measure_of_correlation_1[i]= (entropy_xy.direction[i].index-entropy_xy1.direction[i].index)/ (entropy_x.direction[i].index > entropy_y.direction[i].index ? entropy_x.direction[i].index : entropy_y.direction[i].index); if (image->matte != MagickFalse) channel_features[OpacityChannel].measure_of_correlation_1[i]= (entropy_xy.direction[i].opacity-entropy_xy1.direction[i].opacity)/ (entropy_x.direction[i].opacity > entropy_y.direction[i].opacity ? entropy_x.direction[i].opacity : entropy_y.direction[i].opacity); channel_features[RedChannel].measure_of_correlation_2[i]= (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].red- entropy_xy.direction[i].red))))); channel_features[GreenChannel].measure_of_correlation_2[i]= (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].green- entropy_xy.direction[i].green))))); channel_features[BlueChannel].measure_of_correlation_2[i]= (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].blue- entropy_xy.direction[i].blue))))); if (image->colorspace == CMYKColorspace) channel_features[IndexChannel].measure_of_correlation_2[i]= (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].index- entropy_xy.direction[i].index))))); if (image->matte != MagickFalse) channel_features[OpacityChannel].measure_of_correlation_2[i]= (sqrt(fabs(1.0-exp(-2.0*(entropy_xy2.direction[i].opacity- entropy_xy.direction[i].opacity))))); } /* Compute more texture features. */ #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(status) #endif for (i=0; i < 4; i++) { for (z=0; z < (ssize_t) number_grays; z++) { register ssize_t y; ChannelStatistics pixel; (void) ResetMagickMemory(&pixel,0,sizeof(pixel)); for (y=0; y < (ssize_t) number_grays; y++) { register ssize_t x; for (x=0; x < (ssize_t) number_grays; x++) { /* Contrast: amount of local variations present in an image. */ if (((y-x) == z) || ((x-y) == z)) { pixel.direction[i].red+=cooccurrence[x][y].direction[i].red; pixel.direction[i].green+=cooccurrence[x][y].direction[i].green; pixel.direction[i].blue+=cooccurrence[x][y].direction[i].blue; if (image->colorspace == CMYKColorspace) pixel.direction[i].index+=cooccurrence[x][y].direction[i].index; if (image->matte != MagickFalse) pixel.direction[i].opacity+= cooccurrence[x][y].direction[i].opacity; } /* Maximum Correlation Coefficient. */ Q[z][y].direction[i].red+=cooccurrence[z][x].direction[i].red* cooccurrence[y][x].direction[i].red/density_x[z].direction[i].red/ density_y[x].direction[i].red; Q[z][y].direction[i].green+=cooccurrence[z][x].direction[i].green* cooccurrence[y][x].direction[i].green/ density_x[z].direction[i].green/density_y[x].direction[i].red; Q[z][y].direction[i].blue+=cooccurrence[z][x].direction[i].blue* cooccurrence[y][x].direction[i].blue/density_x[z].direction[i].blue/ density_y[x].direction[i].blue; if (image->colorspace == CMYKColorspace) Q[z][y].direction[i].index+=cooccurrence[z][x].direction[i].index* cooccurrence[y][x].direction[i].index/ density_x[z].direction[i].index/density_y[x].direction[i].index; if (image->matte != MagickFalse) Q[z][y].direction[i].opacity+= cooccurrence[z][x].direction[i].opacity* cooccurrence[y][x].direction[i].opacity/ density_x[z].direction[i].opacity/ density_y[x].direction[i].opacity; } } channel_features[RedChannel].contrast[i]+=z*z*pixel.direction[i].red; channel_features[GreenChannel].contrast[i]+=z*z*pixel.direction[i].green; channel_features[BlueChannel].contrast[i]+=z*z*pixel.direction[i].blue; if (image->colorspace == CMYKColorspace) channel_features[BlackChannel].contrast[i]+=z*z* pixel.direction[i].index; if (image->matte != MagickFalse) channel_features[OpacityChannel].contrast[i]+=z*z* pixel.direction[i].opacity; } /* Maximum Correlation Coefficient. Future: return second largest eigenvalue of Q. */ channel_features[RedChannel].maximum_correlation_coefficient[i]= sqrt((double) -1.0); channel_features[GreenChannel].maximum_correlation_coefficient[i]= sqrt((double) -1.0); channel_features[BlueChannel].maximum_correlation_coefficient[i]= sqrt((double) -1.0); if (image->colorspace == CMYKColorspace) channel_features[IndexChannel].maximum_correlation_coefficient[i]= sqrt((double) -1.0); if (image->matte != MagickFalse) channel_features[OpacityChannel].maximum_correlation_coefficient[i]= sqrt((double) -1.0); } /* Relinquish resources. */ sum=(ChannelStatistics *) RelinquishMagickMemory(sum); for (i=0; i < (ssize_t) number_grays; i++) Q[i]=(ChannelStatistics *) RelinquishMagickMemory(Q[i]); Q=(ChannelStatistics **) RelinquishMagickMemory(Q); density_y=(ChannelStatistics *) RelinquishMagickMemory(density_y); density_xy=(ChannelStatistics *) RelinquishMagickMemory(density_xy); density_x=(ChannelStatistics *) RelinquishMagickMemory(density_x); for (i=0; i < (ssize_t) number_grays; i++) cooccurrence[i]=(ChannelStatistics *) RelinquishMagickMemory(cooccurrence[i]); cooccurrence=(ChannelStatistics **) RelinquishMagickMemory(cooccurrence); return(channel_features); }
MagickExport MagickBooleanType GradientImage(Image *image, const GradientType type,const SpreadMethod method, const PixelInfo *start_color,const PixelInfo *stop_color, ExceptionInfo *exception) { DrawInfo *draw_info; GradientInfo *gradient; MagickBooleanType status; register ssize_t i; /* Set gradient start-stop end points. */ assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(start_color != (const PixelInfo *) NULL); assert(stop_color != (const PixelInfo *) NULL); draw_info=AcquireDrawInfo(); gradient=(&draw_info->gradient); gradient->type=type; gradient->bounding_box.width=image->columns; gradient->bounding_box.height=image->rows; gradient->gradient_vector.x2=(double) image->columns-1.0; gradient->gradient_vector.y2=(double) image->rows-1.0; if ((type == LinearGradient) && (gradient->gradient_vector.y2 != 0.0)) gradient->gradient_vector.x2=0.0; gradient->center.x=(double) gradient->gradient_vector.x2/2.0; gradient->center.y=(double) gradient->gradient_vector.y2/2.0; gradient->radius=MagickMax(gradient->center.x,gradient->center.y); gradient->spread=method; /* Define the gradient to fill between the stops. */ gradient->number_stops=2; gradient->stops=(StopInfo *) AcquireQuantumMemory(gradient->number_stops, sizeof(*gradient->stops)); if (gradient->stops == (StopInfo *) NULL) ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); (void) ResetMagickMemory(gradient->stops,0,gradient->number_stops* sizeof(*gradient->stops)); for (i=0; i < (ssize_t) gradient->number_stops; i++) GetPixelInfo(image,&gradient->stops[i].color); gradient->stops[0].color=(*start_color); gradient->stops[0].offset=0.0; gradient->stops[1].color=(*stop_color); gradient->stops[1].offset=1.0; /* Draw a gradient on the image. */ (void) SetImageColorspace(image,start_color->colorspace,exception); status=DrawGradientImage(image,draw_info,exception); draw_info=DestroyDrawInfo(draw_info); return(status); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d D O T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadDOTImage() reads a Graphviz image file and returns it. It allocates % the memory necessary for the new Image structure and returns a pointer to % the new image. % % The format of the ReadDOTImage method is: % % Image *ReadDOTImage(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 *ReadDOTImage(const ImageInfo *image_info,ExceptionInfo *exception) { char command[MaxTextExtent]; const char *option; graph_t *graph; Image *image; ImageInfo *read_info; MagickBooleanType status; /* Open image file. */ 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); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) return((Image *) NULL); read_info=CloneImageInfo(image_info); SetImageInfoBlob(read_info,(void *) NULL,0); (void) CopyMagickString(read_info->magick,"SVG",MaxTextExtent); (void) AcquireUniqueFilename(read_info->filename); (void) FormatLocaleString(command,MaxTextExtent,"-Tsvg -o%s %s", read_info->filename,image_info->filename); #if !defined(WITH_CGRAPH) graph=agread(GetBlobFileHandle(image)); #else graph=agread(GetBlobFileHandle(image),(Agdisc_t *) NULL); #endif if (graph == (graph_t *) NULL) return ((Image *) NULL); option=GetImageOption(image_info,"dot:layout-engine"); if (option == (const char *) NULL) gvLayout(graphic_context,graph,(char *) "dot"); else gvLayout(graphic_context,graph,(char *) option); gvRenderFilename(graphic_context,graph,(char *) "svg",read_info->filename); gvFreeLayout(graphic_context,graph); agclose(graph); /* Read SVG graph. */ image=ReadImage(read_info,exception); (void) RelinquishUniqueFileResource(read_info->filename); read_info=DestroyImageInfo(read_info); if (image == (Image *) NULL) return((Image *) NULL); return(GetFirstImageInList(image)); }
MagickExport Image *OilPaintImage(const Image *image,const double radius, const double sigma,ExceptionInfo *exception) { #define NumberPaintBins 256 #define OilPaintImageTag "OilPaint/Image" CacheView *image_view, *paint_view; Image *linear_image, *paint_image; MagickBooleanType status; MagickOffsetType progress; size_t **histograms, width; ssize_t center, 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,sigma); linear_image=CloneImage(image,0,0,MagickTrue,exception); paint_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception); if ((linear_image == (Image *) NULL) || (paint_image == (Image *) NULL)) { if (linear_image != (Image *) NULL) linear_image=DestroyImage(linear_image); if (paint_image != (Image *) NULL) linear_image=DestroyImage(paint_image); return((Image *) NULL); } if (SetImageStorageClass(paint_image,DirectClass,exception) == MagickFalse) { linear_image=DestroyImage(linear_image); paint_image=DestroyImage(paint_image); return((Image *) NULL); } histograms=AcquireHistogramThreadSet(NumberPaintBins); if (histograms == (size_t **) NULL) { linear_image=DestroyImage(linear_image); paint_image=DestroyImage(paint_image); ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); } /* Oil paint image. */ status=MagickTrue; progress=0; center=(ssize_t) GetPixelChannels(linear_image)*(linear_image->columns+width)* (width/2L)+GetPixelChannels(linear_image)*(width/2L); image_view=AcquireVirtualCacheView(linear_image,exception); paint_view=AcquireAuthenticCacheView(paint_image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(progress,status) \ magick_threads(linear_image,paint_image,linear_image->rows,1) #endif for (y=0; y < (ssize_t) linear_image->rows; y++) { register const Quantum *restrict p; register Quantum *restrict q; register size_t *histogram; register ssize_t x; if (status == MagickFalse) continue; p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t) (width/2L),linear_image->columns+width,width,exception); q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1, exception); if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) { status=MagickFalse; continue; } histogram=histograms[GetOpenMPThreadId()]; for (x=0; x < (ssize_t) linear_image->columns; x++) { register ssize_t i, u; size_t count; ssize_t j, k, n, v; /* Assign most frequent color. */ k=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++) { n=(ssize_t) ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity( linear_image,p+GetPixelChannels(linear_image)*(u+k)))); histogram[n]++; if (histogram[n] > count) { j=k+u; count=histogram[n]; } } k+=(ssize_t) (linear_image->columns+width); } for (i=0; i < (ssize_t) GetPixelChannels(linear_image); i++) { PixelChannel channel=GetPixelChannelChannel(linear_image,i); PixelTrait traits=GetPixelChannelTraits(linear_image,channel); PixelTrait paint_traits=GetPixelChannelTraits(paint_image,channel); if ((traits == UndefinedPixelTrait) || (paint_traits == UndefinedPixelTrait)) continue; if (((paint_traits & CopyPixelTrait) != 0) || (GetPixelReadMask(linear_image,p) == 0)) { SetPixelChannel(paint_image,channel,p[center+i],q); continue; } SetPixelChannel(paint_image,channel,p[j*GetPixelChannels(linear_image)+ i],q); } p+=GetPixelChannels(linear_image); q+=GetPixelChannels(paint_image); } if (SyncCacheViewAuthenticPixels(paint_view,exception) == MagickFalse) status=MagickFalse; if (linear_image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_OilPaintImage) #endif proceed=SetImageProgress(linear_image,OilPaintImageTag,progress++, linear_image->rows); if (proceed == MagickFalse) status=MagickFalse; } } paint_view=DestroyCacheView(paint_view); image_view=DestroyCacheView(image_view); histograms=DestroyHistogramThreadSet(histograms); linear_image=DestroyImage(linear_image); if (status == MagickFalse) paint_image=DestroyImage(paint_image); return(paint_image); }
static ConvolveInfo *GetConvolveInfo(const Image *image,const char *name, const char *source,ExceptionInfo *exception) { char options[MaxTextExtent]; cl_int status; ConvolveInfo *convolve_info; size_t length, lengths[] = { strlen(source) }; /* Create OpenCL info. */ convolve_info=(ConvolveInfo *) AcquireAlignedMemory(1,sizeof(*convolve_info)); if (convolve_info == (ConvolveInfo *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); return((ConvolveInfo *) NULL); } (void) ResetMagickMemory(convolve_info,0,sizeof(*convolve_info)); /* Create OpenCL context. */ convolve_info->context=clCreateContextFromType((cl_context_properties *) NULL,CL_DEVICE_TYPE_GPU,ConvolveNotify,exception,&status); if ((convolve_info->context == (cl_context) NULL) || (status != CL_SUCCESS)) convolve_info->context=clCreateContextFromType((cl_context_properties *) NULL,CL_DEVICE_TYPE_CPU,ConvolveNotify,exception,&status); if ((convolve_info->context == (cl_context) NULL) || (status != CL_SUCCESS)) convolve_info->context=clCreateContextFromType((cl_context_properties *) NULL,CL_DEVICE_TYPE_DEFAULT,ConvolveNotify,exception,&status); if ((convolve_info->context == (cl_context) NULL) || (status != CL_SUCCESS)) { (void) ThrowMagickException(exception,GetMagickModule(),DelegateWarning, "failed to create OpenCL context","`%s' (%d)",image->filename,status); DestroyConvolveInfo(convolve_info); return((ConvolveInfo *) NULL); } /* Detect OpenCL devices. */ status=clGetContextInfo(convolve_info->context,CL_CONTEXT_DEVICES,0,NULL, &length); if ((status != CL_SUCCESS) || (length == 0)) { DestroyConvolveInfo(convolve_info); return((ConvolveInfo *) NULL); } convolve_info->devices=(cl_device_id *) AcquireMagickMemory(length); if (convolve_info->devices == (cl_device_id *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); DestroyConvolveInfo(convolve_info); return((ConvolveInfo *) NULL); } status=clGetContextInfo(convolve_info->context,CL_CONTEXT_DEVICES,length, convolve_info->devices,NULL); if (status != CL_SUCCESS) { DestroyConvolveInfo(convolve_info); return((ConvolveInfo *) NULL); } /* Create OpenCL command queue. */ convolve_info->command_queue=clCreateCommandQueue(convolve_info->context, convolve_info->devices[0],0,&status); if ((convolve_info->command_queue == (cl_command_queue) NULL) || (status != CL_SUCCESS)) { DestroyConvolveInfo(convolve_info); return((ConvolveInfo *) NULL); } /* Build OpenCL program. */ convolve_info->program=clCreateProgramWithSource(convolve_info->context,1, &source,lengths,&status); if ((convolve_info->program == (cl_program) NULL) || (status != CL_SUCCESS)) { DestroyConvolveInfo(convolve_info); return((ConvolveInfo *) NULL); } (void) FormatMagickString(options,MaxTextExtent,CLOptions,(double) QuantumRange,MagickEpsilon); status=clBuildProgram(convolve_info->program,1,convolve_info->devices,options, NULL,NULL); if ((convolve_info->program == (cl_program) NULL) || (status != CL_SUCCESS)) { char *log; status=clGetProgramBuildInfo(convolve_info->program, convolve_info->devices[0],CL_PROGRAM_BUILD_LOG,0,NULL,&length); log=(char *) AcquireMagickMemory(length); if (log == (char *) NULL) { DestroyConvolveInfo(convolve_info); return((ConvolveInfo *) NULL); } status=clGetProgramBuildInfo(convolve_info->program, convolve_info->devices[0],CL_PROGRAM_BUILD_LOG,length,log,&length); (void) ThrowMagickException(exception,GetMagickModule(),DelegateWarning, "failed to build OpenCL program","`%s' (%s)",image->filename,log); log=DestroyString(log); DestroyConvolveInfo(convolve_info); return((ConvolveInfo *) NULL); } /* Get a kernel object. */ convolve_info->kernel=clCreateKernel(convolve_info->program,name,&status); if ((convolve_info->kernel == (cl_kernel) NULL) || (status != CL_SUCCESS)) { DestroyConvolveInfo(convolve_info); return((ConvolveInfo *) NULL); } return(convolve_info); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % T r a n s p a r e n t P a i n t I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % TransparentPaintImage() changes the opacity value associated with any pixel % that matches color to the value defined by opacity. % % By default color must match a particular pixel color exactly. However, in % many cases two colors may differ by a small amount. Fuzz defines how much % tolerance is acceptable to consider two colors as the same. For example, % set fuzz to 10 and the color red at intensities of 100 and 102 respectively % are now interpreted as the same color. % % The format of the TransparentPaintImage method is: % % MagickBooleanType TransparentPaintImage(Image *image, % const PixelInfo *target,const Quantum opacity, % const MagickBooleanType invert,ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o target: the target color. % % o opacity: the replacement opacity value. % % o invert: paint any pixel that does not match the target color. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType TransparentPaintImage(Image *image, const PixelInfo *target,const Quantum opacity,const MagickBooleanType invert, ExceptionInfo *exception) { #define TransparentPaintImageTag "Transparent/Image" CacheView *image_view; MagickBooleanType status; MagickOffsetType progress; PixelInfo zero; ssize_t y; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(target != (PixelInfo *) NULL); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) return(MagickFalse); if (image->alpha_trait != BlendPixelTrait) (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception); /* Make image color transparent. */ status=MagickTrue; progress=0; GetPixelInfo(image,&zero); image_view=AcquireAuthenticCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(progress,status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { PixelInfo pixel; register ssize_t x; register Quantum *restrict q; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) { status=MagickFalse; continue; } pixel=zero; for (x=0; x < (ssize_t) image->columns; x++) { GetPixelInfoPixel(image,q,&pixel); if (IsFuzzyEquivalencePixelInfo(&pixel,target) != invert) SetPixelAlpha(image,opacity,q); q+=GetPixelChannels(image); } 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_TransparentPaintImage) #endif proceed=SetImageProgress(image,TransparentPaintImageTag,progress++, image->rows); if (proceed == MagickFalse) status=MagickFalse; } } image_view=DestroyCacheView(image_view); return(status); }
static MagickBooleanType ReadOneLayer(Image* image,XCFDocInfo* inDocInfo, XCFLayerInfo *outLayer ) { long i; MagickOffsetType offset; unsigned int foundPropEnd = 0; unsigned long hierarchy_offset, layer_mask_offset; /* clear the block! */ (void) ResetMagickMemory( outLayer, 0, sizeof( XCFLayerInfo ) ); /* read in the layer width, height, type and name */ outLayer->width = ReadBlobMSBLong(image); outLayer->height = ReadBlobMSBLong(image); outLayer->type = ReadBlobMSBLong(image); (void) ReadBlobStringWithLongSize(image, outLayer->name, sizeof(outLayer->name)); /* allocate the image for this layer */ outLayer->image=CloneImage(image,outLayer->width, outLayer->height,MagickTrue, &image->exception); if (outLayer->image == (Image *) NULL) return MagickFalse; /* read the layer properties! */ foundPropEnd = 0; while ( (foundPropEnd == MagickFalse) && (EOFBlob(image) == MagickFalse) ) { PropType prop_type = (PropType) ReadBlobMSBLong(image); unsigned long prop_size = ReadBlobMSBLong(image); switch (prop_type) { case PROP_END: foundPropEnd = 1; break; case PROP_ACTIVE_LAYER: outLayer->active = 1; break; case PROP_FLOATING_SELECTION: outLayer->floating_offset = ReadBlobMSBLong(image); break; case PROP_OPACITY: outLayer->opacity = ReadBlobMSBLong(image); break; case PROP_VISIBLE: outLayer->visible = ReadBlobMSBLong(image); break; case PROP_LINKED: outLayer->linked = ReadBlobMSBLong(image); break; case PROP_PRESERVE_TRANSPARENCY: outLayer->preserve_trans = ReadBlobMSBLong(image); break; case PROP_APPLY_MASK: outLayer->apply_mask = ReadBlobMSBLong(image); break; case PROP_EDIT_MASK: outLayer->edit_mask = ReadBlobMSBLong(image); break; case PROP_SHOW_MASK: outLayer->show_mask = ReadBlobMSBLong(image); break; case PROP_OFFSETS: outLayer->offset_x = (long) ReadBlobMSBLong(image); outLayer->offset_y = (long) ReadBlobMSBLong(image); break; case PROP_MODE: outLayer->mode = ReadBlobMSBLong(image); break; case PROP_TATTOO: outLayer->preserve_trans = ReadBlobMSBLong(image); break; case PROP_PARASITES: { for (i=0; i < (long) prop_size; i++ ) (void) ReadBlobByte(image); /* long base = info->cp; GimpParasite *p; while (info->cp - base < prop_size) { p = xcf_load_parasite(info); gimp_drawable_parasite_attach(GIMP_DRAWABLE(layer), p); gimp_parasite_free(p); } if (info->cp - base != prop_size) g_message ("Error detected while loading a layer's parasites"); */ } break; default: /* g_message ("unexpected/unknown layer property: %d (skipping)", prop_type); */ { int buf[16]; ssize_t amount; /* read over it... */ while ((prop_size > 0) && (EOFBlob(image) == MagickFalse)) { amount = (ssize_t) MagickMin(16, prop_size); amount = ReadBlob(image, (size_t) amount, (unsigned char *) &buf); if (!amount) ThrowBinaryException(CorruptImageError,"CorruptImage", image->filename); prop_size -= (unsigned long) MagickMin(16, (size_t) amount); } } break; } } if (foundPropEnd == MagickFalse) return(MagickFalse); /* clear the image based on the layer opacity */ outLayer->image->background_color.opacity= ScaleCharToQuantum((unsigned char) (255-outLayer->opacity)); (void) SetImageBackgroundColor(outLayer->image); /* set the compositing mode */ outLayer->image->compose = GIMPBlendModeToCompositeOperator( outLayer->mode ); if ( outLayer->visible == MagickFalse ) { /* BOGUS: should really be separate member var! */ outLayer->image->compose = NoCompositeOp; } /* read the hierarchy and layer mask offsets */ hierarchy_offset = ReadBlobMSBLong(image); layer_mask_offset = ReadBlobMSBLong(image); /* read in the hierarchy */ offset=SeekBlob(image, (MagickOffsetType) hierarchy_offset, SEEK_SET); if (offset < 0) (void) ThrowMagickException(&image->exception,GetMagickModule(), CorruptImageError,"InvalidImageHeader","`%s'",image->filename); if (load_hierarchy (image, inDocInfo, outLayer) == 0) return(MagickFalse); /* read in the layer mask */ if (layer_mask_offset != 0) { offset=SeekBlob(image, (MagickOffsetType) layer_mask_offset, SEEK_SET); #if 0 /* BOGUS: support layer masks! */ layer_mask = xcf_load_layer_mask (info, gimage); if (layer_mask == 0) goto error; /* set the offsets of the layer_mask */ GIMP_DRAWABLE (layer_mask)->offset_x = GIMP_DRAWABLE (layer)->offset_x; GIMP_DRAWABLE (layer_mask)->offset_y = GIMP_DRAWABLE (layer)->offset_y; gimp_layer_add_mask (layer, layer_mask, MagickFalse); layer->mask->apply_mask = apply_mask; layer->mask->edit_mask = edit_mask; layer->mask->show_mask = show_mask; #endif } /* attach the floating selection... */ #if 0 /* BOGUS: we may need to read this, even if we don't support it! */ if (add_floating_sel) { GimpLayer *floating_sel; floating_sel = info->floating_sel; floating_sel_attach (floating_sel, GIMP_DRAWABLE (layer)); } #endif return MagickTrue; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d E X R I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadEXRImage reads an image in the high dynamic-range (HDR) file format % developed by Industrial Light & Magic. It allocates the memory necessary % for the new Image structure and returns a pointer to the new image. % % The format of the ReadEXRImage method is: % % Image *ReadEXRImage(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 *ReadEXRImage(const ImageInfo *image_info,ExceptionInfo *exception) { const ImfHeader *hdr_info; Image *image; ImageInfo *read_info; ImfInputFile *file; ImfRgba *scanline; int max_x, max_y, min_x, min_y; ssize_t y; register ssize_t x; register PixelPacket *q; MagickBooleanType status; /* Open image. */ 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); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } read_info=CloneImageInfo(image_info); if (IsPathAccessible(read_info->filename) == MagickFalse) { (void) AcquireUniqueFilename(read_info->filename); (void) ImageToFile(image,read_info->filename,exception); } file=ImfOpenInputFile(read_info->filename); if (file == (ImfInputFile *) NULL) { ThrowFileException(exception,BlobError,"UnableToOpenBlob", ImfErrorMessage()); read_info=DestroyImageInfo(read_info); return((Image *) NULL); } hdr_info=ImfInputHeader(file); ImfHeaderDataWindow(hdr_info,&min_x,&min_y,&max_x,&max_y); image->columns=max_x-min_x+1UL; image->rows=max_y-min_y+1UL; image->matte=MagickTrue; if (image_info->ping != MagickFalse) { (void) ImfCloseInputFile(file); if (LocaleCompare(image_info->filename,read_info->filename) != 0) (void) RelinquishUniqueFileResource(read_info->filename); read_info=DestroyImageInfo(read_info); (void) CloseBlob(image); return(GetFirstImageInList(image)); } scanline=(ImfRgba *) AcquireQuantumMemory(image->columns,sizeof(*scanline)); if (scanline == (ImfRgba *) NULL) { (void) ImfCloseInputFile(file); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } for (y=0; y < (ssize_t) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; ImfInputSetFrameBuffer(file,scanline-min_x-image->columns*(min_y+y),1, image->columns); ImfInputReadPixels(file,min_y+y,min_y+y); for (x=0; x < (ssize_t) image->columns; x++) { q->red=ClampToQuantum((MagickRealType) QuantumRange*ImfHalfToFloat( scanline[x].r)); q->green=ClampToQuantum((MagickRealType) QuantumRange*ImfHalfToFloat( scanline[x].g)); q->blue=ClampToQuantum((MagickRealType) QuantumRange*ImfHalfToFloat( scanline[x].b)); q->opacity=ClampToQuantum((MagickRealType) QuantumRange-QuantumRange* ImfHalfToFloat(scanline[x].a)); q++; } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; } scanline=(ImfRgba *) RelinquishMagickMemory(scanline); (void) ImfCloseInputFile(file); if (LocaleCompare(image_info->filename,read_info->filename) != 0) (void) RelinquishUniqueFileResource(read_info->filename); read_info=DestroyImageInfo(read_info); (void) CloseBlob(image); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % G e t I m a g e T o t a l I n k D e n s i t y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetImageTotalInkDensity() returns the total ink density for a CMYK image. % Total Ink Density (TID) is determined by adding the CMYK values in the % darkest shadow area in an image. % % The format of the GetImageTotalInkDensity method is: % % double GetImageTotalInkDensity(const Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickExport double GetImageTotalInkDensity(Image *image) { CacheView *image_view; double total_ink_density; ExceptionInfo *exception; MagickBooleanType status; ssize_t y; assert(image != (Image *) NULL); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); assert(image->signature == MagickSignature); if (image->colorspace != CMYKColorspace) { (void) ThrowMagickException(&image->exception,GetMagickModule(), ImageError,"ColorSeparatedImageRequired","`%s'",image->filename); return(0.0); } status=MagickTrue; total_ink_density=0.0; exception=(&image->exception); image_view=AcquireVirtualCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) { double density; register const IndexPacket *indexes; register const PixelPacket *p; register ssize_t x; p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); if (p == (const PixelPacket *) NULL) { status=MagickFalse; continue; } indexes=GetCacheViewVirtualIndexQueue(image_view); for (x=0; x < (ssize_t) image->columns; x++) { density=(double) GetPixelRed(p)+GetPixelGreen(p)+ GetPixelBlue(p)+GetPixelIndex(indexes+x); if (density > total_ink_density) #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_GetImageTotalInkDensity) #endif { if (density > total_ink_density) total_ink_density=density; } p++; } } image_view=DestroyCacheView(image_view); if (status == MagickFalse) total_ink_density=0.0; return(total_ink_density); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e E X R I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteEXRImage() writes an image to a file the in the high dynamic-range % (HDR) file format developed by Industrial Light & Magic. % % The format of the WriteEXRImage method is: % % MagickBooleanType WriteEXRImage(const ImageInfo *image_info,Image *image) % % A description of each parameter follows. % % o image_info: the image info. % % o image: The image. % */ static MagickBooleanType WriteEXRImage(const ImageInfo *image_info,Image *image) { ImageInfo *write_info; ImfHalf half_quantum; ImfHeader *hdr_info; ImfOutputFile *file; ImfRgba *scanline; int compression; ssize_t y; MagickBooleanType status; register const PixelPacket *p; register ssize_t x; /* 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); write_info=CloneImageInfo(image_info); (void) AcquireUniqueFilename(write_info->filename); hdr_info=ImfNewHeader(); ImfHeaderSetDataWindow(hdr_info,0,0,(int) image->columns-1,(int) image->rows-1); ImfHeaderSetDisplayWindow(hdr_info,0,0,(int) image->columns-1,(int) image->rows-1); compression=IMF_NO_COMPRESSION; if (write_info->compression == ZipSCompression) compression=IMF_ZIPS_COMPRESSION; if (write_info->compression == ZipCompression) compression=IMF_ZIP_COMPRESSION; if (write_info->compression == PizCompression) compression=IMF_PIZ_COMPRESSION; if (write_info->compression == Pxr24Compression) compression=IMF_PXR24_COMPRESSION; #if defined(B44Compression) if (write_info->compression == B44Compression) compression=IMF_B44_COMPRESSION; #endif #if defined(B44ACompression) if (write_info->compression == B44ACompression) compression=IMF_B44A_COMPRESSION; #endif ImfHeaderSetCompression(hdr_info,compression); ImfHeaderSetLineOrder(hdr_info,IMF_INCREASING_Y); file=ImfOpenOutputFile(write_info->filename,hdr_info,IMF_WRITE_RGBA); ImfDeleteHeader(hdr_info); if (file == (ImfOutputFile *) NULL) { ThrowFileException(&image->exception,BlobError,"UnableToOpenBlob", ImfErrorMessage()); write_info=DestroyImageInfo(write_info); return(MagickFalse); } scanline=(ImfRgba *) AcquireQuantumMemory(image->columns,sizeof(*scanline)); if (scanline == (ImfRgba *) NULL) { (void) ImfCloseOutputFile(file); ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); } 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++) { ImfFloatToHalf(QuantumScale*p->red,&half_quantum); scanline[x].r=half_quantum; ImfFloatToHalf(QuantumScale*p->green,&half_quantum); scanline[x].g=half_quantum; ImfFloatToHalf(QuantumScale*p->blue,&half_quantum); scanline[x].b=half_quantum; if (image->matte == MagickFalse) ImfFloatToHalf(1.0,&half_quantum); else ImfFloatToHalf(1.0-QuantumScale*p->opacity,&half_quantum); scanline[x].a=half_quantum; p++; } ImfOutputSetFrameBuffer(file,scanline-(y*image->columns),1,image->columns); ImfOutputWritePixels(file,1); } (void) ImfCloseOutputFile(file); scanline=(ImfRgba *) RelinquishMagickMemory(scanline); (void) FileToImage(image,write_info->filename); (void) RelinquishUniqueFileResource(write_info->filename); write_info=DestroyImageInfo(write_info); (void) CloseBlob(image); return(MagickTrue); }
MagickExport MagickStatusType ParseMetaGeometry(const char *geometry,ssize_t *x, ssize_t *y,size_t *width,size_t *height) { GeometryInfo geometry_info; MagickStatusType flags; size_t former_height, former_width; /* Ensure the image geometry is valid. */ assert(x != (ssize_t *) NULL); assert(y != (ssize_t *) NULL); assert(width != (size_t *) NULL); assert(height != (size_t *) NULL); if ((geometry == (char *) NULL) || (*geometry == '\0')) return(NoValue); (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",geometry); /* Parse geometry using GetGeometry. */ SetGeometryInfo(&geometry_info); former_width=(*width); former_height=(*height); flags=GetGeometry(geometry,x,y,width,height); if ((flags & PercentValue) != 0) { MagickStatusType flags; PointInfo scale; /* Geometry is a percentage of the image size. */ flags=ParseGeometry(geometry,&geometry_info); scale.x=geometry_info.rho; if ((flags & RhoValue) == 0) scale.x=100.0; scale.y=geometry_info.sigma; if ((flags & SigmaValue) == 0) scale.y=scale.x; *width=(size_t) floor(scale.x*former_width/100.0+0.5); if (*width == 0) *width=1; *height=(size_t) floor(scale.y*former_height/100.0+0.5); if (*height == 0) *height=1; former_width=(*width); former_height=(*height); } if (((flags & AspectValue) == 0) && ((*width != former_width) || (*height != former_height))) { MagickRealType scale_factor; /* Respect aspect ratio of the image. */ if ((former_width == 0) || (former_height == 0)) scale_factor=1.0; else if (((flags & RhoValue) != 0) && (flags & SigmaValue) != 0) { scale_factor=(MagickRealType) *width/(MagickRealType) former_width; if ((flags & MinimumValue) == 0) { if (scale_factor > ((MagickRealType) *height/(MagickRealType) former_height)) scale_factor=(MagickRealType) *height/(MagickRealType) former_height; } else if (scale_factor < ((MagickRealType) *height/(MagickRealType) former_height)) scale_factor=(MagickRealType) *height/(MagickRealType) former_height; } else if ((flags & RhoValue) != 0) { scale_factor=(MagickRealType) *width/(MagickRealType) former_width; if (((flags & MinimumValue) != 0) && (scale_factor < ((MagickRealType) *width/(MagickRealType) former_height))) scale_factor=(MagickRealType) *width/(MagickRealType) former_height; } else { scale_factor=(MagickRealType) *height/(MagickRealType) former_height; if (((flags & MinimumValue) != 0) && (scale_factor < ((MagickRealType) *height/(MagickRealType) former_width))) scale_factor=(MagickRealType) *height/(MagickRealType) former_width; } *width=MagickMax((size_t) floor(scale_factor*former_width+0.5),1UL); *height=MagickMax((size_t) floor(scale_factor*former_height+0.5),1UL); } if ((flags & GreaterValue) != 0) { if (former_width < *width) *width=former_width; if (former_height < *height) *height=former_height; } if ((flags & LessValue) != 0) { if (former_width > *width) *width=former_width; if (former_height > *height) *height=former_height; } if ((flags & AreaValue) != 0) { MagickRealType area, distance; PointInfo scale; /* Geometry is a maximum area in pixels. */ (void) ParseGeometry(geometry,&geometry_info); area=geometry_info.rho; distance=sqrt((double) former_width*former_height); scale.x=(double) former_width/(double) (distance/sqrt((double) area)); scale.y=(double) former_height/(double) (distance/sqrt((double) area)); if ((scale.x < (double) *width) || (scale.y < (double) *height)) { *width=(size_t) (former_width/(distance/sqrt((double) area))); *height=(size_t) (former_height/(distance/sqrt((double) area))); } former_width=(*width); former_height=(*height); } return(flags); }
static Image *ReadSFWImage(const ImageInfo *image_info,ExceptionInfo *exception) { static unsigned char HuffmanTable[] = { 0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA }; FILE *file; Image *flipped_image, *image; ImageInfo *read_info; int unique_file; MagickBooleanType status; register unsigned char *header, *data; size_t extent; ssize_t count; unsigned char *buffer, *offset; /* Open image file. */ 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); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } /* Read image into a buffer. */ buffer=(unsigned char *) AcquireQuantumMemory((size_t) GetBlobSize(image), sizeof(*buffer)); if (buffer == (unsigned char *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); count=ReadBlob(image,(size_t) GetBlobSize(image),buffer); if ((count == 0) || (LocaleNCompare((char *) buffer,"SFW",3) != 0)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); (void) CloseBlob(image); image=DestroyImage(image); /* Find the start of the JFIF data */ header=SFWScan(buffer,buffer+count-1,(const unsigned char *) "\377\310\377\320",4); if (header == (unsigned char *) NULL) { buffer=(unsigned char *) RelinquishMagickMemory(buffer); ThrowReaderException(CorruptImageError,"ImproperImageHeader"); } TranslateSFWMarker(header); /* translate soi and app tags */ TranslateSFWMarker(header+2); (void) CopyMagickMemory(header+6,"JFIF\0\001\0",7); /* JFIF magic */ /* Translate remaining markers. */ offset=header+2; offset+=(offset[2] << 8)+offset[3]+2; for ( ; ; ) { TranslateSFWMarker(offset); if (offset[1] == 0xda) break; offset+=(offset[2] << 8)+offset[3]+2; } offset--; data=SFWScan(offset,buffer+count-1,(const unsigned char *) "\377\311",2); if (data == (unsigned char *) NULL) { buffer=(unsigned char *) RelinquishMagickMemory(buffer); ThrowReaderException(CorruptImageError,"ImproperImageHeader"); } TranslateSFWMarker(data++); /* translate eoi marker */ /* Write JFIF file. */ read_info=CloneImageInfo(image_info); read_info->blob=(void *) NULL; read_info->length=0; file=(FILE *) NULL; unique_file=AcquireUniqueFileResource(read_info->filename); if (unique_file != -1) file=OpenMagickStream(read_info->filename,"wb"); if ((unique_file == -1) || (file == (FILE *) NULL)) { buffer=(unsigned char *) RelinquishMagickMemory(buffer); read_info=DestroyImageInfo(read_info); (void) CopyMagickString(image->filename,read_info->filename, MaxTextExtent); ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile", image->filename); image=DestroyImageList(image); return((Image *) NULL); } extent=fwrite(header,(size_t) (offset-header+1),1,file); extent=fwrite(HuffmanTable,1,sizeof(HuffmanTable)/sizeof(*HuffmanTable),file); extent=fwrite(offset+1,(size_t) (data-offset),1,file); status=ferror(file) == -1 ? MagickFalse : MagickTrue; (void) fclose(file); buffer=(unsigned char *) RelinquishMagickMemory(buffer); if (status == MagickFalse) { char *message; (void) remove(read_info->filename); read_info=DestroyImageInfo(read_info); message=GetExceptionMessage(errno); (void) ThrowMagickException(&image->exception,GetMagickModule(), FileOpenError,"UnableToWriteFile","`%s': %s",image->filename,message); message=DestroyString(message); image=DestroyImageList(image); return((Image *) NULL); } /* Read JPEG image. */ image=ReadImage(read_info,exception); (void) RelinquishUniqueFileResource(read_info->filename); read_info=DestroyImageInfo(read_info); if (image == (Image *) NULL) return(GetFirstImageInList(image)); /* Correct image orientation. */ flipped_image=FlipImage(image,exception); if (flipped_image != (Image *) NULL) { DuplicateBlob(flipped_image,image); image=DestroyImage(image); image=flipped_image; } return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % G e t P a g e G e o m e t r y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetPageGeometry() replaces any page mneumonic with the equivalent size in % picas. % % The format of the GetPageGeometry method is: % % char *GetPageGeometry(const char *page_geometry) % % A description of each parameter follows. % % o page_geometry: Specifies a pointer to an array of characters. The % string is either a Postscript page name (e.g. A4) or a postscript page % geometry (e.g. 612x792+36+36). % */ MagickExport char *GetPageGeometry(const char *page_geometry) { static const char *PageSizes[][2]= { { "4x6", "288x432" }, { "5x7", "360x504" }, { "7x9", "504x648" }, { "8x10", "576x720" }, { "9x11", "648x792" }, { "9x12", "648x864" }, { "10x13", "720x936" }, { "10x14", "720x1008" }, { "11x17", "792x1224" }, { "a0", "2384x3370" }, { "a1", "1684x2384" }, { "a10", "73x105" }, { "a2", "1191x1684" }, { "a3", "842x1191" }, { "a4", "595x842" }, { "a4smaLL", "595x842" }, { "a5", "420x595" }, { "a6", "297x420" }, { "a7", "210x297" }, { "a8", "148x210" }, { "a9", "105x148" }, { "archa", "648x864" }, { "archb", "864x1296" }, { "archC", "1296x1728" }, { "archd", "1728x2592" }, { "arche", "2592x3456" }, { "b0", "2920x4127" }, { "b1", "2064x2920" }, { "b10", "91x127" }, { "b2", "1460x2064" }, { "b3", "1032x1460" }, { "b4", "729x1032" }, { "b5", "516x729" }, { "b6", "363x516" }, { "b7", "258x363" }, { "b8", "181x258" }, { "b9", "127x181" }, { "c0", "2599x3676" }, { "c1", "1837x2599" }, { "c2", "1298x1837" }, { "c3", "918x1296" }, { "c4", "649x918" }, { "c5", "459x649" }, { "c6", "323x459" }, { "c7", "230x323" }, { "executive", "540x720" }, { "flsa", "612x936" }, { "flse", "612x936" }, { "folio", "612x936" }, { "halfletter", "396x612" }, { "isob0", "2835x4008" }, { "isob1", "2004x2835" }, { "isob10", "88x125" }, { "isob2", "1417x2004" }, { "isob3", "1001x1417" }, { "isob4", "709x1001" }, { "isob5", "499x709" }, { "isob6", "354x499" }, { "isob7", "249x354" }, { "isob8", "176x249" }, { "isob9", "125x176" }, { "jisb0", "1030x1456" }, { "jisb1", "728x1030" }, { "jisb2", "515x728" }, { "jisb3", "364x515" }, { "jisb4", "257x364" }, { "jisb5", "182x257" }, { "jisb6", "128x182" }, { "ledger", "1224x792" }, { "legal", "612x1008" }, { "letter", "612x792" }, { "lettersmaLL", "612x792" }, { "quarto", "610x780" }, { "statement", "396x612" }, { "tabloid", "792x1224" }, { (char *) NULL, (char *) NULL } }; char *page; register ssize_t i; assert(page_geometry != (char *) NULL); (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",page_geometry); page=AcquireString(page_geometry); for (i=0; *PageSizes[i] != (char *) NULL; i++) if (LocaleNCompare(PageSizes[i][0],page,strlen(PageSizes[i][0])) == 0) { RectangleInfo geometry; MagickStatusType flags; /* Replace mneumonic with the equivalent size in dots-per-inch. */ (void) CopyMagickString(page,PageSizes[i][1],MaxTextExtent); (void) ConcatenateMagickString(page,page_geometry+ strlen(PageSizes[i][0]),MaxTextExtent); flags=GetGeometry(page,&geometry.x,&geometry.y,&geometry.width, &geometry.height); if ((flags & GreaterValue) == 0) (void) ConcatenateMagickString(page,">",MaxTextExtent); break; } return(page); }
static Image *ReadFITSImage(const ImageInfo *image_info, ExceptionInfo *exception) { typedef struct _FITSInfo { MagickBooleanType extend, simple; int bits_per_pixel, columns, rows, number_axes, number_planes; double min_data, max_data, zero, scale; EndianType endian; } FITSInfo; char *comment, keyword[9], property[MaxTextExtent], value[73]; double pixel, scale; FITSInfo fits_info; Image *image; int c; MagickBooleanType status; MagickSizeType number_pixels; register ssize_t i, x; register PixelPacket *q; ssize_t count, scene, y; /* Open image file. */ 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); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } /* Initialize image header. */ (void) ResetMagickMemory(&fits_info,0,sizeof(fits_info)); fits_info.extend=MagickFalse; fits_info.simple=MagickFalse; fits_info.bits_per_pixel=8; fits_info.columns=1; fits_info.rows=1; fits_info.rows=1; fits_info.number_planes=1; fits_info.min_data=0.0; fits_info.max_data=0.0; fits_info.zero=0.0; fits_info.scale=1.0; fits_info.endian=MSBEndian; /* Decode image header. */ for (comment=(char *) NULL; EOFBlob(image) == MagickFalse; ) { for ( ; EOFBlob(image) == MagickFalse; ) { register char *p; count=ReadBlob(image,8,(unsigned char *) keyword); if (count != 8) break; for (i=0; i < 8; i++) { if (isspace((int) ((unsigned char) keyword[i])) != 0) break; keyword[i]=tolower((int) ((unsigned char) keyword[i])); } keyword[i]='\0'; count=ReadBlob(image,72,(unsigned char *) value); value[72]='\0'; if (count != 72) break; p=value; if (*p == '=') { p+=2; while (isspace((int) ((unsigned char) *p)) != 0) p++; } if (LocaleCompare(keyword,"end") == 0) break; if (LocaleCompare(keyword,"extend") == 0) fits_info.extend=(*p == 'T') || (*p == 't') ? MagickTrue : MagickFalse; if (LocaleCompare(keyword,"simple") == 0) fits_info.simple=(*p == 'T') || (*p == 't') ? MagickTrue : MagickFalse; if (LocaleCompare(keyword,"bitpix") == 0) fits_info.bits_per_pixel=StringToLong(p); if (LocaleCompare(keyword,"naxis") == 0) fits_info.number_axes=StringToLong(p); if (LocaleCompare(keyword,"naxis1") == 0) fits_info.columns=StringToLong(p); if (LocaleCompare(keyword,"naxis2") == 0) fits_info.rows=StringToLong(p); if (LocaleCompare(keyword,"naxis3") == 0) fits_info.number_planes=StringToLong(p); if (LocaleCompare(keyword,"datamax") == 0) fits_info.max_data=StringToDouble(p,(char **) NULL); if (LocaleCompare(keyword,"datamin") == 0) fits_info.min_data=StringToDouble(p,(char **) NULL); if (LocaleCompare(keyword,"bzero") == 0) fits_info.zero=StringToDouble(p,(char **) NULL); if (LocaleCompare(keyword,"bscale") == 0) fits_info.scale=StringToDouble(p,(char **) NULL); if (LocaleCompare(keyword,"comment") == 0) { if (comment == (char *) NULL) comment=ConstantString(p); else (void) ConcatenateString(&comment,p); } if (LocaleCompare(keyword,"xendian") == 0) { if (LocaleNCompare(p,"big",3) == 0) fits_info.endian=MSBEndian; else fits_info.endian=LSBEndian; } (void) FormatLocaleString(property,MaxTextExtent,"fits:%s",keyword); (void) SetImageProperty(image,property,p); } c=0; while (((TellBlob(image) % FITSBlocksize) != 0) && (c != EOF)) c=ReadBlobByte(image); if (fits_info.extend == MagickFalse) break; number_pixels=(MagickSizeType) fits_info.columns*fits_info.rows; if ((fits_info.simple != MagickFalse) && (fits_info.number_axes >= 1) && (fits_info.number_axes <= 4) && (number_pixels != 0)) break; } /* Verify that required image information is defined. */ if (comment != (char *) NULL) { (void) SetImageProperty(image,"comment",comment); comment=DestroyString(comment); } if (EOFBlob(image) != MagickFalse) ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", image->filename); number_pixels=(MagickSizeType) fits_info.columns*fits_info.rows; if ((fits_info.simple == MagickFalse) || (fits_info.number_axes < 1) || (fits_info.number_axes > 4) || (number_pixels == 0)) ThrowReaderException(CorruptImageError,"ImageTypeNotSupported"); for (scene=0; scene < (ssize_t) fits_info.number_planes; scene++) { image->columns=(size_t) fits_info.columns; image->rows=(size_t) fits_info.rows; image->depth=(size_t) (fits_info.bits_per_pixel < 0 ? -1 : 1)* fits_info.bits_per_pixel; image->endian=fits_info.endian; image->scene=(size_t) scene; if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) if (image->scene >= (image_info->scene+image_info->number_scenes-1)) break; /* Initialize image structure. */ (void) SetImageColorspace(image,GRAYColorspace); if ((fits_info.min_data == 0.0) && (fits_info.max_data == 0.0)) { if (fits_info.zero == 0.0) (void) GetFITSPixelExtrema(image,fits_info.bits_per_pixel, &fits_info.min_data,&fits_info.max_data); else fits_info.max_data=GetFITSPixelRange((size_t) fits_info.bits_per_pixel); } else fits_info.max_data=GetFITSPixelRange((size_t) fits_info.bits_per_pixel); /* Convert FITS pixels to pixel packets. */ scale=QuantumRange/(fits_info.max_data-fits_info.min_data); for (y=(ssize_t) image->rows-1; y >= 0; y--) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { pixel=GetFITSPixel(image,fits_info.bits_per_pixel); if ((image->depth == 16) || (image->depth == 32) || (image->depth == 64)) SetFITSUnsignedPixels(1,image->depth,image->endian,(unsigned char *) &pixel); SetPixelRed(q,ClampToQuantum(scale*(fits_info.scale*(pixel- fits_info.min_data)+fits_info.zero))); SetPixelGreen(q,GetPixelRed(q)); SetPixelBlue(q,GetPixelRed(q)); q++; } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } if (EOFBlob(image) != MagickFalse) { ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", image->filename); break; } /* Proceed to next image. */ if (image_info->number_scenes != 0) if (image->scene >= (image_info->scene+image_info->number_scenes-1)) break; if (scene < (ssize_t) (fits_info.number_planes-1)) { /* Allocate next image structure. */ AcquireNextImage(image_info,image); if (GetNextImageInList(image) == (Image *) NULL) { image=DestroyImageList(image); return((Image *) NULL); } image=SyncNextImageInList(image); status=SetImageProgress(image,LoadImagesTag,TellBlob(image), GetBlobSize(image)); if (status == MagickFalse) break; } } (void) CloseBlob(image); return(GetFirstImageInList(image)); }