/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % 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; MemoryInfo *pixel_info; 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, *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"); pixel_info=AcquireVirtualMemory(image->columns,image->rows*number_planes* sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); if ((flags & 0x01) && !(flags & 0x02)) { ssize_t j; /* Set background color. */ p=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=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=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=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=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=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); pixel_info=RelinquishVirtualMemory(pixel_info); 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 A V S I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadAVSImage() reads an AVS X 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 ReadAVSImage method is: % % Image *ReadAVSImage(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 *ReadAVSImage(const ImageInfo *image_info,ExceptionInfo *exception) { Image *image; MagickBooleanType status; MemoryInfo *pixel_info; register Quantum *q; register ssize_t x; register unsigned char *p; size_t height, length, width; ssize_t count, y; unsigned char *pixels; /* 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); } /* Read AVS X image. */ width=ReadBlobMSBLong(image); height=ReadBlobMSBLong(image); if (EOFBlob(image) != MagickFalse) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); if ((width == 0UL) || (height == 0UL)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); do { /* Convert AVS raster image to pixel packets. */ image->columns=width; image->rows=height; image->depth=8; if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) if (image->scene >= (image_info->scene+image_info->number_scenes-1)) break; status=SetImageExtent(image,image->columns,image->rows,exception); if (status == MagickFalse) return(DestroyImageList(image)); pixel_info=AcquireVirtualMemory(image->columns,4*sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); length=(size_t) 4*image->columns; for (y=0; y < (ssize_t) image->rows; y++) { count=ReadBlob(image,length,pixels); if ((size_t) count != length) ThrowReaderException(CorruptImageError,"UnableToReadImageData"); p=pixels; q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { SetPixelAlpha(image,ScaleCharToQuantum(*p++),q); SetPixelRed(image,ScaleCharToQuantum(*p++),q); SetPixelGreen(image,ScaleCharToQuantum(*p++),q); SetPixelBlue(image,ScaleCharToQuantum(*p++),q); if (GetPixelAlpha(image,q) != OpaqueAlpha) image->alpha_trait=BlendPixelTrait; 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; } } pixel_info=RelinquishVirtualMemory(pixel_info); 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; width=ReadBlobMSBLong(image); height=ReadBlobMSBLong(image); if ((width != 0UL) && (height != 0UL)) { /* 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 ((width != 0UL) && (height != 0UL)); (void) CloseBlob(image); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d P C X I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadPCXImage() reads a ZSoft IBM PC Paintbrush 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 ReadPCXImage method is: % % Image *ReadPCXImage(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 *ReadPCXImage(const ImageInfo *image_info,ExceptionInfo *exception) { #define ThrowPCXException(severity,tag) \ { \ scanline=(unsigned char *) RelinquishMagickMemory(scanline); \ pixel_info=RelinquishVirtualMemory(pixel_info); \ ThrowReaderException(severity,tag); \ } Image *image; int bits, id, mask; MagickBooleanType status; MagickOffsetType offset, *page_table; MemoryInfo *pixel_info; PCXInfo pcx_info; register ssize_t x; register Quantum *q; register ssize_t i; register unsigned char *p, *r; size_t one, pcx_packets; ssize_t count, y; unsigned char packet, pcx_colormap[768], *pixels, *scanline; /* 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); } /* Determine if this a PCX file. */ page_table=(MagickOffsetType *) NULL; if (LocaleCompare(image_info->magick,"DCX") == 0) { size_t magic; /* Read the DCX page table. */ magic=ReadBlobLSBLong(image); if (magic != 987654321) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); page_table=(MagickOffsetType *) AcquireQuantumMemory(1024UL, sizeof(*page_table)); if (page_table == (MagickOffsetType *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); for (id=0; id < 1024; id++) { page_table[id]=(MagickOffsetType) ReadBlobLSBLong(image); if (page_table[id] == 0) break; } } if (page_table != (MagickOffsetType *) NULL) { offset=SeekBlob(image,(MagickOffsetType) page_table[0],SEEK_SET); if (offset < 0) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); } count=ReadBlob(image,1,&pcx_info.identifier); for (id=1; id < 1024; id++) { int bits_per_pixel; /* Verify PCX identifier. */ pcx_info.version=(unsigned char) ReadBlobByte(image); if ((count != 1) || (pcx_info.identifier != 0x0a)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); pcx_info.encoding=(unsigned char) ReadBlobByte(image); bits_per_pixel=ReadBlobByte(image); if (bits_per_pixel == -1) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); pcx_info.bits_per_pixel=(unsigned char) bits_per_pixel; pcx_info.left=ReadBlobLSBShort(image); pcx_info.top=ReadBlobLSBShort(image); pcx_info.right=ReadBlobLSBShort(image); pcx_info.bottom=ReadBlobLSBShort(image); pcx_info.horizontal_resolution=ReadBlobLSBShort(image); pcx_info.vertical_resolution=ReadBlobLSBShort(image); /* Read PCX raster colormap. */ image->columns=(size_t) MagickAbsoluteValue((ssize_t) pcx_info.right- pcx_info.left)+1UL; image->rows=(size_t) MagickAbsoluteValue((ssize_t) pcx_info.bottom- pcx_info.top)+1UL; if ((image->columns == 0) || (image->rows == 0) || ((pcx_info.bits_per_pixel != 1) && (pcx_info.bits_per_pixel != 2) && (pcx_info.bits_per_pixel != 4) && (pcx_info.bits_per_pixel != 8))) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); image->depth=pcx_info.bits_per_pixel; image->units=PixelsPerInchResolution; image->resolution.x=(double) pcx_info.horizontal_resolution; image->resolution.y=(double) pcx_info.vertical_resolution; image->colors=16; count=ReadBlob(image,3*image->colors,pcx_colormap); if (count != (ssize_t) (3*image->colors)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); pcx_info.reserved=(unsigned char) ReadBlobByte(image); pcx_info.planes=(unsigned char) ReadBlobByte(image); if ((pcx_info.bits_per_pixel*pcx_info.planes) >= 64) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); one=1; if ((pcx_info.bits_per_pixel != 8) || (pcx_info.planes == 1)) if ((pcx_info.version == 3) || (pcx_info.version == 5) || ((pcx_info.bits_per_pixel*pcx_info.planes) == 1)) image->colors=(size_t) MagickMin(one << (1UL* (pcx_info.bits_per_pixel*pcx_info.planes)),256UL); if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); if ((pcx_info.bits_per_pixel >= 8) && (pcx_info.planes != 1)) image->storage_class=DirectClass; p=pcx_colormap; for (i=0; i < (ssize_t) image->colors; i++) { image->colormap[i].red=ScaleCharToQuantum(*p++); image->colormap[i].green=ScaleCharToQuantum(*p++); image->colormap[i].blue=ScaleCharToQuantum(*p++); } pcx_info.bytes_per_line=ReadBlobLSBShort(image); pcx_info.palette_info=ReadBlobLSBShort(image); pcx_info.horizontal_screensize=ReadBlobLSBShort(image); pcx_info.vertical_screensize=ReadBlobLSBShort(image); for (i=0; i < 54; i++) (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; status=SetImageExtent(image,image->columns,image->rows,exception); if (status == MagickFalse) return(DestroyImageList(image)); /* Read image data. */ if (HeapOverflowSanityCheck(image->rows, (size_t) pcx_info.bytes_per_line) != MagickFalse) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); pcx_packets=(size_t) image->rows*pcx_info.bytes_per_line; if (HeapOverflowSanityCheck(pcx_packets, (size_t)pcx_info.planes) != MagickFalse) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); pcx_packets=(size_t) pcx_packets*pcx_info.planes; if ((size_t) (pcx_info.bits_per_pixel*pcx_info.planes*image->columns) > (pcx_packets*8U)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); scanline=(unsigned char *) AcquireQuantumMemory(MagickMax(image->columns, pcx_info.bytes_per_line),MagickMax(8,pcx_info.planes)*sizeof(*scanline)); pixel_info=AcquireVirtualMemory(pcx_packets,2*sizeof(*pixels)); if ((scanline == (unsigned char *) NULL) || (pixel_info == (MemoryInfo *) NULL)) { if (scanline != (unsigned char *) NULL) scanline=(unsigned char *) RelinquishMagickMemory(scanline); if (pixel_info != (MemoryInfo *) NULL) pixel_info=RelinquishVirtualMemory(pixel_info); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); /* Uncompress image data. */ p=pixels; if (pcx_info.encoding == 0) while (pcx_packets != 0) { packet=(unsigned char) ReadBlobByte(image); if (EOFBlob(image) != MagickFalse) ThrowPCXException(CorruptImageError,"UnexpectedEndOfFile"); *p++=packet; pcx_packets--; } else while (pcx_packets != 0) { packet=(unsigned char) ReadBlobByte(image); if (EOFBlob(image) != MagickFalse) ThrowPCXException(CorruptImageError,"UnexpectedEndOfFile"); if ((packet & 0xc0) != 0xc0) { *p++=packet; pcx_packets--; continue; } count=(ssize_t) (packet & 0x3f); packet=(unsigned char) ReadBlobByte(image); if (EOFBlob(image) != MagickFalse) ThrowPCXException(CorruptImageError,"UnexpectedEndOfFile"); for ( ; count != 0; count--) { *p++=packet; pcx_packets--; if (pcx_packets == 0) break; } } if (image->storage_class == DirectClass) image->alpha_trait=pcx_info.planes > 3 ? BlendPixelTrait : UndefinedPixelTrait; else if ((pcx_info.version == 5) || ((pcx_info.bits_per_pixel*pcx_info.planes) == 1)) { /* Initialize image colormap. */ if (image->colors > 256) ThrowPCXException(CorruptImageError,"ColormapExceeds256Colors"); if ((pcx_info.bits_per_pixel*pcx_info.planes) == 1) { /* Monochrome colormap. */ image->colormap[0].red=(Quantum) 0; image->colormap[0].green=(Quantum) 0; image->colormap[0].blue=(Quantum) 0; image->colormap[1].red=QuantumRange; image->colormap[1].green=QuantumRange; image->colormap[1].blue=QuantumRange; } else if (image->colors > 16) { /* 256 color images have their color map at the end of the file. */ pcx_info.colormap_signature=(unsigned char) ReadBlobByte(image); count=ReadBlob(image,3*image->colors,pcx_colormap); p=pcx_colormap; for (i=0; i < (ssize_t) image->colors; i++) { image->colormap[i].red=ScaleCharToQuantum(*p++); image->colormap[i].green=ScaleCharToQuantum(*p++); image->colormap[i].blue=ScaleCharToQuantum(*p++); } } } /* Convert PCX raster image to pixel packets. */ for (y=0; y < (ssize_t) image->rows; y++) { p=pixels+(y*pcx_info.bytes_per_line*pcx_info.planes); q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; r=scanline; if (image->storage_class == DirectClass) for (i=0; i < pcx_info.planes; i++) { r=scanline+i; for (x=0; x < (ssize_t) pcx_info.bytes_per_line; x++) { switch (i) { case 0: { *r=(*p++); break; } case 1: { *r=(*p++); break; } case 2: { *r=(*p++); break; } case 3: default: { *r=(*p++); break; } } r+=pcx_info.planes; } } else if (pcx_info.planes > 1) { for (x=0; x < (ssize_t) image->columns; x++) *r++=0; for (i=0; i < pcx_info.planes; i++) { r=scanline; for (x=0; x < (ssize_t) pcx_info.bytes_per_line; x++) { bits=(*p++); for (mask=0x80; mask != 0; mask>>=1) { if (bits & mask) *r|=1 << i; r++; } } } } else switch (pcx_info.bits_per_pixel) { case 1: { register ssize_t bit; for (x=0; x < ((ssize_t) image->columns-7); x+=8) { for (bit=7; bit >= 0; bit--) *r++=(unsigned char) ((*p) & (0x01 << bit) ? 0x01 : 0x00); p++; } if ((image->columns % 8) != 0) { for (bit=7; bit >= (ssize_t) (8-(image->columns % 8)); bit--) *r++=(unsigned char) ((*p) & (0x01 << bit) ? 0x01 : 0x00); p++; } break; } case 2: { for (x=0; x < ((ssize_t) image->columns-3); x+=4) { *r++=(*p >> 6) & 0x3; *r++=(*p >> 4) & 0x3; *r++=(*p >> 2) & 0x3; *r++=(*p) & 0x3; p++; } if ((image->columns % 4) != 0) { for (i=3; i >= (ssize_t) (4-(image->columns % 4)); i--) *r++=(unsigned char) ((*p >> (i*2)) & 0x03); p++; } break; } case 4: { for (x=0; x < ((ssize_t) image->columns-1); x+=2) { *r++=(*p >> 4) & 0xf; *r++=(*p) & 0xf; p++; } if ((image->columns % 2) != 0) *r++=(*p++ >> 4) & 0xf; break; } case 8: { (void) CopyMagickMemory(r,p,image->columns); break; } default: break; } /* Transfer image scanline. */ r=scanline; for (x=0; x < (ssize_t) image->columns; x++) { if (image->storage_class == PseudoClass) SetPixelIndex(image,*r++,q); else { SetPixelRed(image,ScaleCharToQuantum(*r++),q); SetPixelGreen(image,ScaleCharToQuantum(*r++),q); SetPixelBlue(image,ScaleCharToQuantum(*r++),q); if (image->alpha_trait != UndefinedPixelTrait) SetPixelAlpha(image,ScaleCharToQuantum(*r++),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; } } if (image->storage_class == PseudoClass) (void) SyncImage(image,exception); scanline=(unsigned char *) RelinquishMagickMemory(scanline); pixel_info=RelinquishVirtualMemory(pixel_info); 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 (page_table == (MagickOffsetType *) NULL) break; if (page_table[id] == 0) break; offset=SeekBlob(image,(MagickOffsetType) page_table[id],SEEK_SET); if (offset < 0) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); count=ReadBlob(image,1,&pcx_info.identifier); if ((count != 0) && (pcx_info.identifier == 0x0a)) { /* 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; } }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % 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; MemoryInfo *pixel_info; PangoAlignment align; PangoContext *context; PangoFontDescription *description; 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=GetImageOption(image_info,"filename"); if (option == (const char *) NULL) property=InterpretImageProperties((ImageInfo *) image_info,image, image_info->filename,exception); else if (LocaleNCompare(option,"pango:",6) == 0) property=InterpretImageProperties((ImageInfo *) image_info,image,option+6, exception); else property=InterpretImageProperties((ImageInfo *) 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=GetImageOption(image_info,"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=GetImageOption(image_info,"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=GetImageOption(image_info,"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=GetImageOption(image_info,"pango:auto-dir"); if (option != (const char *) NULL) pango_layout_set_auto_dir(layout,1); option=GetImageOption(image_info,"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=GetImageOption(image_info,"pango:justify"); if (IfMagickTrue(IsStringTrue(option))) pango_layout_set_justify(layout,1); option=GetImageOption(image_info,"pango:single-paragraph"); if (IfMagickTrue(IsStringTrue(option))) pango_layout_set_single_paragraph_mode(layout,1); option=GetImageOption(image_info,"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=GetImageOption(image_info,"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) description=pango_font_description_new(); else 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=GetImageOption(image_info,"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)); } status=SetImageExtent(image,image->columns,image->rows,exception); if (status == MagickFalse) return(DestroyImageList(image)); /* Render markup. */ stride=(size_t) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, (int) image->columns); pixel_info=AcquireVirtualMemory(image->rows,stride*sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) { draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); surface=cairo_image_surface_create_for_data(pixels,CAIRO_FORMAT_ARGB32, (int) image->columns,(int) image->rows,(int) 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); cairo_set_source_rgba(cairo_image,QuantumScale*draw_info->fill.red, QuantumScale*draw_info->fill.green,QuantumScale*draw_info->fill.blue, QuantumScale*draw_info->fill.alpha); 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=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. */ pixel_info=RelinquishVirtualMemory(pixel_info); draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e A V S I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteAVSImage() writes an image to a file in AVS X image format. % % The format of the WriteAVSImage method is: % % MagickBooleanType WriteAVSImage(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 WriteAVSImage(const ImageInfo *image_info,Image *image, ExceptionInfo *exception) { MagickBooleanType status; MagickOffsetType scene; MemoryInfo *pixel_info; register const Quantum *magick_restrict p; register ssize_t x; register unsigned char *magick_restrict q; ssize_t count, y; unsigned char *pixels; /* 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); scene=0; do { /* Write AVS header. */ (void) TransformImageColorspace(image,sRGBColorspace,exception); (void) WriteBlobMSBLong(image,(unsigned int) image->columns); (void) WriteBlobMSBLong(image,(unsigned int) image->rows); /* Allocate memory for pixels. */ pixel_info=AcquireVirtualMemory(image->columns,4*sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); /* Convert MIFF to AVS raster pixels. */ for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) break; q=pixels; for (x=0; x < (ssize_t) image->columns; x++) { *q++=ScaleQuantumToChar((Quantum) (image->alpha_trait == BlendPixelTrait ? GetPixelAlpha(image,p) : OpaqueAlpha)); *q++=ScaleQuantumToChar(GetPixelRed(image,p)); *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); p+=GetPixelChannels(image); } count=WriteBlob(image,(size_t) (q-pixels),pixels); if (count != (ssize_t) (q-pixels)) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } pixel_info=RelinquishVirtualMemory(pixel_info); 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); }
static MagickBooleanType WriteSGIImage(const ImageInfo *image_info,Image *image) { CompressionType compression; const char *value; MagickBooleanType status; MagickOffsetType scene; MagickSizeType number_pixels; MemoryInfo *pixel_info; SGIInfo iris_info; register const PixelPacket *p; register ssize_t i, x; register unsigned char *q; ssize_t y, z; unsigned char *pixels, *packets; /* 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); if ((image->columns > 65535UL) || (image->rows > 65535UL)) ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == MagickFalse) return(status); scene=0; do { /* Initialize SGI raster file header. */ (void) TransformImageColorspace(image,sRGBColorspace); (void) ResetMagickMemory(&iris_info,0,sizeof(iris_info)); iris_info.magic=0x01DA; compression=image->compression; if (image_info->compression != UndefinedCompression) compression=image_info->compression; if (image->depth > 8) compression=NoCompression; if (compression == NoCompression) iris_info.storage=(unsigned char) 0x00; else iris_info.storage=(unsigned char) 0x01; iris_info.bytes_per_pixel=(unsigned char) (image->depth > 8 ? 2 : 1); iris_info.dimension=3; iris_info.columns=(unsigned short) image->columns; iris_info.rows=(unsigned short) image->rows; if (image->matte != MagickFalse) iris_info.depth=4; else { if ((image_info->type != TrueColorType) && (SetImageGray(image,&image->exception) != MagickFalse)) { iris_info.dimension=2; iris_info.depth=1; } else iris_info.depth=3; } iris_info.minimum_value=0; iris_info.maximum_value=(size_t) (image->depth <= 8 ? 1UL*ScaleQuantumToChar(QuantumRange) : 1UL*ScaleQuantumToShort(QuantumRange)); /* Write SGI header. */ (void) WriteBlobMSBShort(image,iris_info.magic); (void) WriteBlobByte(image,iris_info.storage); (void) WriteBlobByte(image,iris_info.bytes_per_pixel); (void) WriteBlobMSBShort(image,iris_info.dimension); (void) WriteBlobMSBShort(image,iris_info.columns); (void) WriteBlobMSBShort(image,iris_info.rows); (void) WriteBlobMSBShort(image,iris_info.depth); (void) WriteBlobMSBLong(image,(unsigned int) iris_info.minimum_value); (void) WriteBlobMSBLong(image,(unsigned int) iris_info.maximum_value); (void) WriteBlobMSBLong(image,(unsigned int) iris_info.sans); value=GetImageProperty(image,"label"); if (value != (const char *) NULL) (void) CopyMagickString(iris_info.name,value,sizeof(iris_info.name)); (void) WriteBlob(image,sizeof(iris_info.name),(unsigned char *) iris_info.name); (void) WriteBlobMSBLong(image,(unsigned int) iris_info.pixel_format); (void) WriteBlob(image,sizeof(iris_info.filler),iris_info.filler); /* Allocate SGI pixels. */ number_pixels=(MagickSizeType) image->columns*image->rows; if ((4*iris_info.bytes_per_pixel*number_pixels) != ((MagickSizeType) (size_t) (4*iris_info.bytes_per_pixel*number_pixels))) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); pixel_info=AcquireVirtualMemory((size_t) number_pixels,4* iris_info.bytes_per_pixel*sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); /* Convert image pixels to uncompressed SGI pixels. */ for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; if (image->depth <= 8) for (x=0; x < (ssize_t) image->columns; x++) { register unsigned char *q; q=(unsigned char *) pixels; q+=((iris_info.rows-1)-y)*(4*iris_info.columns)+4*x; *q++=ScaleQuantumToChar(GetPixelRed(p)); *q++=ScaleQuantumToChar(GetPixelGreen(p)); *q++=ScaleQuantumToChar(GetPixelBlue(p)); *q++=ScaleQuantumToChar(GetPixelAlpha(p)); p++; } else for (x=0; x < (ssize_t) image->columns; x++) { register unsigned short *q; q=(unsigned short *) pixels; q+=((iris_info.rows-1)-y)*(4*iris_info.columns)+4*x; *q++=ScaleQuantumToShort(GetPixelRed(p)); *q++=ScaleQuantumToShort(GetPixelGreen(p)); *q++=ScaleQuantumToShort(GetPixelBlue(p)); *q++=ScaleQuantumToShort(GetPixelAlpha(p)); p++; } if (image->previous == (Image *) NULL) { status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } switch (compression) { case NoCompression: { /* Write uncompressed SGI pixels. */ for (z=0; z < (ssize_t) iris_info.depth; z++) { for (y=0; y < (ssize_t) iris_info.rows; y++) { if (image->depth <= 8) for (x=0; x < (ssize_t) iris_info.columns; x++) { register unsigned char *q; q=(unsigned char *) pixels; q+=y*(4*iris_info.columns)+4*x+z; (void) WriteBlobByte(image,*q); } else for (x=0; x < (ssize_t) iris_info.columns; x++) { register unsigned short *q; q=(unsigned short *) pixels; q+=y*(4*iris_info.columns)+4*x+z; (void) WriteBlobMSBShort(image,*q); } } } break; } default: { MemoryInfo *packet_info; size_t length, number_packets, *runlength; ssize_t offset, *offsets; /* Convert SGI uncompressed pixels. */ offsets=(ssize_t *) AcquireQuantumMemory(iris_info.rows, iris_info.depth*sizeof(*offsets)); runlength=(size_t *) AcquireQuantumMemory(iris_info.rows, iris_info.depth*sizeof(*runlength)); packet_info=AcquireVirtualMemory((2*(size_t) iris_info.columns+10)* image->rows,4*sizeof(*packets)); if ((offsets == (ssize_t *) NULL) || (runlength == (size_t *) NULL) || (packet_info == (MemoryInfo *) NULL)) { if (offsets != (ssize_t *) NULL) offsets=(ssize_t *) RelinquishMagickMemory(offsets); if (runlength != (size_t *) NULL) runlength=(size_t *) RelinquishMagickMemory(runlength); if (packet_info != (MemoryInfo *) NULL) packet_info=RelinquishVirtualMemory(packet_info); ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); } packets=(unsigned char *) GetVirtualMemoryBlob(packet_info); offset=512+4*2*((ssize_t) iris_info.rows*iris_info.depth); number_packets=0; q=pixels; for (y=0; y < (ssize_t) iris_info.rows; y++) { for (z=0; z < (ssize_t) iris_info.depth; z++) { length=SGIEncode(q+z,(size_t) iris_info.columns,packets+ number_packets); number_packets+=length; offsets[y+z*iris_info.rows]=offset; runlength[y+z*iris_info.rows]=(size_t) length; offset+=(ssize_t) length; } q+=(iris_info.columns*4); } /* Write out line start and length tables and runlength-encoded pixels. */ for (i=0; i < (ssize_t) (iris_info.rows*iris_info.depth); i++) (void) WriteBlobMSBLong(image,(unsigned int) offsets[i]); for (i=0; i < (ssize_t) (iris_info.rows*iris_info.depth); i++) (void) WriteBlobMSBLong(image,(unsigned int) runlength[i]); (void) WriteBlob(image,number_packets,packets); /* Relinquish resources. */ offsets=(ssize_t *) RelinquishMagickMemory(offsets); runlength=(size_t *) RelinquishMagickMemory(runlength); packet_info=RelinquishVirtualMemory(packet_info); break; } } pixel_info=RelinquishVirtualMemory(pixel_info); 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); }
static Image *ReadSGIImage(const ImageInfo *image_info,ExceptionInfo *exception) { Image *image; MagickBooleanType status; MagickSizeType number_pixels; MemoryInfo *pixel_info; register IndexPacket *indexes; register PixelPacket *q; register ssize_t i, x; register unsigned char *p; SGIInfo iris_info; size_t bytes_per_pixel, quantum; ssize_t count, y, z; unsigned char *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); } /* Read SGI raster header. */ iris_info.magic=ReadBlobMSBShort(image); do { /* Verify SGI identifier. */ if (iris_info.magic != 0x01DA) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); iris_info.storage=(unsigned char) ReadBlobByte(image); switch (iris_info.storage) { case 0x00: image->compression=NoCompression; break; case 0x01: image->compression=RLECompression; break; default: ThrowReaderException(CorruptImageError,"ImproperImageHeader"); } iris_info.bytes_per_pixel=(unsigned char) ReadBlobByte(image); if ((iris_info.bytes_per_pixel == 0) || (iris_info.bytes_per_pixel > 2)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); iris_info.dimension=ReadBlobMSBShort(image); iris_info.columns=ReadBlobMSBShort(image); iris_info.rows=ReadBlobMSBShort(image); iris_info.depth=ReadBlobMSBShort(image); if ((iris_info.depth == 0) || (iris_info.depth > 4)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); iris_info.minimum_value=ReadBlobMSBLong(image); iris_info.maximum_value=ReadBlobMSBLong(image); iris_info.sans=ReadBlobMSBLong(image); (void) ReadBlob(image,sizeof(iris_info.name),(unsigned char *) iris_info.name); iris_info.name[sizeof(iris_info.name)-1]='\0'; if (*iris_info.name != '\0') (void) SetImageProperty(image,"label",iris_info.name); iris_info.pixel_format=ReadBlobMSBLong(image); if (iris_info.pixel_format != 0) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); count=ReadBlob(image,sizeof(iris_info.filler),iris_info.filler); (void) count; image->columns=iris_info.columns; image->rows=iris_info.rows; image->depth=(size_t) MagickMin(iris_info.depth,MAGICKCORE_QUANTUM_DEPTH); if (iris_info.pixel_format == 0) image->depth=(size_t) MagickMin((size_t) 8* iris_info.bytes_per_pixel,MAGICKCORE_QUANTUM_DEPTH); if (iris_info.depth < 3) { image->storage_class=PseudoClass; image->colors=iris_info.bytes_per_pixel > 1 ? 65535 : 256; } if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) if (image->scene >= (image_info->scene+image_info->number_scenes-1)) break; status=SetImageExtent(image,image->columns,image->rows); if (status == MagickFalse) { InheritException(exception,&image->exception); return(DestroyImageList(image)); } /* Allocate SGI pixels. */ bytes_per_pixel=(size_t) iris_info.bytes_per_pixel; number_pixels=(MagickSizeType) iris_info.columns*iris_info.rows; if ((4*bytes_per_pixel*number_pixels) != ((MagickSizeType) (size_t) (4*bytes_per_pixel*number_pixels))) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); pixel_info=AcquireVirtualMemory(iris_info.columns,iris_info.rows*4* bytes_per_pixel*sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); if ((int) iris_info.storage != 0x01) { unsigned char *scanline; /* Read standard image format. */ scanline=(unsigned char *) AcquireQuantumMemory(iris_info.columns, bytes_per_pixel*sizeof(*scanline)); if (scanline == (unsigned char *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); for (z=0; z < (ssize_t) iris_info.depth; z++) { p=pixels+bytes_per_pixel*z; for (y=0; y < (ssize_t) iris_info.rows; y++) { count=ReadBlob(image,bytes_per_pixel*iris_info.columns,scanline); if (EOFBlob(image) != MagickFalse) break; if (bytes_per_pixel == 2) for (x=0; x < (ssize_t) iris_info.columns; x++) { *p=scanline[2*x]; *(p+1)=scanline[2*x+1]; p+=8; } else for (x=0; x < (ssize_t) iris_info.columns; x++) { *p=scanline[x]; p+=4; } } } scanline=(unsigned char *) RelinquishMagickMemory(scanline); } else { MemoryInfo *packet_info; size_t *runlength; ssize_t offset, *offsets; unsigned char *packets; unsigned int data_order; /* Read runlength-encoded image format. */ offsets=(ssize_t *) AcquireQuantumMemory((size_t) iris_info.rows, iris_info.depth*sizeof(*offsets)); runlength=(size_t *) AcquireQuantumMemory(iris_info.rows, iris_info.depth*sizeof(*runlength)); packet_info=AcquireVirtualMemory((size_t) iris_info.columns+10UL,4UL* sizeof(*packets)); if ((offsets == (ssize_t *) NULL) || (runlength == (size_t *) NULL) || (packet_info == (MemoryInfo *) NULL)) { if (offsets == (ssize_t *) NULL) offsets=(ssize_t *) RelinquishMagickMemory(offsets); if (runlength == (size_t *) NULL) runlength=(size_t *) RelinquishMagickMemory(runlength); if (packet_info == (MemoryInfo *) NULL) packet_info=RelinquishVirtualMemory(packet_info); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } packets=(unsigned char *) GetVirtualMemoryBlob(packet_info); for (i=0; i < (ssize_t) (iris_info.rows*iris_info.depth); i++) offsets[i]=(int) ReadBlobMSBLong(image); for (i=0; i < (ssize_t) (iris_info.rows*iris_info.depth); i++) { runlength[i]=ReadBlobMSBLong(image); if (runlength[i] > (4*(size_t) iris_info.columns+10)) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); } /* Check data order. */ offset=0; data_order=0; for (y=0; ((y < (ssize_t) iris_info.rows) && (data_order == 0)); y++) for (z=0; ((z < (ssize_t) iris_info.depth) && (data_order == 0)); z++) { if (offsets[y+z*iris_info.rows] < offset) data_order=1; offset=offsets[y+z*iris_info.rows]; } offset=(ssize_t) TellBlob(image); if (data_order == 1) { for (z=0; z < (ssize_t) iris_info.depth; z++) { p=pixels; for (y=0; y < (ssize_t) iris_info.rows; y++) { if (offset != offsets[y+z*iris_info.rows]) { offset=offsets[y+z*iris_info.rows]; offset=(ssize_t) SeekBlob(image,(ssize_t) offset,SEEK_SET); } count=ReadBlob(image,(size_t) runlength[y+z*iris_info.rows], packets); if (EOFBlob(image) != MagickFalse) break; offset+=(ssize_t) runlength[y+z*iris_info.rows]; status=SGIDecode(bytes_per_pixel,(ssize_t) (runlength[y+z*iris_info.rows]/bytes_per_pixel),packets, 1L*iris_info.columns,p+bytes_per_pixel*z); if (status == MagickFalse) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); p+=(iris_info.columns*4*bytes_per_pixel); } } } else { MagickOffsetType position; position=TellBlob(image); p=pixels; for (y=0; y < (ssize_t) iris_info.rows; y++) { for (z=0; z < (ssize_t) iris_info.depth; z++) { if (offset != offsets[y+z*iris_info.rows]) { offset=offsets[y+z*iris_info.rows]; offset=(ssize_t) SeekBlob(image,(ssize_t) offset,SEEK_SET); } count=ReadBlob(image,(size_t) runlength[y+z*iris_info.rows], packets); if (EOFBlob(image) != MagickFalse) break; offset+=(ssize_t) runlength[y+z*iris_info.rows]; status=SGIDecode(bytes_per_pixel,(ssize_t) (runlength[y+z*iris_info.rows]/bytes_per_pixel),packets, 1L*iris_info.columns,p+bytes_per_pixel*z); if (status == MagickFalse) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); } p+=(iris_info.columns*4*bytes_per_pixel); } offset=(ssize_t) SeekBlob(image,position,SEEK_SET); } packet_info=RelinquishVirtualMemory(packet_info); runlength=(size_t *) RelinquishMagickMemory(runlength); offsets=(ssize_t *) RelinquishMagickMemory(offsets); } /* Initialize image structure. */ image->matte=iris_info.depth == 4 ? MagickTrue : MagickFalse; image->columns=iris_info.columns; image->rows=iris_info.rows; /* Convert SGI raster image to pixel packets. */ if (image->storage_class == DirectClass) { /* Convert SGI image to DirectClass pixel packets. */ if (bytes_per_pixel == 2) { for (y=0; y < (ssize_t) image->rows; y++) { p=pixels+(image->rows-y-1)*8*image->columns; 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,ScaleShortToQuantum((unsigned short) ((*(p+0) << 8) | (*(p+1))))); SetPixelGreen(q,ScaleShortToQuantum((unsigned short) ((*(p+2) << 8) | (*(p+3))))); SetPixelBlue(q,ScaleShortToQuantum((unsigned short) ((*(p+4) << 8) | (*(p+5))))); SetPixelOpacity(q,OpaqueOpacity); if (image->matte != MagickFalse) SetPixelAlpha(q,ScaleShortToQuantum((unsigned short) ((*(p+6) << 8) | (*(p+7))))); p+=8; 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 for (y=0; y < (ssize_t) image->rows; y++) { p=pixels+(image->rows-y-1)*4*image->columns; 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)); q->green=ScaleCharToQuantum(*(p+1)); q->blue=ScaleCharToQuantum(*(p+2)); SetPixelOpacity(q,OpaqueOpacity); if (image->matte != MagickFalse) SetPixelAlpha(q,ScaleCharToQuantum(*(p+3))); p+=4; 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 grayscale map. */ if (AcquireImageColormap(image,image->colors) == MagickFalse) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); /* Convert SGI image to PseudoClass pixel packets. */ if (bytes_per_pixel == 2) { for (y=0; y < (ssize_t) image->rows; y++) { p=pixels+(image->rows-y-1)*8*image->columns; 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++) { quantum=(*p << 8); quantum|=(*(p+1)); SetPixelIndex(indexes+x,quantum); p+=8; 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 for (y=0; y < (ssize_t) image->rows; y++) { p=pixels+(image->rows-y-1)*4*image->columns; 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); p+=4; q++; } 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); } pixel_info=RelinquishVirtualMemory(pixel_info); 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; iris_info.magic=ReadBlobMSBShort(image); if (iris_info.magic == 0x01DA) { /* 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 (iris_info.magic == 0x01DA); (void) CloseBlob(image); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % 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 WritePS2Image(const ImageInfo *image_info,Image *image, ExceptionInfo *exception) { static const char *const PostscriptProlog[]= { "%%%%BeginProlog", "%%", "%% Display a color image. The image is displayed in color on", "%% Postscript viewers or printers that support color, otherwise", "%% it is displayed as grayscale.", "%%", "/DirectClassImage", "{", " %%", " %% Display a DirectClass image.", " %%", " colorspace 0 eq", " {", " /DeviceRGB setcolorspace", " <<", " /ImageType 1", " /Width columns", " /Height rows", " /BitsPerComponent 8", " /Decode [0 1 0 1 0 1]", " /ImageMatrix [columns 0 0 rows neg 0 rows]", " compression 0 gt", " { /DataSource pixel_stream %s }", " { /DataSource pixel_stream %s } ifelse", " >> image", " }", " {", " /DeviceCMYK setcolorspace", " <<", " /ImageType 1", " /Width columns", " /Height rows", " /BitsPerComponent 8", " /Decode [1 0 1 0 1 0 1 0]", " /ImageMatrix [columns 0 0 rows neg 0 rows]", " compression 0 gt", " { /DataSource pixel_stream %s }", " { /DataSource pixel_stream %s } ifelse", " >> image", " } ifelse", "} bind def", "", "/PseudoClassImage", "{", " %%", " %% Display a PseudoClass image.", " %%", " %% Parameters:", " %% colors: number of colors in the colormap.", " %%", " currentfile buffer readline pop", " token pop /colors exch def pop", " colors 0 eq", " {", " %%", " %% Image is grayscale.", " %%", " currentfile buffer readline pop", " token pop /bits exch def pop", " /DeviceGray setcolorspace", " <<", " /ImageType 1", " /Width columns", " /Height rows", " /BitsPerComponent bits", " /Decode [0 1]", " /ImageMatrix [columns 0 0 rows neg 0 rows]", " compression 0 gt", " { /DataSource pixel_stream %s }", " {", " /DataSource pixel_stream %s", " <<", " /K "CCITTParam, " /Columns columns", " /Rows rows", " >> /CCITTFaxDecode filter", " } ifelse", " >> image", " }", " {", " %%", " %% Parameters:", " %% colormap: red, green, blue color packets.", " %%", " /colormap colors 3 mul string def", " currentfile colormap readhexstring pop pop", " currentfile buffer readline pop", " [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace", " <<", " /ImageType 1", " /Width columns", " /Height rows", " /BitsPerComponent 8", " /Decode [0 255]", " /ImageMatrix [columns 0 0 rows neg 0 rows]", " compression 0 gt", " { /DataSource pixel_stream %s }", " { /DataSource pixel_stream %s } ifelse", " >> image", " } ifelse", "} bind def", "", "/DisplayImage", "{", " %%", " %% Display a DirectClass or PseudoClass image.", " %%", " %% Parameters:", " %% x & y translation.", " %% x & y scale.", " %% label pointsize.", " %% image label.", " %% image columns & rows.", " %% class: 0-DirectClass or 1-PseudoClass.", " %% colorspace: 0-RGB or 1-CMYK.", " %% compression: 0-RLECompression or 1-NoCompression.", " %% hex color packets.", " %%", " gsave", " /buffer 512 string def", " /pixel_stream currentfile def", "", " currentfile buffer readline pop", " token pop /x exch def", " token pop /y exch def pop", " x y translate", " currentfile buffer readline pop", " token pop /x exch def", " token pop /y exch def pop", " currentfile buffer readline pop", " token pop /pointsize exch def pop", " /Helvetica findfont pointsize scalefont setfont", (const char *) NULL }, *const PostscriptEpilog[]= { " x y scale", " currentfile buffer readline pop", " token pop /columns exch def", " token pop /rows exch def pop", " currentfile buffer readline pop", " token pop /class exch def pop", " currentfile buffer readline pop", " token pop /colorspace exch def pop", " currentfile buffer readline pop", " token pop /compression exch def pop", " class 0 gt { PseudoClassImage } { DirectClassImage } ifelse", " grestore", (const char *) NULL }; char buffer[MagickPathExtent], date[MagickPathExtent], page_geometry[MagickPathExtent], **labels; CompressionType compression; const char *const *q, *value; double pointsize; GeometryInfo geometry_info; MagickOffsetType scene, start, stop; MagickBooleanType progress, status; MagickOffsetType offset; MagickSizeType number_pixels; MagickStatusType flags; PointInfo delta, resolution, scale; RectangleInfo geometry, media_info, page_info; register const Quantum *p; register ssize_t x; register ssize_t i; SegmentInfo bounds; size_t length, page, text_size; ssize_t j, y; time_t timer; unsigned char *pixels; /* Open output image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == 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); compression=image->compression; if (image_info->compression != UndefinedCompression) compression=image_info->compression; switch (compression) { #if !defined(MAGICKCORE_JPEG_DELEGATE) case JPEGCompression: { compression=RLECompression; (void) ThrowMagickException(exception,GetMagickModule(), MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)", image->filename); break; } #endif default: break; } (void) ResetMagickMemory(&bounds,0,sizeof(bounds)); page=1; scene=0; do { /* Scale relative to dots-per-inch. */ delta.x=DefaultResolution; delta.y=DefaultResolution; resolution.x=image->resolution.x; resolution.y=image->resolution.y; if ((resolution.x == 0.0) || (resolution.y == 0.0)) { flags=ParseGeometry(PSDensityGeometry,&geometry_info); resolution.x=geometry_info.rho; resolution.y=geometry_info.sigma; if ((flags & SigmaValue) == 0) resolution.y=resolution.x; } if (image_info->density != (char *) NULL) { flags=ParseGeometry(image_info->density,&geometry_info); resolution.x=geometry_info.rho; resolution.y=geometry_info.sigma; if ((flags & SigmaValue) == 0) resolution.y=resolution.x; } if (image->units == PixelsPerCentimeterResolution) { resolution.x=(size_t) (100.0*2.54*resolution.x+0.5)/100.0; resolution.y=(size_t) (100.0*2.54*resolution.y+0.5)/100.0; } SetGeometry(image,&geometry); (void) FormatLocaleString(page_geometry,MagickPathExtent,"%.20gx%.20g", (double) image->columns,(double) image->rows); if (image_info->page != (char *) NULL) (void) CopyMagickString(page_geometry,image_info->page,MagickPathExtent); else if ((image->page.width != 0) && (image->page.height != 0)) (void) FormatLocaleString(page_geometry,MagickPathExtent, "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,(double) image->page.height,(double) image->page.x,(double) image->page.y); else if ((image->gravity != UndefinedGravity) && (LocaleCompare(image_info->magick,"PS") == 0)) (void) CopyMagickString(page_geometry,PSPageGeometry,MagickPathExtent); (void) ConcatenateMagickString(page_geometry,">",MagickPathExtent); (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y, &geometry.width,&geometry.height); scale.x=(double) (geometry.width*delta.x)/resolution.x; geometry.width=(size_t) floor(scale.x+0.5); scale.y=(double) (geometry.height*delta.y)/resolution.y; geometry.height=(size_t) floor(scale.y+0.5); (void) ParseAbsoluteGeometry(page_geometry,&media_info); (void) ParseGravityGeometry(image,page_geometry,&page_info,exception); if (image->gravity != UndefinedGravity) { geometry.x=(-page_info.x); geometry.y=(ssize_t) (media_info.height+page_info.y-image->rows); } pointsize=12.0; if (image_info->pointsize != 0.0) pointsize=image_info->pointsize; text_size=0; value=GetImageProperty(image,"label",exception); if (value != (const char *) NULL) text_size=(size_t) (MultilineCensus(value)*pointsize+12); if (page == 1) { /* Output Postscript header. */ if (LocaleCompare(image_info->magick,"PS2") == 0) (void) CopyMagickString(buffer,"%!PS-Adobe-3.0\n",MagickPathExtent); else (void) CopyMagickString(buffer,"%!PS-Adobe-3.0 EPSF-3.0\n", MagickPathExtent); (void) WriteBlobString(image,buffer); (void) WriteBlobString(image,"%%Creator: (ImageMagick)\n"); (void) FormatLocaleString(buffer,MagickPathExtent,"%%%%Title: (%s)\n", image->filename); (void) WriteBlobString(image,buffer); timer=time((time_t *) NULL); (void) FormatMagickTime(timer,MagickPathExtent,date); (void) FormatLocaleString(buffer,MagickPathExtent, "%%%%CreationDate: (%s)\n",date); (void) WriteBlobString(image,buffer); bounds.x1=(double) geometry.x; bounds.y1=(double) geometry.y; bounds.x2=(double) geometry.x+geometry.width; bounds.y2=(double) geometry.y+geometry.height+text_size; if ((image_info->adjoin != MagickFalse) && (GetNextImageInList(image) != (Image *) NULL)) (void) CopyMagickString(buffer,"%%BoundingBox: (atend)\n", MagickPathExtent); else { (void) FormatLocaleString(buffer,MagickPathExtent, "%%%%BoundingBox: %.20g %.20g %.20g %.20g\n",ceil(bounds.x1-0.5), ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent, "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1, bounds.y1,bounds.x2,bounds.y2); } (void) WriteBlobString(image,buffer); value=GetImageProperty(image,"label",exception); if (value != (const char *) NULL) (void) WriteBlobString(image, "%%DocumentNeededResources: font Helvetica\n"); (void) WriteBlobString(image,"%%LanguageLevel: 2\n"); if (LocaleCompare(image_info->magick,"PS2") != 0) (void) WriteBlobString(image,"%%Pages: 1\n"); else { (void) WriteBlobString(image,"%%Orientation: Portrait\n"); (void) WriteBlobString(image,"%%PageOrder: Ascend\n"); if (image_info->adjoin == MagickFalse) (void) CopyMagickString(buffer,"%%Pages: 1\n",MagickPathExtent); else (void) FormatLocaleString(buffer,MagickPathExtent, "%%%%Pages: %.20g\n",(double) GetImageListLength(image)); (void) WriteBlobString(image,buffer); } if (image->colorspace == CMYKColorspace) (void) WriteBlobString(image, "%%DocumentProcessColors: Cyan Magenta Yellow Black\n"); (void) WriteBlobString(image,"%%EndComments\n"); (void) WriteBlobString(image,"\n%%BeginDefaults\n"); (void) WriteBlobString(image,"%%EndDefaults\n\n"); /* Output Postscript commands. */ for (q=PostscriptProlog; *q; q++) { switch (compression) { case NoCompression: { (void) FormatLocaleString(buffer,MagickPathExtent,*q, "/ASCII85Decode filter"); break; } case JPEGCompression: { (void) FormatLocaleString(buffer,MagickPathExtent,*q, "/DCTDecode filter"); break; } case LZWCompression: { (void) FormatLocaleString(buffer,MagickPathExtent,*q, "/LZWDecode filter"); break; } case FaxCompression: case Group4Compression: { (void) FormatLocaleString(buffer,MagickPathExtent,*q," "); break; } default: { (void) FormatLocaleString(buffer,MagickPathExtent,*q, "/RunLengthDecode filter"); break; } } (void) WriteBlobString(image,buffer); (void) WriteBlobByte(image,'\n'); } value=GetImageProperty(image,"label",exception); if (value != (const char *) NULL) for (j=(ssize_t) MultilineCensus(value)-1; j >= 0; j--) { (void) WriteBlobString(image," /label 512 string def\n"); (void) WriteBlobString(image," currentfile label readline pop\n"); (void) FormatLocaleString(buffer,MagickPathExtent, " 0 y %g add moveto label show pop\n",j*pointsize+12); (void) WriteBlobString(image,buffer); } for (q=PostscriptEpilog; *q; q++) { (void) FormatLocaleString(buffer,MagickPathExtent,"%s\n",*q); (void) WriteBlobString(image,buffer); } if (LocaleCompare(image_info->magick,"PS2") == 0) (void) WriteBlobString(image," showpage\n"); (void) WriteBlobString(image,"} bind def\n"); (void) WriteBlobString(image,"%%EndProlog\n"); } (void) FormatLocaleString(buffer,MagickPathExtent,"%%%%Page: 1 %.20g\n", (double) page++); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent, "%%%%PageBoundingBox: %.20g %.20g %.20g %.20g\n",(double) geometry.x, (double) geometry.y,geometry.x+(double) geometry.width,geometry.y+(double) (geometry.height+text_size)); (void) WriteBlobString(image,buffer); if ((double) geometry.x < bounds.x1) bounds.x1=(double) geometry.x; if ((double) geometry.y < bounds.y1) bounds.y1=(double) geometry.y; if ((double) (geometry.x+geometry.width-1) > bounds.x2) bounds.x2=(double) geometry.x+geometry.width-1; if ((double) (geometry.y+(geometry.height+text_size)-1) > bounds.y2) bounds.y2=(double) geometry.y+(geometry.height+text_size)-1; value=GetImageProperty(image,"label",exception); if (value != (const char *) NULL) (void) WriteBlobString(image,"%%PageResources: font Times-Roman\n"); if (LocaleCompare(image_info->magick,"PS2") != 0) (void) WriteBlobString(image,"userdict begin\n"); start=TellBlob(image); (void) FormatLocaleString(buffer,MagickPathExtent, "%%%%BeginData:%13ld %s Bytes\n",0L, compression == NoCompression ? "ASCII" : "Binary"); (void) WriteBlobString(image,buffer); stop=TellBlob(image); (void) WriteBlobString(image,"DisplayImage\n"); /* Output image data. */ (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g\n%g %g\n%g\n", (double) geometry.x,(double) geometry.y,scale.x,scale.y,pointsize); (void) WriteBlobString(image,buffer); labels=(char **) NULL; value=GetImageProperty(image,"label",exception); if (value != (const char *) NULL) labels=StringToList(value); if (labels != (char **) NULL) { for (i=0; labels[i] != (char *) NULL; i++) { (void) FormatLocaleString(buffer,MagickPathExtent,"%s \n", labels[i]); (void) WriteBlobString(image,buffer); labels[i]=DestroyString(labels[i]); } labels=(char **) RelinquishMagickMemory(labels); } number_pixels=(MagickSizeType) image->columns*image->rows; if (number_pixels != (MagickSizeType) ((size_t) number_pixels)) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); if ((compression == FaxCompression) || (compression == Group4Compression) || ((image_info->type != TrueColorType) && (SetImageGray(image,exception) != MagickFalse))) { (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g\n1\n%d\n", (double) image->columns,(double) image->rows,(int) (image->colorspace == CMYKColorspace)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent,"%d\n", (int) ((compression != FaxCompression) && (compression != Group4Compression))); (void) WriteBlobString(image,buffer); (void) WriteBlobString(image,"0\n"); (void) FormatLocaleString(buffer,MagickPathExtent,"%d\n", (compression == FaxCompression) || (compression == Group4Compression) ? 1 : 8); (void) WriteBlobString(image,buffer); switch (compression) { case FaxCompression: case Group4Compression: { if (LocaleCompare(CCITTParam,"0") == 0) { (void) HuffmanEncodeImage(image_info,image,image,exception); break; } (void) Huffman2DEncodeImage(image_info,image,image,exception); break; } case JPEGCompression: { status=InjectImageBlob(image_info,image,image,"jpeg",exception); if (status == MagickFalse) { (void) CloseBlob(image); return(MagickFalse); } break; } case RLECompression: default: { MemoryInfo *pixel_info; register unsigned char *q; /* Allocate pixel array. */ length=(size_t) number_pixels; pixel_info=AcquireVirtualMemory(length,sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); /* Dump runlength encoded pixels. */ q=pixels; 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++) { *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma(image,p))); p+=GetPixelChannels(image); } progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (progress == MagickFalse) break; } length=(size_t) (q-pixels); if (compression == LZWCompression) status=LZWEncodeImage(image,length,pixels,exception); else status=PackbitsEncodeImage(image,length,pixels,exception); pixel_info=RelinquishVirtualMemory(pixel_info); if (status == MagickFalse) { (void) CloseBlob(image); return(MagickFalse); } break; } case NoCompression: { /* Dump uncompressed PseudoColor packets. */ Ascii85Initialize(image); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum( GetPixelLuma(image,p)))); p+=GetPixelChannels(image); } progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); if (progress == MagickFalse) break; } Ascii85Flush(image); break; } } } else if ((image->storage_class == DirectClass) || (image->colors > 256) || (compression == JPEGCompression) || (image->alpha_trait != UndefinedPixelTrait)) { (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g\n0\n%d\n", (double) image->columns,(double) image->rows,(int) (image->colorspace == CMYKColorspace)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent,"%d\n", (int) (compression == NoCompression)); (void) WriteBlobString(image,buffer); switch (compression) { case JPEGCompression: { status=InjectImageBlob(image_info,image,image,"jpeg",exception); if (status == MagickFalse) { (void) CloseBlob(image); return(MagickFalse); } break; } case RLECompression: default: { MemoryInfo *pixel_info; register unsigned char *q; /* Allocate pixel array. */ length=(size_t) number_pixels; pixel_info=AcquireVirtualMemory(length,4*sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) ThrowWriterException(ResourceLimitError, "MemoryAllocationFailed"); pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); /* Dump runlength encoded pixels. */ q=pixels; 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++) { if ((image->alpha_trait != UndefinedPixelTrait) && (GetPixelAlpha(image,p) == (Quantum) TransparentAlpha)) { *q++=ScaleQuantumToChar(QuantumRange); *q++=ScaleQuantumToChar(QuantumRange); *q++=ScaleQuantumToChar(QuantumRange); } else if (image->colorspace != CMYKColorspace) { *q++=ScaleQuantumToChar(GetPixelRed(image,p)); *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); } else { *q++=ScaleQuantumToChar(GetPixelRed(image,p)); *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); *q++=ScaleQuantumToChar(GetPixelBlack(image,p)); } p+=GetPixelChannels(image); } progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); if (progress == MagickFalse) break; } length=(size_t) (q-pixels); if (compression == LZWCompression) status=LZWEncodeImage(image,length,pixels,exception); else status=PackbitsEncodeImage(image,length,pixels,exception); if (status == MagickFalse) { (void) CloseBlob(image); return(MagickFalse); } pixel_info=RelinquishVirtualMemory(pixel_info); break; } case NoCompression: { /* Dump uncompressed DirectColor packets. */ Ascii85Initialize(image); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { if ((image->alpha_trait != UndefinedPixelTrait) && (GetPixelAlpha(image,p) == (Quantum) TransparentAlpha)) { Ascii85Encode(image,ScaleQuantumToChar((Quantum) QuantumRange)); Ascii85Encode(image,ScaleQuantumToChar((Quantum) QuantumRange)); Ascii85Encode(image,ScaleQuantumToChar((Quantum) QuantumRange)); } else if (image->colorspace != CMYKColorspace) { Ascii85Encode(image,ScaleQuantumToChar( GetPixelRed(image,p))); Ascii85Encode(image,ScaleQuantumToChar( GetPixelGreen(image,p))); Ascii85Encode(image,ScaleQuantumToChar( GetPixelBlue(image,p))); } else { Ascii85Encode(image,ScaleQuantumToChar( GetPixelRed(image,p))); Ascii85Encode(image,ScaleQuantumToChar( GetPixelGreen(image,p))); Ascii85Encode(image,ScaleQuantumToChar( GetPixelBlue(image,p))); Ascii85Encode(image,ScaleQuantumToChar( GetPixelBlack(image,p))); } p+=GetPixelChannels(image); } progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); if (progress == MagickFalse) break; } Ascii85Flush(image); break; } } } else { /* Dump number of colors and colormap. */ (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g\n1\n%d\n", (double) image->columns,(double) image->rows,(int) (image->colorspace == CMYKColorspace)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent,"%d\n", (int) (compression == NoCompression)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double) image->colors); (void) WriteBlobString(image,buffer); for (i=0; i < (ssize_t) image->colors; i++) { (void) FormatLocaleString(buffer,MagickPathExtent,"%02X%02X%02X\n", ScaleQuantumToChar(image->colormap[i].red), ScaleQuantumToChar(image->colormap[i].green), ScaleQuantumToChar(image->colormap[i].blue)); (void) WriteBlobString(image,buffer); } switch (compression) { case RLECompression: default: { MemoryInfo *pixel_info; register unsigned char *q; /* Allocate pixel array. */ length=(size_t) number_pixels; pixel_info=AcquireVirtualMemory(length,sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) ThrowWriterException(ResourceLimitError, "MemoryAllocationFailed"); pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); /* Dump runlength encoded pixels. */ q=pixels; 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++) { *q++=(unsigned char) GetPixelIndex(image,p); p+=GetPixelChannels(image); } progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); if (progress == MagickFalse) break; } length=(size_t) (q-pixels); if (compression == LZWCompression) status=LZWEncodeImage(image,length,pixels,exception); else status=PackbitsEncodeImage(image,length,pixels,exception); pixel_info=RelinquishVirtualMemory(pixel_info); if (status == MagickFalse) { (void) CloseBlob(image); return(MagickFalse); } break; } case NoCompression: { /* Dump uncompressed PseudoColor packets. */ Ascii85Initialize(image); for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { Ascii85Encode(image,(unsigned char) GetPixelIndex(image,p)); p+=GetPixelChannels(image); } progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); if (progress == MagickFalse) break; } Ascii85Flush(image); break; } } } (void) WriteBlobByte(image,'\n'); length=(size_t) (TellBlob(image)-stop); stop=TellBlob(image); offset=SeekBlob(image,start,SEEK_SET); if (offset < 0) ThrowWriterException(CorruptImageError,"ImproperImageHeader"); (void) FormatLocaleString(buffer,MagickPathExtent, "%%%%BeginData:%13ld %s Bytes\n",(long) length, compression == NoCompression ? "ASCII" : "Binary"); (void) WriteBlobString(image,buffer); offset=SeekBlob(image,stop,SEEK_SET); (void) WriteBlobString(image,"%%EndData\n"); if (LocaleCompare(image_info->magick,"PS2") != 0) (void) WriteBlobString(image,"end\n"); (void) WriteBlobString(image,"%%PageTrailer\n"); if (GetNextImageInList(image) == (Image *) NULL) break; image=SyncNextImageInList(image); status=SetImageProgress(image,SaveImagesTag,scene++, GetImageListLength(image)); if (status == MagickFalse) break; } while (image_info->adjoin != MagickFalse); (void) WriteBlobString(image,"%%Trailer\n"); if (page > 1) { (void) FormatLocaleString(buffer,MagickPathExtent, "%%%%BoundingBox: %.20g %.20g %.20g %.20g\n",ceil(bounds.x1-0.5), ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5)); (void) WriteBlobString(image,buffer); (void) FormatLocaleString(buffer,MagickPathExtent, "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1,bounds.y1, bounds.x2,bounds.y2); (void) WriteBlobString(image,buffer); } (void) WriteBlobString(image,"%%EOF\n"); (void) CloseBlob(image); return(MagickTrue); }
static MagickBooleanType WriteJBIGImage(const ImageInfo *image_info, Image *image,ExceptionInfo *exception) { double version; MagickBooleanType status; MagickOffsetType scene; MemoryInfo *pixel_info; register const Quantum *p; register ssize_t x; register unsigned char *q; size_t number_packets; ssize_t y; struct jbg_enc_state jbig_info; unsigned char bit, byte, *pixels; /* Open image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); if (status == MagickFalse) return(status); version=StringToDouble(JBG_VERSION,(char **) NULL); scene=0; do { /* Allocate pixel data. */ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse) (void) TransformImageColorspace(image,sRGBColorspace,exception); number_packets=(image->columns+7)/8; pixel_info=AcquireVirtualMemory(number_packets,image->rows*sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); /* Convert pixels to a bitmap. */ (void) SetImageType(image,BilevelType,exception); q=pixels; for (y=0; y < (ssize_t) image->rows; y++) { p=GetVirtualPixels(image,0,y,image->columns,1,exception); if (p == (const Quantum *) NULL) break; bit=0; byte=0; for (x=0; x < (ssize_t) image->columns; x++) { byte<<=1; if (GetPixelLuma(image,p) < (QuantumRange/2.0)) byte|=0x01; bit++; if (bit == 8) { *q++=byte; bit=0; byte=0; } p+=GetPixelChannels(image); } if (bit != 0) *q++=byte << (8-bit); if (image->previous == (Image *) NULL) { status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } /* Initialize JBIG info structure. */ jbg_enc_init(&jbig_info,(unsigned long) image->columns,(unsigned long) image->rows,1,&pixels,(void (*)(unsigned char *,size_t,void *)) JBIGEncode,image); if (image_info->scene != 0) jbg_enc_layers(&jbig_info,(int) image_info->scene); else { size_t x_resolution, y_resolution; x_resolution=640; y_resolution=480; if (image_info->density != (char *) NULL) { GeometryInfo geometry_info; MagickStatusType flags; flags=ParseGeometry(image_info->density,&geometry_info); x_resolution=geometry_info.rho; y_resolution=geometry_info.sigma; if ((flags & SigmaValue) == 0) y_resolution=x_resolution; } if (image->units == PixelsPerCentimeterResolution) { x_resolution=(size_t) (100.0*2.54*x_resolution+0.5)/100.0; y_resolution=(size_t) (100.0*2.54*y_resolution+0.5)/100.0; } (void) jbg_enc_lrlmax(&jbig_info,(unsigned long) x_resolution, (unsigned long) y_resolution); } (void) jbg_enc_lrange(&jbig_info,-1,-1); jbg_enc_options(&jbig_info,JBG_ILEAVE | JBG_SMID,JBG_TPDON | JBG_TPBON | JBG_DPON,version < 1.6 ? -1 : 0,-1,-1); /* Write JBIG image. */ jbg_enc_out(&jbig_info); jbg_enc_free(&jbig_info); pixel_info=RelinquishVirtualMemory(pixel_info); 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); }