void ImageMesh::buildMesh2D(const std::string & filename) { int xpixels = 0, ypixels = 0; // Extract the number of pixels from the image using the file command GetPixelInfo(filename, xpixels, ypixels); // Set the maximum dimension to 1.0 while scaling the other // direction to maintain the aspect ratio. _xmax = xpixels; _ymax = ypixels; if (_scale_to_one) { Real max = std::max(_xmax, _ymax); _xmax /= max; _ymax /= max; } // Compute the number of cells in the x and y direction based on // the user's cells_per_pixel parameter. Note: we use ints here // because the GeneratedMesh params object uses ints for these... _nx = static_cast<int>(_cells_per_pixel * xpixels); _ny = static_cast<int>(_cells_per_pixel * ypixels); // Actually build the Mesh MeshTools::Generation::build_square(dynamic_cast<UnstructuredMesh&>(getMesh()), _nx, _ny, /*xmin=*/0., /*xmax=*/_xmax, /*ymin=*/0., /*ymax=*/_ymax, QUAD4); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d N U L L I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadNULLImage creates a constant image and initializes it to the % X server color as specified by the filename. It allocates the memory % necessary for the new Image structure and returns a pointer to the new % image. % % The format of the ReadNULLImage method is: % % Image *ReadNULLImage(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 *ReadNULLImage(const ImageInfo *image_info, ExceptionInfo *exception) { Image *image; PixelInfo background; register ssize_t x; register Quantum *q; ssize_t y; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info,exception); if (image->columns == 0) image->columns=1; if (image->rows == 0) image->rows=1; image->alpha_trait=BlendPixelTrait; GetPixelInfo(image,&background); background.alpha=(double) TransparentAlpha; if (image->colorspace == CMYKColorspace) ConvertRGBToCMYK(&background); for (y=0; y < (ssize_t) image->rows; y++) { q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { SetPixelInfoPixel(image,&background,q); q+=GetPixelChannels(image); } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; } return(GetFirstImageInList(image)); }
void ImageMesh::buildMesh2D(const std::string & filename) { int xpixels = 0, ypixels = 0; // Extract the number of pixels from the image using the file command GetPixelInfo(filename, xpixels, ypixels); // Set the maximum dimension to 1.0 while scaling the other // direction to maintain the aspect ratio. Real xmax = xpixels, ymax = ypixels; if (_scale_to_one) { Real max = std::max(xmax, ymax); xmax /= max; ymax /= max; } // Compute the number of cells in the x and y direction based on // the user's cells_per_pixel parameter. Note: we use ints here // because the GeneratedMesh params object uses ints for these... int nx = static_cast<int>(_cells_per_pixel * xpixels), ny = static_cast<int>(_cells_per_pixel * ypixels); // Actually build the Mesh MeshTools::Generation::build_square(dynamic_cast<UnstructuredMesh&>(getMesh()), nx, ny, /*xmin=*/0., /*xmax=*/xmax, /*ymin=*/0., /*ymax=*/ymax, QUAD4); // We've determined the correct xmax, ymax values so set them in // our InputParameters object InputParameters & pars = _app.getInputParameterWarehouse().getInputParameters(name()); pars.set<Real>("xmax") = xmax; pars.set<Real>("ymax") = ymax; // Set the number of cells in the x and y directions that we determined. pars.set<int>("nx") = nx; pars.set<int>("ny") = ny; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % A c q u i r e I m a g e C o l o r m a p % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % AcquireImageColormap() allocates an image colormap and initializes % it to a linear gray colorspace. If the image already has a colormap, % it is replaced. AcquireImageColormap() returns MagickTrue if successful, % otherwise MagickFalse if there is not enough memory. % % The format of the AcquireImageColormap method is: % % MagickBooleanType AcquireImageColormap(Image *image,const size_t colors, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o colors: the number of colors in the image colormap. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType AcquireImageColormap(Image *image, const size_t colors,ExceptionInfo *exception) { register ssize_t i; /* Allocate image colormap. */ assert(image != (Image *) NULL); assert(image->signature == MagickCoreSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); image->colors=MagickMax(colors,1); if (image->colormap == (PixelInfo *) NULL) image->colormap=(PixelInfo *) AcquireQuantumMemory(image->colors, sizeof(*image->colormap)); else image->colormap=(PixelInfo *) ResizeQuantumMemory(image->colormap, image->colors,sizeof(*image->colormap)); if (image->colormap == (PixelInfo *) NULL) { image->colors=0; image->storage_class=DirectClass; ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); } for (i=0; i < (ssize_t) image->colors; i++) { double pixel; pixel=(double) (i*(QuantumRange/MagickMax(colors-1,1))); GetPixelInfo(image,image->colormap+i); image->colormap[i].alpha_trait=BlendPixelTrait; image->colormap[i].red=pixel; image->colormap[i].green=pixel; image->colormap[i].blue=pixel; image->colormap[i].alpha=OpaqueAlpha; } return(SetImageStorageClass(image,PseudoClass,exception)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % G e t O n e C a c h e V i e w V i r t u a l P i x e l I n f o % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetOneCacheViewVirtualPixelInfo() returns a single pixel at the specified % (x,y) location. The image background color is returned if an error occurs. % If you plan to modify the pixel, use GetOneCacheViewAuthenticPixel() instead. % % The format of the GetOneCacheViewVirtualPixelInfo method is: % % MagickBooleanType GetOneCacheViewVirtualPixelInfo( % const CacheView *cache_view,const ssize_t x,const ssize_t y, % PixelInfo *pixel,ExceptionInfo *exception) % % A description of each parameter follows: % % o cache_view: the cache view. % % o x,y: These values define the offset of the pixel. % % o pixel: return a pixel at the specified (x,y) location. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType GetOneCacheViewVirtualPixelInfo( const CacheView *cache_view,const ssize_t x,const ssize_t y,PixelInfo *pixel, ExceptionInfo *exception) { const int id = GetOpenMPThreadId(); register const Quantum *magick_restrict p; assert(cache_view != (CacheView *) NULL); assert(cache_view->signature == MagickCoreSignature); assert(id < (int) cache_view->number_threads); GetPixelInfo(cache_view->image,pixel); p=GetVirtualPixelsFromNexus(cache_view->image, cache_view->virtual_pixel_method,x,y,1,1,cache_view->nexus_info[id], exception); if (p == (const Quantum *) NULL) return(MagickFalse); GetPixelInfoPixel(cache_view->image,p,pixel); return(MagickTrue); }
void ImageMesh::buildMesh3D(const std::vector<std::string> & filenames) { // If the user gave us a "stack" with 0 or 1 files in it, we can't // really create a 3D Mesh from that if (filenames.size() <= 1) mooseError("ImageMesh error: Cannot create a 3D ImageMesh from an image stack with " << filenames.size() << " images."); // For each file in the stack, process it using the 'file' command. // We want to be sure that all the images in the stack are the same // size, for example... int xpixels = 0, ypixels = 0, zpixels = filenames.size(); // Take pixel info from the first image in the stack to determine the aspect ratio GetPixelInfo(filenames[0], xpixels, ypixels); // TODO: Check that all images are the same aspect ratio and have // the same number of pixels? ImageFunction does not currently do // this... // for (unsigned i=0; i<filenames.size(); ++i) // { // // Extract the number of pixels from the image using the file command // GetPixelInfo(filenames[i], xpixels, ypixels); // // // Moose::out << "Image " << filenames[i] << " has size: " << xpixels << " by " << ypixels << std::endl; // } // Use the number of x and y pixels and the number of images to // determine the the x, y, and z dimensions of the mesh. We assume // that there is 1 pixel in the z-direction for each image in the // stack. // Set the maximum dimension to 1.0 while scaling the other // directions to maintain the aspect ratio. Real xmax = xpixels, ymax = ypixels, zmax = zpixels; if (_scale_to_one) { Real max = std::max(std::max(xmax, ymax), zmax); xmax /= max; ymax /= max; zmax /= max; } // Compute the number of cells in the x and y direction based on // the user's cells_per_pixel parameter. Note: we use ints here // because the GeneratedMesh params object uses ints for these... int nx = static_cast<int>(_cells_per_pixel * xpixels), ny = static_cast<int>(_cells_per_pixel * ypixels), nz = static_cast<int>(_cells_per_pixel * zpixels); // Actually build the Mesh MeshTools::Generation::build_cube(dynamic_cast<UnstructuredMesh&>(getMesh()), nx, ny, nz, /*xmin=*/0., /*xmax=*/xmax, /*ymin=*/0., /*ymax=*/ymax, /*zmin=*/0., /*zmax=*/zmax, HEX8); // We've determined the correct xmax, ymax, zmax values, so set them in // our InputParameters object. InputParameters & pars = _app.getInputParameterWarehouse().getInputParameters(name()); pars.set<Real>("xmax") = xmax; pars.set<Real>("ymax") = ymax; pars.set<Real>("zmax") = zmax; // Set the number of cells in the x, y, and z directions that we determined. pars.set<int>("nx") = nx; pars.set<int>("ny") = ny; pars.set<int>("nz") = nz; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e T X T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteTXTImage writes the pixel values as text numbers. % % The format of the WriteTXTImage method is: % % MagickBooleanType WriteTXTImage(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 WriteTXTImage(const ImageInfo *image_info,Image *image, ExceptionInfo *exception) { char buffer[MagickPathExtent], colorspace[MagickPathExtent], tuple[MagickPathExtent]; MagickBooleanType status; MagickOffsetType scene; PixelInfo pixel; register const Quantum *p; register ssize_t x; ssize_t y; /* Open output image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickCoreSignature); assert(image != (Image *) NULL); assert(image->signature == MagickCoreSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); status=OpenBlob(image_info,image,WriteBlobMode,exception); if (status == MagickFalse) return(status); scene=0; do { ComplianceType compliance; const char *value; (void) CopyMagickString(colorspace,CommandOptionToMnemonic( MagickColorspaceOptions,(ssize_t) image->colorspace),MagickPathExtent); LocaleLower(colorspace); image->depth=GetImageQuantumDepth(image,MagickTrue); if (image->alpha_trait != UndefinedPixelTrait) (void) ConcatenateMagickString(colorspace,"a",MagickPathExtent); compliance=NoCompliance; value=GetImageOption(image_info,"txt:compliance"); if (value != (char *) NULL) compliance=(ComplianceType) ParseCommandOption(MagickComplianceOptions, MagickFalse,value); if (LocaleCompare(image_info->magick,"SPARSE-COLOR") != 0) { size_t depth; depth=compliance == SVGCompliance ? image->depth : MAGICKCORE_QUANTUM_DEPTH; (void) FormatLocaleString(buffer,MagickPathExtent, "# ImageMagick pixel enumeration: %.20g,%.20g,%.20g,%s\n",(double) image->columns,(double) image->rows,(double) ((MagickOffsetType) GetQuantumRange(depth)),colorspace); (void) WriteBlobString(image,buffer); } GetPixelInfo(image,&pixel); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { GetPixelInfoPixel(image,p,&pixel); if (pixel.colorspace == LabColorspace) { pixel.green-=(QuantumRange+1)/2.0; pixel.blue-=(QuantumRange+1)/2.0; } if (LocaleCompare(image_info->magick,"SPARSE-COLOR") == 0) { /* Sparse-color format. */ if (GetPixelAlpha(image,p) == (Quantum) OpaqueAlpha) { GetColorTuple(&pixel,MagickFalse,tuple); (void) FormatLocaleString(buffer,MagickPathExtent, "%.20g,%.20g,",(double) x,(double) y); (void) WriteBlobString(image,buffer); (void) WriteBlobString(image,tuple); (void) WriteBlobString(image," "); } p+=GetPixelChannels(image); continue; } (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g,%.20g: ", (double) x,(double) y); (void) WriteBlobString(image,buffer); (void) CopyMagickString(tuple,"(",MagickPathExtent); if (pixel.colorspace == GRAYColorspace) ConcatenateColorComponent(&pixel,GrayPixelChannel,compliance, tuple); else { ConcatenateColorComponent(&pixel,RedPixelChannel,compliance,tuple); (void) ConcatenateMagickString(tuple,",",MagickPathExtent); ConcatenateColorComponent(&pixel,GreenPixelChannel,compliance, tuple); (void) ConcatenateMagickString(tuple,",",MagickPathExtent); ConcatenateColorComponent(&pixel,BluePixelChannel,compliance,tuple); } if (pixel.colorspace == CMYKColorspace) { (void) ConcatenateMagickString(tuple,",",MagickPathExtent); ConcatenateColorComponent(&pixel,BlackPixelChannel,compliance, tuple); } if (pixel.alpha_trait != UndefinedPixelTrait) { (void) ConcatenateMagickString(tuple,",",MagickPathExtent); ConcatenateColorComponent(&pixel,AlphaPixelChannel,compliance, tuple); } (void) ConcatenateMagickString(tuple,")",MagickPathExtent); (void) WriteBlobString(image,tuple); (void) WriteBlobString(image," "); GetColorTuple(&pixel,MagickTrue,tuple); (void) FormatLocaleString(buffer,MagickPathExtent,"%s",tuple); (void) WriteBlobString(image,buffer); (void) WriteBlobString(image," "); (void) QueryColorname(image,&pixel,SVGCompliance,tuple,exception); (void) WriteBlobString(image,tuple); (void) WriteBlobString(image,"\n"); p+=GetPixelChannels(image); } status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } if (GetNextImageInList(image) == (Image *) NULL) break; image=SyncNextImageInList(image); status=SetImageProgress(image,SaveImagesTag,scene++, GetImageListLength(image)); if (status == MagickFalse) break; } while (image_info->adjoin != MagickFalse); (void) CloseBlob(image); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d T X T I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadTXTImage() reads a text file and returns it as an image. It allocates % the memory necessary for the new Image structure and returns a pointer to % the new image. % % The format of the ReadTXTImage method is: % % Image *ReadTXTImage(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 *ReadTXTImage(const ImageInfo *image_info,ExceptionInfo *exception) { char colorspace[MagickPathExtent], text[MagickPathExtent]; Image *image; long x_offset, y_offset; PixelInfo pixel; MagickBooleanType status; QuantumAny range; register ssize_t i, x; register Quantum *q; ssize_t count, type, y; unsigned long depth, height, max_value, width; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickCoreSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickCoreSignature); image=AcquireImage(image_info,exception); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } (void) ResetMagickMemory(text,0,sizeof(text)); (void) ReadBlobString(image,text); if (LocaleNCompare((char *) text,MagickID,strlen(MagickID)) != 0) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); do { width=0; height=0; max_value=0; *colorspace='\0'; count=(ssize_t) sscanf(text+32,"%lu,%lu,%lu,%s",&width,&height,&max_value, colorspace); if ((count != 4) || (width == 0) || (height == 0) || (max_value == 0)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); image->columns=width; image->rows=height; for (depth=1; (GetQuantumRange(depth)+1) < max_value; depth++) ; image->depth=depth; status=SetImageExtent(image,image->columns,image->rows,exception); if (status == MagickFalse) return(DestroyImageList(image)); LocaleLower(colorspace); i=(ssize_t) strlen(colorspace)-1; image->alpha_trait=UndefinedPixelTrait; if ((i > 0) && (colorspace[i] == 'a')) { colorspace[i]='\0'; image->alpha_trait=BlendPixelTrait; } type=ParseCommandOption(MagickColorspaceOptions,MagickFalse,colorspace); if (type < 0) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); (void) SetImageBackgroundColor(image,exception); (void) SetImageColorspace(image,(ColorspaceType) type,exception); GetPixelInfo(image,&pixel); range=GetQuantumRange(image->depth); for (y=0; y < (ssize_t) image->rows; y++) { double alpha, black, blue, green, red; red=0.0; green=0.0; blue=0.0; black=0.0; alpha=0.0; for (x=0; x < (ssize_t) image->columns; x++) { if (ReadBlobString(image,text) == (char *) NULL) break; switch (image->colorspace) { case GRAYColorspace: { if (image->alpha_trait != UndefinedPixelTrait) { count=(ssize_t) sscanf(text,"%ld,%ld: (%lf%*[%,]%lf%*[%,]", &x_offset,&y_offset,&red,&alpha); green=red; blue=red; break; } count=(ssize_t) sscanf(text,"%ld,%ld: (%lf%*[%,]",&x_offset, &y_offset,&red); green=red; blue=red; break; } case CMYKColorspace: { if (image->alpha_trait != UndefinedPixelTrait) { count=(ssize_t) sscanf(text, "%ld,%ld: (%lf%*[%,]%lf%*[%,]%lf%*[%,]%lf%*[%,]%lf%*[%,]", &x_offset,&y_offset,&red,&green,&blue,&black,&alpha); break; } count=(ssize_t) sscanf(text, "%ld,%ld: (%lf%*[%,]%lf%*[%,]%lf%*[%,]%lf%*[%,]",&x_offset, &y_offset,&red,&green,&blue,&black); break; } default: { if (image->alpha_trait != UndefinedPixelTrait) { count=(ssize_t) sscanf(text, "%ld,%ld: (%lf%*[%,]%lf%*[%,]%lf%*[%,]%lf%*[%,]", &x_offset,&y_offset,&red,&green,&blue,&alpha); break; } count=(ssize_t) sscanf(text, "%ld,%ld: (%lf%*[%,]%lf%*[%,]%lf%*[%,]",&x_offset, &y_offset,&red,&green,&blue); break; } } if (strchr(text,'%') != (char *) NULL) { red*=0.01*range; green*=0.01*range; blue*=0.01*range; black*=0.01*range; alpha*=0.01*range; } if (image->colorspace == LabColorspace) { green+=(range+1)/2.0; blue+=(range+1)/2.0; } pixel.red=(MagickRealType) ScaleAnyToQuantum((QuantumAny) (red+0.5), range); pixel.green=(MagickRealType) ScaleAnyToQuantum((QuantumAny) (green+0.5), range); pixel.blue=(MagickRealType) ScaleAnyToQuantum((QuantumAny) (blue+0.5), range); pixel.black=(MagickRealType) ScaleAnyToQuantum((QuantumAny) (black+0.5), range); pixel.alpha=(MagickRealType) ScaleAnyToQuantum((QuantumAny) (alpha+0.5), range); q=GetAuthenticPixels(image,(ssize_t) x_offset,(ssize_t) y_offset,1,1, exception); if (q == (Quantum *) NULL) continue; SetPixelViaPixelInfo(image,&pixel,q); if (SyncAuthenticPixels(image,exception) == MagickFalse) break; } } (void) ReadBlobString(image,text); if (LocaleNCompare((char *) text,MagickID,strlen(MagickID)) == 0) { /* Allocate next image structure. */ AcquireNextImage(image_info,image,exception); 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 (LocaleNCompare((char *) text,MagickID,strlen(MagickID)) == 0); (void) CloseBlob(image); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e D E B U G I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteDEBUGImage writes the image pixel values with 20 places of precision. % % The format of the WriteDEBUGImage method is: % % MagickBooleanType WriteDEBUGImage(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 WriteDEBUGImage(const ImageInfo *image_info, Image *image,ExceptionInfo *exception) { char buffer[MaxTextExtent], colorspace[MaxTextExtent], tuple[MaxTextExtent]; ssize_t y; MagickBooleanType status; MagickOffsetType scene; PixelInfo pixel; register const Quantum *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,WriteBlobMode,exception); if (status == MagickFalse) return(status); scene=0; do { (void) CopyMagickString(colorspace,CommandOptionToMnemonic( MagickColorspaceOptions,(ssize_t) image->colorspace),MaxTextExtent); LocaleLower(colorspace); image->depth=GetImageQuantumDepth(image,MagickTrue); if (image->alpha_trait == BlendPixelTrait) (void) ConcatenateMagickString(colorspace,"a",MaxTextExtent); (void) FormatLocaleString(buffer,MaxTextExtent, "# ImageMagick pixel debugging: %.20g,%.20g,%.20g,%s\n",(double) image->columns,(double) image->rows,(double) ((MagickOffsetType) GetQuantumRange(image->depth)),colorspace); (void) WriteBlobString(image,buffer); GetPixelInfo(image,&pixel); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g,%.20g: ",(double) x,(double) y); (void) WriteBlobString(image,buffer); GetPixelInfoPixel(image,p,&pixel); (void) FormatLocaleString(tuple,MaxTextExtent,"%.20g,%.20g,%.20g ", (double) pixel.red,(double) pixel.green,(double) pixel.blue); if (pixel.colorspace == CMYKColorspace) { char black[MaxTextExtent]; (void) FormatLocaleString(black,MaxTextExtent,",%.20g ", (double) pixel.black); (void) ConcatenateMagickString(tuple,black,MaxTextExtent); } if (pixel.alpha_trait == BlendPixelTrait) { char alpha[MaxTextExtent]; (void) FormatLocaleString(alpha,MaxTextExtent,",%.20g ", (double) pixel.alpha); (void) ConcatenateMagickString(tuple,alpha,MaxTextExtent); } (void) WriteBlobString(image,tuple); (void) WriteBlobString(image,"\n"); p+=GetPixelChannels(image); } status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } if (GetNextImageInList(image) == (Image *) NULL) break; image=SyncNextImageInList(image); status=SetImageProgress(image,SaveImagesTag,scene++, GetImageListLength(image)); if (status == MagickFalse) break; } while (image_info->adjoin != MagickFalse); (void) CloseBlob(image); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e X P M I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteXPMImage() writes an image to a file in the X pixmap format. % % The format of the WriteXPMImage method is: % % MagickBooleanType WriteXPMImage(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 WriteXPMImage(const ImageInfo *image_info,Image *image, ExceptionInfo *exception) { #define MaxCixels 92 static const char Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; char buffer[MaxTextExtent], basename[MaxTextExtent], name[MaxTextExtent], symbol[MaxTextExtent]; MagickBooleanType status; PixelInfo pixel; register const Quantum *p; register ssize_t i, x; size_t characters_per_pixel; ssize_t j, k, opacity, y; /* 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); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); if (status == MagickFalse) return(status); if (IsRGBColorspace(image->colorspace) == MagickFalse) (void) TransformImageColorspace(image,sRGBColorspace,exception); opacity=(-1); if (image->matte == MagickFalse) { if ((image->storage_class == DirectClass) || (image->colors > 256)) (void) SetImageType(image,PaletteType,exception); } else { MagickRealType alpha, beta; /* Identify transparent colormap index. */ if ((image->storage_class == DirectClass) || (image->colors > 256)) (void) SetImageType(image,PaletteBilevelMatteType,exception); for (i=0; i < (ssize_t) image->colors; i++) if (image->colormap[i].alpha != OpaqueAlpha) { if (opacity < 0) { opacity=i; continue; } alpha=(MagickRealType) TransparentAlpha-(MagickRealType) image->colormap[i].alpha; beta=(MagickRealType) TransparentAlpha-(MagickRealType) image->colormap[opacity].alpha; if (alpha < beta) opacity=i; } if (opacity == -1) { (void) SetImageType(image,PaletteBilevelMatteType,exception); for (i=0; i < (ssize_t) image->colors; i++) if (image->colormap[i].alpha != OpaqueAlpha) { if (opacity < 0) { opacity=i; continue; } alpha=(Quantum) TransparentAlpha-(MagickRealType) image->colormap[i].alpha; beta=(Quantum) TransparentAlpha-(MagickRealType) image->colormap[opacity].alpha; if (alpha < beta) opacity=i; } } if (opacity >= 0) { image->colormap[opacity].red=image->transparent_color.red; image->colormap[opacity].green=image->transparent_color.green; image->colormap[opacity].blue=image->transparent_color.blue; } } /* Compute the character per pixel. */ characters_per_pixel=1; for (k=MaxCixels; (ssize_t) image->colors > k; k*=MaxCixels) characters_per_pixel++; /* XPM header. */ (void) WriteBlobString(image,"/* XPM */\n"); GetPathComponent(image->filename,BasePath,basename); if (isalnum((int) ((unsigned char) *basename)) == 0) { (void) FormatLocaleString(buffer,MaxTextExtent,"xpm_%s",basename); (void) CopyMagickString(basename,buffer,MaxTextExtent); } if (isalpha((int) ((unsigned char) basename[0])) == 0) basename[0]='_'; for (i=1; basename[i] != '\0'; i++) if (isalnum((int) ((unsigned char) basename[i])) == 0) basename[i]='_'; (void) FormatLocaleString(buffer,MaxTextExtent, "static char *%s[] = {\n",basename); (void) WriteBlobString(image,buffer); (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n"); (void) FormatLocaleString(buffer,MaxTextExtent, "\"%.20g %.20g %.20g %.20g \",\n",(double) image->columns,(double) image->rows,(double) image->colors,(double) characters_per_pixel); (void) WriteBlobString(image,buffer); GetPixelInfo(image,&pixel); for (i=0; i < (ssize_t) image->colors; i++) { /* Define XPM color. */ pixel=image->colormap[i]; pixel.colorspace=RGBColorspace; pixel.depth=8; pixel.alpha=(MagickRealType) OpaqueAlpha; (void) QueryColorname(image,&pixel,XPMCompliance,name,exception); if (i == opacity) (void) CopyMagickString(name,"None",MaxTextExtent); /* Write XPM color. */ k=i % MaxCixels; symbol[0]=Cixel[k]; for (j=1; j < (ssize_t) characters_per_pixel; j++) { k=((i-k)/MaxCixels) % MaxCixels; symbol[j]=Cixel[k]; } symbol[j]='\0'; (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s c %s\",\n",symbol, name); (void) WriteBlobString(image,buffer); } /* Define XPM pixels. */ (void) WriteBlobString(image,"/* pixels */\n"); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) break; (void) WriteBlobString(image,"\""); for (x=0; x < (ssize_t) image->columns; x++) { k=((ssize_t) GetPixelIndex(image,p) % MaxCixels); symbol[0]=Cixel[k]; for (j=1; j < (ssize_t) characters_per_pixel; j++) { k=(((int) GetPixelIndex(image,p)-k)/MaxCixels) % MaxCixels; symbol[j]=Cixel[k]; } symbol[j]='\0'; (void) CopyMagickString(buffer,symbol,MaxTextExtent); (void) WriteBlobString(image,buffer); p+=GetPixelChannels(image); } (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s\n", (y == (ssize_t) (image->rows-1) ? "" : ",")); (void) WriteBlobString(image,buffer); if (image->previous == (Image *) NULL) { status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } (void) WriteBlobString(image,"};\n"); (void) CloseBlob(image); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e P I C O N I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WritePICONImage() writes an image to a file in the Personal Icon format. % % The format of the WritePICONImage method is: % % MagickBooleanType WritePICONImage(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 WritePICONImage(const ImageInfo *image_info, Image *image,ExceptionInfo *exception) { #define ColormapExtent 155 #define GraymapExtent 95 #define PiconGeometry "48x48>" static unsigned char Colormap[]= { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x06, 0x00, 0x05, 0x00, 0xf4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x4f, 0x4f, 0x70, 0x80, 0x90, 0x7e, 0x7e, 0x7e, 0xdc, 0xdc, 0xdc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 0xff, 0x1e, 0x90, 0xff, 0x87, 0xce, 0xeb, 0xe6, 0xe6, 0xfa, 0x00, 0xff, 0xff, 0x80, 0x00, 0x80, 0xb2, 0x22, 0x22, 0x2e, 0x8b, 0x57, 0x32, 0xcd, 0x32, 0x00, 0xff, 0x00, 0x98, 0xfb, 0x98, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x63, 0x47, 0xff, 0xa5, 0x00, 0xff, 0xd7, 0x00, 0xff, 0xff, 0x00, 0xee, 0x82, 0xee, 0xa0, 0x52, 0x2d, 0xcd, 0x85, 0x3f, 0xd2, 0xb4, 0x8c, 0xf5, 0xde, 0xb3, 0xff, 0xfa, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x05, 0x18, 0x20, 0x10, 0x08, 0x03, 0x51, 0x18, 0x07, 0x92, 0x28, 0x0b, 0xd3, 0x38, 0x0f, 0x14, 0x49, 0x13, 0x55, 0x59, 0x17, 0x96, 0x69, 0x1b, 0xd7, 0x85, 0x00, 0x3b, }, Graymap[]= { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x04, 0x00, 0x04, 0x00, 0xf3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x21, 0x21, 0x21, 0x33, 0x33, 0x33, 0x45, 0x45, 0x45, 0x54, 0x54, 0x54, 0x66, 0x66, 0x66, 0x78, 0x78, 0x78, 0x87, 0x87, 0x87, 0x99, 0x99, 0x99, 0xab, 0xab, 0xab, 0xba, 0xba, 0xba, 0xcc, 0xcc, 0xcc, 0xde, 0xde, 0xde, 0xed, 0xed, 0xed, 0xff, 0xff, 0xff, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, 0x0c, 0x10, 0x04, 0x31, 0x48, 0x31, 0x07, 0x25, 0xb5, 0x58, 0x73, 0x4f, 0x04, 0x00, 0x3b, }; #define MaxCixels 92 static const char Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; char buffer[MaxTextExtent], basename[MaxTextExtent], name[MaxTextExtent], symbol[MaxTextExtent]; Image *affinity_image, *picon; ImageInfo *blob_info; MagickBooleanType status, transparent; PixelInfo pixel; QuantizeInfo *quantize_info; RectangleInfo geometry; register const Quantum *p; register ssize_t i, x; register Quantum *q; size_t characters_per_pixel, colors; ssize_t j, k, y; /* 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); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); if (status == MagickFalse) return(status); if (IsRGBColorspace(image->colorspace) == MagickFalse) (void) TransformImageColorspace(image,sRGBColorspace,exception); SetGeometry(image,&geometry); (void) ParseMetaGeometry(PiconGeometry,&geometry.x,&geometry.y, &geometry.width,&geometry.height); picon=ResizeImage(image,geometry.width,geometry.height,TriangleFilter, exception); blob_info=CloneImageInfo(image_info); (void) AcquireUniqueFilename(blob_info->filename); if ((image_info->type != TrueColorType) && (IsImageGray(image,exception) != MagickFalse)) affinity_image=BlobToImage(blob_info,Graymap,GraymapExtent,exception); else affinity_image=BlobToImage(blob_info,Colormap,ColormapExtent,exception); (void) RelinquishUniqueFileResource(blob_info->filename); blob_info=DestroyImageInfo(blob_info); if ((picon == (Image *) NULL) || (affinity_image == (Image *) NULL)) return(MagickFalse); quantize_info=AcquireQuantizeInfo(image_info); status=RemapImage(quantize_info,picon,affinity_image,exception); quantize_info=DestroyQuantizeInfo(quantize_info); affinity_image=DestroyImage(affinity_image); transparent=MagickFalse; if (picon->storage_class == PseudoClass) { (void) CompressImageColormap(picon,exception); if (picon->matte != MagickFalse) transparent=MagickTrue; } else { /* Convert DirectClass to PseudoClass picon. */ if (picon->matte != MagickFalse) { /* Map all the transparent pixels. */ for (y=0; y < (ssize_t) picon->rows; y++) { q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) picon->columns; x++) { if (GetPixelAlpha(image,q) == (Quantum) TransparentAlpha) transparent=MagickTrue; else SetPixelAlpha(picon,OpaqueAlpha,q); q+=GetPixelChannels(picon); } if (SyncAuthenticPixels(picon,exception) == MagickFalse) break; } } (void) SetImageType(picon,PaletteType,exception); } colors=picon->colors; if (transparent != MagickFalse) { colors++; picon->colormap=(PixelInfo *) ResizeQuantumMemory((void **) picon->colormap,(size_t) colors,sizeof(*picon->colormap)); if (picon->colormap == (PixelInfo *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationError"); for (y=0; y < (ssize_t) picon->rows; y++) { q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) picon->columns; x++) { if (GetPixelAlpha(image,q) == (Quantum) TransparentAlpha) SetPixelIndex(picon,picon->colors,q); q+=GetPixelChannels(picon); } if (SyncAuthenticPixels(picon,exception) == MagickFalse) break; } } /* Compute the character per pixel. */ characters_per_pixel=1; for (k=MaxCixels; (ssize_t) colors > k; k*=MaxCixels) characters_per_pixel++; /* XPM header. */ (void) WriteBlobString(image,"/* XPM */\n"); GetPathComponent(picon->filename,BasePath,basename); (void) FormatLocaleString(buffer,MaxTextExtent, "static char *%s[] = {\n",basename); (void) WriteBlobString(image,buffer); (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n"); (void) FormatLocaleString(buffer,MaxTextExtent, "\"%.20g %.20g %.20g %.20g\",\n",(double) picon->columns,(double) picon->rows,(double) colors,(double) characters_per_pixel); (void) WriteBlobString(image,buffer); GetPixelInfo(image,&pixel); for (i=0; i < (ssize_t) colors; i++) { /* Define XPM color. */ pixel=picon->colormap[i]; pixel.colorspace=RGBColorspace; pixel.depth=8; pixel.alpha=(MagickRealType) OpaqueAlpha; (void) QueryColorname(image,&pixel,XPMCompliance,name,exception); if (transparent != MagickFalse) { if (i == (ssize_t) (colors-1)) (void) CopyMagickString(name,"grey75",MaxTextExtent); } /* Write XPM color. */ k=i % MaxCixels; symbol[0]=Cixel[k]; for (j=1; j < (ssize_t) characters_per_pixel; j++) { k=((i-k)/MaxCixels) % MaxCixels; symbol[j]=Cixel[k]; } symbol[j]='\0'; (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s c %s\",\n", symbol,name); (void) WriteBlobString(image,buffer); } /* Define XPM pixels. */ (void) WriteBlobString(image,"/* pixels */\n"); for (y=0; y < (ssize_t) picon->rows; y++) { p=GetVirtualPixels(picon,0,y,picon->columns,1,exception); if (p == (const Quantum *) NULL) break; (void) WriteBlobString(image,"\""); for (x=0; x < (ssize_t) picon->columns; x++) { k=((ssize_t) GetPixelIndex(picon,p) % MaxCixels); symbol[0]=Cixel[k]; for (j=1; j < (ssize_t) characters_per_pixel; j++) { k=(((int) GetPixelIndex(picon,p)-k)/MaxCixels) % MaxCixels; symbol[j]=Cixel[k]; } symbol[j]='\0'; (void) CopyMagickString(buffer,symbol,MaxTextExtent); (void) WriteBlobString(image,buffer); p+=GetPixelChannels(image); } (void) FormatLocaleString(buffer,MaxTextExtent,"\"%s\n", y == (ssize_t) (picon->rows-1) ? "" : ","); (void) WriteBlobString(image,buffer); status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, picon->rows); if (status == MagickFalse) break; } picon=DestroyImage(picon); (void) WriteBlobString(image,"};\n"); (void) CloseBlob(image); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % 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 == MagickCoreSignature); 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 == UndefinedPixelTrait) (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); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % 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 262144UL #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; MemoryInfo *segment_info; 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 == MagickCoreSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(draw_info != (DrawInfo *) NULL); assert(draw_info->signature == MagickCoreSignature); 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) SetImageColorspace(image,sRGBColorspace,exception); if ((image->alpha_trait == UndefinedPixelTrait) && (draw_info->fill.alpha_trait != UndefinedPixelTrait)) (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_info=AcquireVirtualMemory(MaxStacksize,sizeof(*segment_stack)); if (segment_info == (MemoryInfo *) NULL) { floodplane_image=DestroyImage(floodplane_image); ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); } segment_stack=(SegmentInfo *) GetVirtualMemoryBlob(segment_info); /* 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); } status=MagickTrue; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(floodplane_image,image,floodplane_image->rows,1) #endif 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. */ if (status == MagickFalse) continue; 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)) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) image->columns; x++) { if (GetPixelGray(floodplane_image,p) != 0) { (void) GetFillColor(draw_info,x,y,&fill_color,exception); SetPixelViaPixelInfo(image,&fill_color,q); } p+=GetPixelChannels(floodplane_image); q+=GetPixelChannels(image); } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; } floodplane_view=DestroyCacheView(floodplane_view); image_view=DestroyCacheView(image_view); segment_info=RelinquishVirtualMemory(segment_info); floodplane_image=DestroyImage(floodplane_image); return(status); }
static MagickBooleanType StatisticsComponentsStatistics(const Image *image, const Image *component_image,const size_t number_objects, ExceptionInfo *exception) { CacheView *component_view, *image_view; CCObject *object; MagickBooleanType status; register ssize_t i; ssize_t y; /* Collect statistics on unique objects. */ object=(CCObject *) AcquireQuantumMemory(number_objects,sizeof(*object)); if (object == (CCObject *) NULL) { (void) ThrowMagickException(exception,GetMagickModule(), ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); return(MagickFalse); } (void) ResetMagickMemory(object,0,number_objects*sizeof(*object)); for (i=0; i < (ssize_t) number_objects; i++) { object[i].id=i; object[i].bounding_box.x=(ssize_t) component_image->columns; object[i].bounding_box.y=(ssize_t) component_image->rows; GetPixelInfo(image,&object[i].color); } status=MagickTrue; image_view=AcquireVirtualCacheView(image,exception); component_view=AcquireVirtualCacheView(component_image,exception); for (y=0; y < (ssize_t) image->rows; y++) { register const Quantum *magick_restrict p, *magick_restrict q; register ssize_t x; if (status == MagickFalse) continue; p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); q=GetCacheViewVirtualPixels(component_view,0,y,component_image->columns,1, exception); if ((p == (const Quantum *) NULL) || (q == (const Quantum *) NULL)) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) image->columns; x++) { i=(ssize_t) GetPixelIntensity(image,q); if (x < object[i].bounding_box.x) object[i].bounding_box.x=x; if (x > (ssize_t) object[i].bounding_box.width) object[i].bounding_box.width=(size_t) x; if (y < object[i].bounding_box.y) object[i].bounding_box.y=y; if (y > (ssize_t) object[i].bounding_box.height) object[i].bounding_box.height=(size_t) y; object[i].color.red+=GetPixelRed(image,p); object[i].color.green+=GetPixelGreen(image,p); object[i].color.blue+=GetPixelBlue(image,p); object[i].color.alpha+=GetPixelAlpha(image,p); object[i].color.black+=GetPixelBlack(image,p); object[i].centroid.x+=x; object[i].centroid.y+=y; object[i].area++; p+=GetPixelChannels(image); q+=GetPixelChannels(component_image); } } for (i=0; i < (ssize_t) number_objects; i++) { object[i].bounding_box.width-=(object[i].bounding_box.x-1); object[i].bounding_box.height-=(object[i].bounding_box.y-1); object[i].color.red=object[i].color.red/object[i].area; object[i].color.green=object[i].color.green/object[i].area; object[i].color.blue=object[i].color.blue/object[i].area; object[i].color.alpha=object[i].color.alpha/object[i].area; object[i].color.black=object[i].color.black/object[i].area; object[i].centroid.x=object[i].centroid.x/object[i].area; object[i].centroid.y=object[i].centroid.y/object[i].area; } component_view=DestroyCacheView(component_view); image_view=DestroyCacheView(image_view); /* Report statistics on unique objects. */ qsort((void *) object,number_objects,sizeof(*object),CCObjectCompare); (void) fprintf(stdout, "Objects (id: bounding-box centroid area mean-color):\n"); for (i=0; i < (ssize_t) number_objects; i++) { char mean_color[MagickPathExtent]; if (status == MagickFalse) break; if (object[i].area < MagickEpsilon) continue; GetColorTuple(&object[i].color,MagickFalse,mean_color); (void) fprintf(stdout, " %.20g: %.20gx%.20g%+.20g%+.20g %.1f,%.1f %.20g %s\n",(double) object[i].id,(double) object[i].bounding_box.width,(double) object[i].bounding_box.height,(double) object[i].bounding_box.x, (double) object[i].bounding_box.y,object[i].centroid.x, object[i].centroid.y,(double) object[i].area,mean_color); } object=(CCObject *) RelinquishMagickMemory(object); return(status); }
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); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e U I L I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Procedure WriteUILImage() writes an image to a file in the X-Motif UIL table % format. % % The format of the WriteUILImage method is: % % MagickBooleanType WriteUILImage(const ImageInfo *image_info, % Image *image,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 WriteUILImage(const ImageInfo *image_info,Image *image, ExceptionInfo *exception) { #define MaxCixels 92 char basename[MagickPathExtent], buffer[MagickPathExtent], name[MagickPathExtent], *symbol; int j; MagickBooleanType status, transparent; MagickSizeType number_pixels; PixelInfo pixel; register const Quantum *p; register ssize_t i, x; size_t characters_per_pixel, colors; ssize_t k, y; static const char Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; /* Open output image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickCoreSignature); assert(image != (Image *) NULL); assert(image->signature == MagickCoreSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickCoreSignature); status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); if (status == MagickFalse) return(status); (void) TransformImageColorspace(image,sRGBColorspace,exception); transparent=MagickFalse; i=0; p=(const Quantum *) NULL; if (image->storage_class == PseudoClass) colors=image->colors; else { unsigned char *matte_image; /* Convert DirectClass to PseudoClass image. */ matte_image=(unsigned char *) NULL; if (image->alpha_trait != UndefinedPixelTrait) { /* Map all the transparent pixels. */ number_pixels=(MagickSizeType) image->columns*image->rows; if (number_pixels != ((MagickSizeType) (size_t) number_pixels)) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); matte_image=(unsigned char *) AcquireQuantumMemory(image->columns, image->rows*sizeof(*matte_image)); if (matte_image == (unsigned char *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { matte_image[i]=(unsigned char) (GetPixelAlpha(image,p) == (Quantum) TransparentAlpha ? 1 : 0); if (matte_image[i] != 0) transparent=MagickTrue; i++; p+=GetPixelChannels(image); } } } (void) SetImageType(image,PaletteType,exception); colors=image->colors; if (transparent != MagickFalse) { register Quantum *q; colors++; for (y=0; y < (ssize_t) image->rows; y++) { q=GetAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { if (matte_image[i] != 0) SetPixelIndex(image,(Quantum) image->colors,q); q+=GetPixelChannels(image); } } } if (matte_image != (unsigned char *) NULL) matte_image=(unsigned char *) RelinquishMagickMemory(matte_image); } /* Compute the character per pixel. */ characters_per_pixel=1; for (k=MaxCixels; (ssize_t) colors > k; k*=MaxCixels) characters_per_pixel++; /* UIL header. */ symbol=AcquireString(""); (void) WriteBlobString(image,"/* UIL */\n"); GetPathComponent(image->filename,BasePath,basename); (void) FormatLocaleString(buffer,MagickPathExtent, "value\n %s_ct : color_table(\n",basename); (void) WriteBlobString(image,buffer); GetPixelInfo(image,&pixel); for (i=0; i < (ssize_t) colors; i++) { /* Define UIL color. */ pixel=image->colormap[i]; pixel.colorspace=sRGBColorspace; pixel.depth=8; pixel.alpha=(double) OpaqueAlpha; GetColorTuple(&pixel,MagickTrue,name); if (transparent != MagickFalse) if (i == (ssize_t) (colors-1)) (void) CopyMagickString(name,"None",MagickPathExtent); /* Write UIL color. */ k=i % MaxCixels; symbol[0]=Cixel[k]; for (j=1; j < (int) characters_per_pixel; j++) { k=((i-k)/MaxCixels) % MaxCixels; symbol[j]=Cixel[k]; } symbol[j]='\0'; (void) SubstituteString(&symbol,"'","''"); if (LocaleCompare(name,"None") == 0) (void) FormatLocaleString(buffer,MagickPathExtent, " background color = '%s'",symbol); else (void) FormatLocaleString(buffer,MagickPathExtent, " color('%s',%s) = '%s'",name, GetPixelInfoIntensity(image,image->colormap+i) < (QuantumRange/2.0) ? "background" : "foreground",symbol); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent,"%s", (i == (ssize_t) (colors-1) ? ");\n" : ",\n")); (void) WriteBlobString(image,buffer); } /* Define UIL pixels. */ GetPathComponent(image->filename,BasePath,basename); (void) FormatLocaleString(buffer,MagickPathExtent, " %s_icon : icon(color_table = %s_ct,\n",basename,basename); (void) WriteBlobString(image,buffer); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) break; (void) WriteBlobString(image," \""); for (x=0; x < (ssize_t) image->columns; x++) { k=((ssize_t) GetPixelIndex(image,p) % MaxCixels); symbol[0]=Cixel[k]; for (j=1; j < (int) characters_per_pixel; j++) { k=(((int) GetPixelIndex(image,p)-k)/MaxCixels) % MaxCixels; symbol[j]=Cixel[k]; } symbol[j]='\0'; (void) CopyMagickString(buffer,symbol,MagickPathExtent); (void) WriteBlobString(image,buffer); p+=GetPixelChannels(image); } (void) FormatLocaleString(buffer,MagickPathExtent,"\"%s\n", (y == (ssize_t) (image->rows-1) ? ");" : ",")); (void) WriteBlobString(image,buffer); status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } symbol=DestroyString(symbol); (void) CloseBlob(image); return(MagickTrue); }
MagickExport Image *ConnectedComponentsImage(const Image *image, const size_t connectivity,CCObjectInfo **objects,ExceptionInfo *exception) { #define ConnectedComponentsImageTag "ConnectedComponents/Image" CacheView *image_view, *component_view; CCObjectInfo *object; char *p; const char *artifact; double area_threshold; Image *component_image; MagickBooleanType status; MagickOffsetType progress; MatrixInfo *equivalences; register ssize_t i; size_t size; ssize_t first, last, n, step, y; /* Initialize connected components image attributes. */ assert(image != (Image *) NULL); assert(image->signature == MagickCoreSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickCoreSignature); if (objects != (CCObjectInfo **) NULL) *objects=(CCObjectInfo *) NULL; component_image=CloneImage(image,image->columns,image->rows,MagickTrue, exception); if (component_image == (Image *) NULL) return((Image *) NULL); component_image->depth=MAGICKCORE_QUANTUM_DEPTH; if (AcquireImageColormap(component_image,MaxColormapSize,exception) == MagickFalse) { component_image=DestroyImage(component_image); ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); } /* Initialize connected components equivalences. */ size=image->columns*image->rows; if (image->columns != (size/image->rows)) { component_image=DestroyImage(component_image); ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); } equivalences=AcquireMatrixInfo(size,1,sizeof(ssize_t),exception); if (equivalences == (MatrixInfo *) NULL) { component_image=DestroyImage(component_image); return((Image *) NULL); } for (n=0; n < (ssize_t) (image->columns*image->rows); n++) (void) SetMatrixElement(equivalences,n,0,&n); object=(CCObjectInfo *) AcquireQuantumMemory(MaxColormapSize,sizeof(*object)); if (object == (CCObjectInfo *) NULL) { equivalences=DestroyMatrixInfo(equivalences); component_image=DestroyImage(component_image); ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); } (void) ResetMagickMemory(object,0,MaxColormapSize*sizeof(*object)); for (i=0; i < (ssize_t) MaxColormapSize; i++) { object[i].id=i; object[i].bounding_box.x=(ssize_t) image->columns; object[i].bounding_box.y=(ssize_t) image->rows; GetPixelInfo(image,&object[i].color); } /* Find connected components. */ status=MagickTrue; progress=0; image_view=AcquireVirtualCacheView(image,exception); for (n=0; n < (ssize_t) (connectivity > 4 ? 4 : 2); n++) { ssize_t connect4[2][2] = { { -1, 0 }, { 0, -1 } }, connect8[4][2] = { { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 } }, dx, dy; if (status == MagickFalse) continue; dy=connectivity > 4 ? connect8[n][0] : connect4[n][0]; dx=connectivity > 4 ? connect8[n][1] : connect4[n][1]; for (y=0; y < (ssize_t) image->rows; y++) { register const Quantum *magick_restrict p; register ssize_t x; if (status == MagickFalse) continue; p=GetCacheViewVirtualPixels(image_view,0,y-1,image->columns,3,exception); if (p == (const Quantum *) NULL) { status=MagickFalse; continue; } p+=GetPixelChannels(image)*image->columns; for (x=0; x < (ssize_t) image->columns; x++) { PixelInfo pixel, target; ssize_t neighbor_offset, object, offset, ox, oy, root; /* Is neighbor an authentic pixel and a different color than the pixel? */ GetPixelInfoPixel(image,p,&pixel); neighbor_offset=dy*(GetPixelChannels(image)*image->columns)+dx* GetPixelChannels(image); GetPixelInfoPixel(image,p+neighbor_offset,&target); if (((x+dx) < 0) || ((x+dx) >= (ssize_t) image->columns) || ((y+dy) < 0) || ((y+dy) >= (ssize_t) image->rows) || (IsFuzzyEquivalencePixelInfo(&pixel,&target) == MagickFalse)) { p+=GetPixelChannels(image); continue; } /* Resolve this equivalence. */ offset=y*image->columns+x; neighbor_offset=dy*image->columns+dx; ox=offset; status=GetMatrixElement(equivalences,ox,0,&object); while (object != ox) { ox=object; status=GetMatrixElement(equivalences,ox,0,&object); } oy=offset+neighbor_offset; status=GetMatrixElement(equivalences,oy,0,&object); while (object != oy) { oy=object; status=GetMatrixElement(equivalences,oy,0,&object); } if (ox < oy) { status=SetMatrixElement(equivalences,oy,0,&ox); root=ox; } else { status=SetMatrixElement(equivalences,ox,0,&oy); root=oy; } ox=offset; status=GetMatrixElement(equivalences,ox,0,&object); while (object != root) { status=GetMatrixElement(equivalences,ox,0,&object); status=SetMatrixElement(equivalences,ox,0,&root); } oy=offset+neighbor_offset; status=GetMatrixElement(equivalences,oy,0,&object); while (object != root) { status=GetMatrixElement(equivalences,oy,0,&object); status=SetMatrixElement(equivalences,oy,0,&root); } status=SetMatrixElement(equivalences,y*image->columns+x,0,&root); p+=GetPixelChannels(image); } } } image_view=DestroyCacheView(image_view); /* Label connected components. */ n=0; image_view=AcquireVirtualCacheView(image,exception); component_view=AcquireAuthenticCacheView(component_image,exception); for (y=0; y < (ssize_t) component_image->rows; y++) { register const Quantum *magick_restrict p; register Quantum *magick_restrict q; register ssize_t x; if (status == MagickFalse) continue; p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); q=QueueCacheViewAuthenticPixels(component_view,0,y,component_image->columns, 1,exception); if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) component_image->columns; x++) { ssize_t id, offset; offset=y*image->columns+x; status=GetMatrixElement(equivalences,offset,0,&id); if (id == offset) { id=n++; if (n > (ssize_t) MaxColormapSize) break; status=SetMatrixElement(equivalences,offset,0,&id); } else { status=GetMatrixElement(equivalences,id,0,&id); status=SetMatrixElement(equivalences,offset,0,&id); } if (x < object[id].bounding_box.x) object[id].bounding_box.x=x; if (x > (ssize_t) object[id].bounding_box.width) object[id].bounding_box.width=(size_t) x; if (y < object[id].bounding_box.y) object[id].bounding_box.y=y; if (y > (ssize_t) object[id].bounding_box.height) object[id].bounding_box.height=(size_t) y; object[id].color.red+=GetPixelRed(image,p); object[id].color.green+=GetPixelGreen(image,p); object[id].color.blue+=GetPixelBlue(image,p); object[id].color.black+=GetPixelBlack(image,p); object[id].color.alpha+=GetPixelAlpha(image,p); object[id].centroid.x+=x; object[id].centroid.y+=y; object[id].area++; SetPixelIndex(component_image,(Quantum) id,q); p+=GetPixelChannels(image); q+=GetPixelChannels(component_image); } if (n > (ssize_t) MaxColormapSize) break; if (SyncCacheViewAuthenticPixels(component_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; proceed=SetImageProgress(image,ConnectedComponentsImageTag,progress++, image->rows); if (proceed == MagickFalse) status=MagickFalse; } } component_view=DestroyCacheView(component_view); image_view=DestroyCacheView(image_view); equivalences=DestroyMatrixInfo(equivalences); if (n > (ssize_t) MaxColormapSize) { object=(CCObjectInfo *) RelinquishMagickMemory(object); component_image=DestroyImage(component_image); ThrowImageException(ResourceLimitError,"TooManyObjects"); } component_image->colors=(size_t) n; for (i=0; i < (ssize_t) component_image->colors; i++) { object[i].bounding_box.width-=(object[i].bounding_box.x-1); object[i].bounding_box.height-=(object[i].bounding_box.y-1); object[i].color.red=object[i].color.red/object[i].area; object[i].color.green=object[i].color.green/object[i].area; object[i].color.blue=object[i].color.blue/object[i].area; object[i].color.alpha=object[i].color.alpha/object[i].area; object[i].color.black=object[i].color.black/object[i].area; object[i].centroid.x=object[i].centroid.x/object[i].area; object[i].centroid.y=object[i].centroid.y/object[i].area; } artifact=GetImageArtifact(image,"connected-components:area-threshold"); area_threshold=0.0; if (artifact != (const char *) NULL) area_threshold=StringToDouble(artifact,(char **) NULL); if (area_threshold > 0.0) { /* Merge object below area threshold. */ component_view=AcquireAuthenticCacheView(component_image,exception); for (i=0; i < (ssize_t) component_image->colors; i++) { double census; RectangleInfo bounding_box; register ssize_t j; size_t id; if (status == MagickFalse) continue; if ((double) object[i].area >= area_threshold) continue; for (j=0; j < (ssize_t) component_image->colors; j++) object[j].census=0; bounding_box=object[i].bounding_box; for (y=0; y < (ssize_t) bounding_box.height+2; y++) { register const Quantum *magick_restrict p; register ssize_t x; if (status == MagickFalse) continue; p=GetCacheViewVirtualPixels(component_view,bounding_box.x-1, bounding_box.y+y-1,bounding_box.width+2,1,exception); if (p == (const Quantum *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) bounding_box.width+2; x++) { j=(ssize_t) GetPixelIndex(component_image,p); if (j != i) object[j].census++; } } census=0; id=0; for (j=0; j < (ssize_t) component_image->colors; j++) if (census < object[j].census) { census=object[j].census; id=(size_t) j; } object[id].area+=object[i].area; for (y=0; y < (ssize_t) bounding_box.height; y++) { register Quantum *magick_restrict q; register ssize_t x; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(component_view,bounding_box.x, bounding_box.y+y,bounding_box.width,1,exception); if (q == (Quantum *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) bounding_box.width; x++) { if ((ssize_t) GetPixelIndex(component_image,q) == i) SetPixelIndex(image,(Quantum) id,q); q+=GetPixelChannels(component_image); } if (SyncCacheViewAuthenticPixels(component_view,exception) == MagickFalse) status=MagickFalse; } } (void) SyncImage(component_image,exception); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d P A N G O I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadPANGOImage() reads an image in the Pango Markup Language Format. % % The format of the ReadPANGOImage method is: % % Image *ReadPANGOImage(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 *ReadPANGOImage(const ImageInfo *image_info, ExceptionInfo *exception) { cairo_font_options_t *font_options; cairo_surface_t *surface; char *caption, *property; cairo_t *cairo_image; const char *option; DrawInfo *draw_info; Image *image; MagickBooleanType status; PangoAlignment align; PangoContext *context; PangoFontMap *fontmap; PangoGravity gravity; PangoLayout *layout; PangoRectangle extent; PixelInfo fill_color; RectangleInfo page; register unsigned char *p; size_t stride; ssize_t y; unsigned char *pixels; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info,exception); (void) ResetImagePage(image,"0x0+0+0"); /* Format caption. */ option=GetImageArtifact(image,"filename"); if (option == (const char *) NULL) property=InterpretImageProperties(image_info,image,image_info->filename, exception); else if (LocaleNCompare(option,"pango:",6) == 0) property=InterpretImageProperties(image_info,image,option+6,exception); else property=InterpretImageProperties(image_info,image,option,exception); (void) SetImageProperty(image,"caption",property,exception); property=DestroyString(property); caption=ConstantString(GetImageProperty(image,"caption",exception)); /* Get context. */ fontmap=pango_cairo_font_map_new(); pango_cairo_font_map_set_resolution(PANGO_CAIRO_FONT_MAP(fontmap), image->resolution.x == 0.0 ? 90.0 : image->resolution.x); font_options=cairo_font_options_create(); option=GetImageArtifact(image,"pango:hinting"); if (option != (const char *) NULL) { if (LocaleCompare(option,"none") != 0) cairo_font_options_set_hint_style(font_options,CAIRO_HINT_STYLE_NONE); if (LocaleCompare(option,"full") != 0) cairo_font_options_set_hint_style(font_options,CAIRO_HINT_STYLE_FULL); } context=pango_font_map_create_context(fontmap); pango_cairo_context_set_font_options(context,font_options); cairo_font_options_destroy(font_options); option=GetImageArtifact(image,"pango:language"); if (option != (const char *) NULL) pango_context_set_language(context,pango_language_from_string(option)); draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); pango_context_set_base_dir(context,draw_info->direction == RightToLeftDirection ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR); switch (draw_info->gravity) { case NorthGravity: { gravity=PANGO_GRAVITY_NORTH; break; } case NorthWestGravity: case WestGravity: case SouthWestGravity: { gravity=PANGO_GRAVITY_WEST; break; } case NorthEastGravity: case EastGravity: case SouthEastGravity: { gravity=PANGO_GRAVITY_EAST; break; } case SouthGravity: { gravity=PANGO_GRAVITY_SOUTH; break; } default: { gravity=PANGO_GRAVITY_AUTO; break; } } pango_context_set_base_gravity(context,gravity); option=GetImageArtifact(image,"pango:gravity-hint"); if (option != (const char *) NULL) { if (LocaleCompare(option,"line") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_LINE); if (LocaleCompare(option,"natural") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_NATURAL); if (LocaleCompare(option,"strong") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_STRONG); } /* Configure layout. */ layout=pango_layout_new(context); option=GetImageArtifact(image,"pango:auto-dir"); if (option != (const char *) NULL) pango_layout_set_auto_dir(layout,1); option=GetImageArtifact(image,"pango:ellipsize"); if (option != (const char *) NULL) { if (LocaleCompare(option,"end") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_END); if (LocaleCompare(option,"middle") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_MIDDLE); if (LocaleCompare(option,"none") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_NONE); if (LocaleCompare(option,"start") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_START); } option=GetImageArtifact(image,"pango:justify"); if (IfMagickTrue(IsStringTrue(option))) pango_layout_set_justify(layout,1); option=GetImageArtifact(image,"pango:single-paragraph"); if (IfMagickTrue(IsStringTrue(option))) pango_layout_set_single_paragraph_mode(layout,1); option=GetImageArtifact(image,"pango:wrap"); if (option != (const char *) NULL) { if (LocaleCompare(option,"char") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_CHAR); if (LocaleCompare(option,"word") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_WORD); if (LocaleCompare(option,"word-char") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_WORD_CHAR); } option=GetImageArtifact(image,"pango:indent"); if (option != (const char *) NULL) pango_layout_set_indent(layout,(int) ((StringToLong(option)* (image->resolution.x == 0.0 ? 90.0 : image->resolution.x)*PANGO_SCALE+36)/ 90.0+0.5)); switch (draw_info->align) { case CenterAlign: align=PANGO_ALIGN_CENTER; break; case RightAlign: align=PANGO_ALIGN_RIGHT; break; case LeftAlign: align=PANGO_ALIGN_LEFT; break; default: { if (draw_info->gravity == CenterGravity) { align=PANGO_ALIGN_CENTER; break; } align=PANGO_ALIGN_LEFT; break; } } if ((align != PANGO_ALIGN_CENTER) && (draw_info->direction == RightToLeftDirection)) align=(PangoAlignment) (PANGO_ALIGN_LEFT+PANGO_ALIGN_RIGHT-align); pango_layout_set_alignment(layout,align); if (draw_info->font != (char *) NULL) { PangoFontDescription *description; /* Set font. */ description=pango_font_description_from_string(draw_info->font); pango_font_description_set_size(description,(int) (PANGO_SCALE* draw_info->pointsize+0.5)); pango_layout_set_font_description(layout,description); pango_font_description_free(description); } option=GetImageArtifact(image,"pango:markup"); if ((option != (const char *) NULL) && (IsStringTrue(option) == MagickFalse)) pango_layout_set_text(layout,caption,-1); else { GError *error; error=(GError *) NULL; if (pango_parse_markup(caption,-1,0,NULL,NULL,NULL,&error) == 0) (void) ThrowMagickException(exception,GetMagickModule(),CoderError, error->message,"`%s'",image_info->filename); pango_layout_set_markup(layout,caption,-1); } pango_layout_context_changed(layout); page.x=0; page.y=0; if (image_info->page != (char *) NULL) (void) ParseAbsoluteGeometry(image_info->page,&page); if (image->columns == 0) { pango_layout_get_extents(layout,NULL,&extent); image->columns=(extent.x+extent.width+PANGO_SCALE/2)/PANGO_SCALE+2*page.x; } else { image->columns-=2*page.x; pango_layout_set_width(layout,(int) ((PANGO_SCALE*image->columns* (image->resolution.x == 0.0 ? 90.0 : image->resolution.x)+45.0)/90.0+ 0.5)); } if (image->rows == 0) { pango_layout_get_extents(layout,NULL,&extent); image->rows=(extent.y+extent.height+PANGO_SCALE/2)/PANGO_SCALE+2*page.y; } else { image->rows-=2*page.y; pango_layout_set_height(layout,(int) ((PANGO_SCALE*image->rows* (image->resolution.y == 0.0 ? 90.0 : image->resolution.y)+45.0)/90.0+ 0.5)); } /* Render markup. */ stride=(size_t) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, image->columns); pixels=(unsigned char *) AcquireQuantumMemory(image->rows,stride* sizeof(*pixels)); if (pixels == (unsigned char *) NULL) { draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } surface=cairo_image_surface_create_for_data(pixels,CAIRO_FORMAT_ARGB32, image->columns,image->rows,stride); cairo_image=cairo_create(surface); cairo_set_operator(cairo_image,CAIRO_OPERATOR_CLEAR); cairo_paint(cairo_image); cairo_set_operator(cairo_image,CAIRO_OPERATOR_OVER); cairo_translate(cairo_image,page.x,page.y); pango_cairo_show_layout(cairo_image,layout); cairo_destroy(cairo_image); cairo_surface_destroy(surface); g_object_unref(layout); g_object_unref(fontmap); /* Convert surface to image. */ (void) SetImageBackgroundColor(image,exception); p=pixels; GetPixelInfo(image,&fill_color); for (y=0; y < (ssize_t) image->rows; y++) { register Quantum *q; register ssize_t x; q=GetAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { double gamma; fill_color.blue=(double) ScaleCharToQuantum(*p++); fill_color.green=(double) ScaleCharToQuantum(*p++); fill_color.red=(double) ScaleCharToQuantum(*p++); fill_color.alpha=(double) ScaleCharToQuantum(*p++); /* Disassociate alpha. */ gamma=1.0-QuantumScale*fill_color.alpha; gamma=PerceptibleReciprocal(gamma); fill_color.blue*=gamma; fill_color.green*=gamma; fill_color.red*=gamma; CompositePixelOver(image,&fill_color,fill_color.alpha,q,(double) GetPixelAlpha(image,q),q); q+=GetPixelChannels(image); } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } /* Relinquish resources. */ pixels=(unsigned char *) RelinquishMagickMemory(pixels); draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + G e t I m a g e B o u n d i n g B o x % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % GetImageBoundingBox() returns the bounding box of an image canvas. % % The format of the GetImageBoundingBox method is: % % RectangleInfo GetImageBoundingBox(const Image *image, % ExceptionInfo *exception) % % A description of each parameter follows: % % o bounds: Method GetImageBoundingBox returns the bounding box of an % image canvas. % % o image: the image. % % o exception: return any errors or warnings in this structure. % */ MagickExport RectangleInfo GetImageBoundingBox(const Image *image, ExceptionInfo *exception) { CacheView *image_view; MagickBooleanType status; PixelInfo target[3], zero; RectangleInfo bounds; register const Quantum *p; ssize_t y; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); bounds.width=0; bounds.height=0; bounds.x=(ssize_t) image->columns; bounds.y=(ssize_t) image->rows; GetPixelInfo(image,&target[0]); image_view=AcquireVirtualCacheView(image,exception); p=GetCacheViewVirtualPixels(image_view,0,0,1,1,exception); if (p == (const Quantum *) NULL) { image_view=DestroyCacheView(image_view); return(bounds); } GetPixelInfoPixel(image,p,&target[0]); GetPixelInfo(image,&target[1]); p=GetCacheViewVirtualPixels(image_view,(ssize_t) image->columns-1,0,1,1, exception); GetPixelInfoPixel(image,p,&target[1]); GetPixelInfo(image,&target[2]); p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) image->rows-1,1,1, exception); GetPixelInfoPixel(image,p,&target[2]); status=MagickTrue; GetPixelInfo(image,&zero); #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++) { PixelInfo pixel; RectangleInfo bounding_box; register const Quantum *restrict p; register ssize_t x; if (status == MagickFalse) continue; #if defined(MAGICKCORE_OPENMP_SUPPORT) # pragma omp critical (MagickCore_GetImageBoundingBox) #endif bounding_box=bounds; p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) { status=MagickFalse; continue; } pixel=zero; for (x=0; x < (ssize_t) image->columns; x++) { GetPixelInfoPixel(image,p,&pixel); if ((x < bounding_box.x) && (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse)) bounding_box.x=x; if ((x > (ssize_t) bounding_box.width) && (IsFuzzyEquivalencePixelInfo(&pixel,&target[1]) == MagickFalse)) bounding_box.width=(size_t) x; if ((y < bounding_box.y) && (IsFuzzyEquivalencePixelInfo(&pixel,&target[0]) == MagickFalse)) bounding_box.y=y; if ((y > (ssize_t) bounding_box.height) && (IsFuzzyEquivalencePixelInfo(&pixel,&target[2]) == MagickFalse)) bounding_box.height=(size_t) y; p+=GetPixelChannels(image); } #if defined(MAGICKCORE_OPENMP_SUPPORT) # pragma omp critical (MagickCore_GetImageBoundingBox) #endif { if (bounding_box.x < bounds.x) bounds.x=bounding_box.x; if (bounding_box.y < bounds.y) bounds.y=bounding_box.y; if (bounding_box.width > bounds.width) bounds.width=bounding_box.width; if (bounding_box.height > bounds.height) bounds.height=bounding_box.height; } } image_view=DestroyCacheView(image_view); if ((bounds.width == 0) || (bounds.height == 0)) (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning, "GeometryDoesNotContainImage","`%s'",image->filename); else { bounds.width-=(bounds.x-1); bounds.height-=(bounds.y-1); } return(bounds); }
void ImageMesh::buildMesh3D(const std::vector<std::string> & filenames) { // If the user gave us a "stack" with 0 or 1 files in it, we can't // really create a 3D Mesh from that if (filenames.size() <= 1) mooseError("ImageMesh error: Cannot create a 3D ImageMesh from an image stack with ", filenames.size(), " images."); // For each file in the stack, process it using the 'file' command. // We want to be sure that all the images in the stack are the same // size, for example... int xpixels = 0, ypixels = 0, zpixels = filenames.size(); // Take pixel info from the first image in the stack to determine the aspect ratio GetPixelInfo(filenames[0], xpixels, ypixels); // TODO: Check that all images are the same aspect ratio and have // the same number of pixels? ImageFunction does not currently do // this... // for (const auto & filename : filenames) // { // // Extract the number of pixels from the image using the file command // GetPixelInfo(filename, xpixels, ypixels); // // // Moose::out << "Image " << filename << " has size: " << xpixels << " by " << ypixels << // std::endl; // } // Use the number of x and y pixels and the number of images to // determine the the x, y, and z dimensions of the mesh. We assume // that there is 1 pixel in the z-direction for each image in the // stack. // Set the maximum dimension to 1.0 while scaling the other // directions to maintain the aspect ratio. _xmax = xpixels; _ymax = ypixels; _zmax = zpixels; if (_scale_to_one) { Real max = std::max(std::max(_xmax, _ymax), _zmax); _xmax /= max; _ymax /= max; _zmax /= max; } // Compute the number of cells in the x and y direction based on // the user's cells_per_pixel parameter. Note: we use ints here // because the GeneratedMesh params object uses ints for these... _nx = static_cast<int>(_cells_per_pixel * xpixels); _ny = static_cast<int>(_cells_per_pixel * ypixels); _nz = static_cast<int>(_cells_per_pixel * zpixels); // Actually build the Mesh MeshTools::Generation::build_cube(dynamic_cast<UnstructuredMesh &>(getMesh()), _nx, _ny, _nz, /*xmin=*/0., /*xmax=*/_xmax, /*ymin=*/0., /*ymax=*/_ymax, /*zmin=*/0., /*zmax=*/_zmax, HEX8); }