static MagickBooleanType load_tile(Image *image,Image *tile_image, XCFDocInfo *inDocInfo,XCFLayerInfo *inLayerInfo,size_t data_length) { ExceptionInfo *exception; ssize_t y; register ssize_t x; register PixelPacket *q; ssize_t count; unsigned char *graydata; XCFPixelPacket *xcfdata, *xcfodata; xcfdata=(XCFPixelPacket *) AcquireQuantumMemory(data_length,sizeof(*xcfdata)); if (xcfdata == (XCFPixelPacket *) NULL) ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); xcfodata=xcfdata; graydata=(unsigned char *) xcfdata; /* used by gray and indexed */ count=ReadBlob(image,data_length,(unsigned char *) xcfdata); if (count != (ssize_t) data_length) ThrowBinaryException(CorruptImageError,"NotEnoughPixelData", image->filename); exception=(&image->exception); for (y=0; y < (ssize_t) tile_image->rows; y++) { q=QueueAuthenticPixels(tile_image,0,y,tile_image->columns,1,exception); if (q == (PixelPacket *) NULL) break; if (inDocInfo->image_type == GIMP_GRAY) { for (x=0; x < (ssize_t) tile_image->columns; x++) { SetPixelRed(q,ScaleCharToQuantum(*graydata)); SetPixelGreen(q,GetPixelRed(q)); SetPixelBlue(q,GetPixelRed(q)); SetPixelAlpha(q,ScaleCharToQuantum((unsigned char) inLayerInfo->opacity)); graydata++; q++; } } else if (inDocInfo->image_type == GIMP_RGB) { for (x=0; x < (ssize_t) tile_image->columns; x++) { SetPixelRed(q,ScaleCharToQuantum(xcfdata->red)); SetPixelGreen(q,ScaleCharToQuantum(xcfdata->green)); SetPixelBlue(q,ScaleCharToQuantum(xcfdata->blue)); SetPixelAlpha(q,xcfdata->opacity == 0U ? OpaqueOpacity : ScaleCharToQuantum((unsigned char) inLayerInfo->opacity)); xcfdata++; q++; } } if (SyncAuthenticPixels(tile_image,exception) == MagickFalse) break; } xcfodata=(XCFPixelPacket *) RelinquishMagickMemory(xcfodata); return MagickTrue; }
static MagickBooleanType load_tile_rle(Image *image,Image *tile_image, XCFDocInfo *inDocInfo,XCFLayerInfo *inLayerInfo,size_t data_length) { ExceptionInfo *exception; MagickOffsetType size; register PixelPacket *q; size_t length; ssize_t bytes_per_pixel, count, i, j; unsigned char data, pixel, *xcfdata, *xcfodata, *xcfdatalimit; bytes_per_pixel=(ssize_t) inDocInfo->bytes_per_pixel; xcfdata=(unsigned char *) AcquireQuantumMemory(data_length,sizeof(*xcfdata)); if (xcfdata == (unsigned char *) NULL) ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); xcfodata=xcfdata; count=ReadBlob(image, (size_t) data_length, xcfdata); xcfdatalimit = xcfodata+count-1; exception=(&image->exception); for (i=0; i < (ssize_t) bytes_per_pixel; i++) { q=GetAuthenticPixels(tile_image,0,0,tile_image->columns,tile_image->rows, exception); size=(MagickOffsetType) tile_image->rows*tile_image->columns; while (size > 0) { if (xcfdata > xcfdatalimit) goto bogus_rle; pixel=(*xcfdata++); length=(size_t) pixel; if (length >= 128) { length=255-(length-1); if (length == 128) { if (xcfdata >= xcfdatalimit) goto bogus_rle; length=(size_t) ((*xcfdata << 8) + xcfdata[1]); xcfdata+=2; } size-=length; if (size < 0) goto bogus_rle; if (&xcfdata[length-1] > xcfdatalimit) goto bogus_rle; while (length-- > 0) { data=(*xcfdata++); switch (i) { case 0: { SetPixelRed(q,ScaleCharToQuantum(data)); if (inDocInfo->image_type != GIMP_GRAY) { SetPixelGreen(q,ScaleCharToQuantum(data)); SetPixelBlue(q,ScaleCharToQuantum(data)); SetPixelAlpha(q,ScaleCharToQuantum( (unsigned char) inLayerInfo->opacity)); } else { SetPixelGreen(q,GetPixelRed(q)); SetPixelBlue(q,GetPixelRed(q)); SetPixelAlpha(q,ScaleCharToQuantum( (unsigned char) inLayerInfo->opacity)); } break; } case 1: { SetPixelGreen(q,ScaleCharToQuantum(data)); break; } case 2: { SetPixelBlue(q,ScaleCharToQuantum(data)); break; } case 3: { SetPixelAlpha(q,data == 0 ? OpaqueOpacity : ScaleCharToQuantum((unsigned char) inLayerInfo->opacity)); break; } } q++; } } else { length+=1; if (length == 128) { if (xcfdata >= xcfdatalimit) goto bogus_rle; length=(size_t) ((*xcfdata << 8) + xcfdata[1]); xcfdata+=2; } size-=length; if (size < 0) goto bogus_rle; if (xcfdata > xcfdatalimit) goto bogus_rle; pixel=(*xcfdata++); for (j= 0; j < (ssize_t) length; j++) { data=pixel; switch (i) { case 0: { SetPixelRed(q,ScaleCharToQuantum(data)); if (inDocInfo->image_type != GIMP_GRAY) { SetPixelGreen(q,ScaleCharToQuantum(data)); SetPixelBlue(q,ScaleCharToQuantum(data)); SetPixelAlpha(q,ScaleCharToQuantum( (unsigned char) inLayerInfo->opacity)); } else { SetPixelGreen(q,GetPixelRed(q)); SetPixelBlue(q,GetPixelRed(q)); SetPixelAlpha(q,ScaleCharToQuantum( (unsigned char) inLayerInfo->opacity)); } break; } case 1: { SetPixelGreen(q,ScaleCharToQuantum(data)); break; } case 2: { SetPixelBlue(q,ScaleCharToQuantum(data)); break; } case 3: { SetPixelAlpha(q,data == 0 ? OpaqueOpacity : ScaleCharToQuantum((unsigned char) inLayerInfo->opacity)); break; } } q++; } } } if (SyncAuthenticPixels(tile_image,exception) == MagickFalse) break; } xcfodata=(unsigned char *) RelinquishMagickMemory(xcfodata); return(MagickTrue); bogus_rle: if (xcfodata != (unsigned char *) NULL) xcfodata=(unsigned char *) RelinquishMagickMemory(xcfodata); return(MagickFalse); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteImage() writes an image or an image sequence to a file or filehandle. % If writing to a file on disk, the name is defined by the filename member of % the image structure. Write() returns MagickFalse is these is a memory % shortage or if the image cannot be written. Check the exception member of % image to determine the cause for any failure. % % The format of the WriteImage method is: % % MagickBooleanType WriteImage(const ImageInfo *image_info,Image *image) % % A description of each parameter follows: % % o image_info: the image info. % % o image: the image. % */ MagickExport MagickBooleanType WriteImage(const ImageInfo *image_info, Image *image) { char filename[MaxTextExtent]; const char *option; const DelegateInfo *delegate_info; const MagickInfo *magick_info; ExceptionInfo *sans_exception; ImageInfo *write_info; MagickBooleanType status, temporary; MagickStatusType thread_support; PolicyDomain domain; PolicyRights rights; /* Determine image type from filename prefix or suffix (e.g. image.jpg). */ assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); sans_exception=AcquireExceptionInfo(); write_info=CloneImageInfo(image_info); (void) CopyMagickString(write_info->filename,image->filename,MaxTextExtent); if (*write_info->magick == '\0') (void) CopyMagickString(write_info->magick,image->magick,MaxTextExtent); (void) SetImageInfo(write_info,1,sans_exception); if (LocaleCompare(write_info->magick,"clipmask") == 0) { if (image->clip_mask == (Image *) NULL) { (void) ThrowMagickException(&image->exception,GetMagickModule(), OptionError,"NoClipPathDefined","`%s'",image->filename); return(MagickFalse); } image=image->clip_mask; (void) SetImageInfo(write_info,1,sans_exception); } (void) CopyMagickString(filename,image->filename,MaxTextExtent); (void) CopyMagickString(image->filename,write_info->filename,MaxTextExtent); domain=CoderPolicyDomain; rights=WritePolicyRights; if (IsRightsAuthorized(domain,rights,write_info->magick) == MagickFalse) { sans_exception=DestroyExceptionInfo(sans_exception); errno=EPERM; ThrowBinaryException(PolicyError,"NotAuthorized",filename); } magick_info=GetMagickInfo(write_info->magick,sans_exception); sans_exception=DestroyExceptionInfo(sans_exception); if (magick_info != (const MagickInfo *) NULL) { if (GetMagickEndianSupport(magick_info) == MagickFalse) image->endian=UndefinedEndian; else if ((image_info->endian == UndefinedEndian) && (GetMagickRawSupport(magick_info) != MagickFalse)) { size_t lsb_first; lsb_first=1; image->endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian; } } (void) SyncImageProfiles(image); option=GetImageOption(image_info,"delegate:bimodal"); if ((option != (const char *) NULL) && (IsMagickTrue(option) != MagickFalse) && (write_info->page == (char *) NULL) && (GetPreviousImageInList(image) == (Image *) NULL) && (GetNextImageInList(image) == (Image *) NULL) && (IsTaintImage(image) == MagickFalse)) { delegate_info=GetDelegateInfo(image->magick,write_info->magick, &image->exception); if ((delegate_info != (const DelegateInfo *) NULL) && (GetDelegateMode(delegate_info) == 0) && (IsPathAccessible(image->magick_filename) != MagickFalse)) { /* Process image with bi-modal delegate. */ (void) CopyMagickString(image->filename,image->magick_filename, MaxTextExtent); status=InvokeDelegate(write_info,image,image->magick, write_info->magick,&image->exception); write_info=DestroyImageInfo(write_info); (void) CopyMagickString(image->filename,filename,MaxTextExtent); return(status); } } status=MagickFalse; temporary=MagickFalse; if ((magick_info != (const MagickInfo *) NULL) && (GetMagickSeekableStream(magick_info) != MagickFalse)) { char filename[MaxTextExtent]; (void) CopyMagickString(filename,image->filename,MaxTextExtent); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); (void) CopyMagickString(image->filename,filename,MaxTextExtent); if (status != MagickFalse) { if (IsBlobSeekable(image) == MagickFalse) { /* A seekable stream is required by the encoder. */ write_info->adjoin=MagickTrue; (void) CopyMagickString(write_info->filename,image->filename, MaxTextExtent); (void) AcquireUniqueFilename(image->filename); temporary=MagickTrue; } (void) CloseBlob(image); } } if (constitute_semaphore == (SemaphoreInfo *) NULL) AcquireSemaphoreInfo(&constitute_semaphore); if ((magick_info != (const MagickInfo *) NULL) && (GetImageEncoder(magick_info) != (EncodeImageHandler *) NULL)) { /* Call appropriate image writer based on image type. */ thread_support=GetMagickThreadSupport(magick_info); if ((thread_support & EncoderThreadSupport) == 0) LockSemaphoreInfo(constitute_semaphore); status=GetImageEncoder(magick_info)(write_info,image); if ((thread_support & EncoderThreadSupport) == 0) UnlockSemaphoreInfo(constitute_semaphore); } else { delegate_info=GetDelegateInfo((char *) NULL,write_info->magick, &image->exception); if (delegate_info != (DelegateInfo *) NULL) { /* Process the image with delegate. */ *write_info->filename='\0'; if (GetDelegateThreadSupport(delegate_info) == MagickFalse) LockSemaphoreInfo(constitute_semaphore); status=InvokeDelegate(write_info,image,(char *) NULL, write_info->magick,&image->exception); if (GetDelegateThreadSupport(delegate_info) == MagickFalse) UnlockSemaphoreInfo(constitute_semaphore); (void) CopyMagickString(image->filename,filename,MaxTextExtent); } else { sans_exception=AcquireExceptionInfo(); magick_info=GetMagickInfo(write_info->magick,sans_exception); sans_exception=DestroyExceptionInfo(sans_exception); if ((write_info->affirm == MagickFalse) && (magick_info == (const MagickInfo *) NULL)) { (void) CopyMagickString(write_info->magick,image->magick, MaxTextExtent); magick_info=GetMagickInfo(write_info->magick,&image->exception); } if ((magick_info == (const MagickInfo *) NULL) || (GetImageEncoder(magick_info) == (EncodeImageHandler *) NULL)) { magick_info=GetMagickInfo(image->magick,&image->exception); (void) CopyMagickString(image->filename,filename,MaxTextExtent); } if ((magick_info == (const MagickInfo *) NULL) || (GetImageEncoder(magick_info) == (EncodeImageHandler *) NULL)) (void) ThrowMagickException(&image->exception,GetMagickModule(), MissingDelegateError,"NoEncodeDelegateForThisImageFormat","`%s'", image->filename); else { /* Call appropriate image writer based on image type. */ thread_support=GetMagickThreadSupport(magick_info); if ((thread_support & EncoderThreadSupport) == 0) LockSemaphoreInfo(constitute_semaphore); status=GetImageEncoder(magick_info)(write_info,image); if ((thread_support & EncoderThreadSupport) == 0) UnlockSemaphoreInfo(constitute_semaphore); } } } if (GetBlobError(image) != MagickFalse) ThrowFileException(&image->exception,FileOpenError, "AnErrorHasOccurredWritingToFile",image->filename); if (temporary == MagickTrue) { /* Copy temporary image file to permanent. */ status=OpenBlob(write_info,image,ReadBinaryBlobMode,&image->exception); if (status != MagickFalse) status=ImageToFile(image,write_info->filename,&image->exception); (void) CloseBlob(image); (void) RelinquishUniqueFileResource(image->filename); (void) CopyMagickString(image->filename,write_info->filename, MaxTextExtent); } if ((LocaleCompare(write_info->magick,"info") != 0) && (write_info->verbose != MagickFalse)) (void) IdentifyImage(image,stdout,MagickFalse); write_info=DestroyImageInfo(write_info); return(status); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R a i s e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % RaiseImage() creates a simulated three-dimensional button-like effect % by lightening and darkening the edges of the image. Members width and % height of raise_info define the width of the vertical and horizontal % edge of the effect. % % The format of the RaiseImage method is: % % MagickBooleanType RaiseImage(const Image *image, % const RectangleInfo *raise_info,const MagickBooleanType raise) % % A description of each parameter follows: % % o image: the image. % % o raise_info: Define the width and height of the raise area. % % o raise: A value other than zero creates a 3-D raise effect, % otherwise it has a lowered effect. % */ MagickExport MagickBooleanType RaiseImage(Image *image, const RectangleInfo *raise_info,const MagickBooleanType raise) { #define AccentuateFactor ScaleCharToQuantum(135) #define HighlightFactor ScaleCharToQuantum(190) #define ShadowFactor ScaleCharToQuantum(190) #define RaiseImageTag "Raise/Image" #define TroughFactor ScaleCharToQuantum(135) CacheView *image_view; ExceptionInfo *exception; MagickBooleanType status; MagickOffsetType progress; Quantum foreground, background; ssize_t y; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(raise_info != (RectangleInfo *) NULL); if ((image->columns <= (raise_info->width << 1)) || (image->rows <= (raise_info->height << 1))) ThrowBinaryException(OptionError,"ImageSizeMustExceedBevelWidth", image->filename); foreground=QuantumRange; background=(Quantum) 0; if (raise == MagickFalse) { foreground=(Quantum) 0; background=QuantumRange; } if (SetImageStorageClass(image,DirectClass) == MagickFalse) return(MagickFalse); /* Raise image. */ status=MagickTrue; progress=0; exception=(&image->exception); image_view=AcquireAuthenticCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,1,1) #endif for (y=0; y < (ssize_t) raise_info->height; y++) { register ssize_t x; register PixelPacket *restrict q; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } for (x=0; x < y; x++) { SetPixelRed(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelRed(q)*HighlightFactor+(MagickRealType) foreground* (QuantumRange-HighlightFactor)))); SetPixelGreen(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelGreen(q)*HighlightFactor+(MagickRealType) foreground* (QuantumRange-HighlightFactor)))); SetPixelBlue(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelBlue(q)*HighlightFactor+(MagickRealType) foreground* (QuantumRange-HighlightFactor)))); q++; } for ( ; x < (ssize_t) (image->columns-y); x++) { SetPixelRed(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelRed(q)*AccentuateFactor+(MagickRealType) foreground* (QuantumRange-AccentuateFactor)))); SetPixelGreen(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelGreen(q)*AccentuateFactor+(MagickRealType) foreground* (QuantumRange-AccentuateFactor)))); SetPixelBlue(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelBlue(q)*AccentuateFactor+(MagickRealType) foreground* (QuantumRange-AccentuateFactor)))); q++; } for ( ; x < (ssize_t) image->columns; x++) { SetPixelRed(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelRed(q)*ShadowFactor+(MagickRealType) background* (QuantumRange-ShadowFactor)))); SetPixelGreen(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelGreen(q)*ShadowFactor+(MagickRealType) background* (QuantumRange-ShadowFactor)))); SetPixelBlue(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelBlue(q)*ShadowFactor+(MagickRealType) background* (QuantumRange-ShadowFactor)))); q++; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_RaiseImage) #endif proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); if (proceed == MagickFalse) status=MagickFalse; } } #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,1,1) #endif for (y=(ssize_t) raise_info->height; y < (ssize_t) (image->rows-raise_info->height); y++) { register ssize_t x; register PixelPacket *restrict q; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) raise_info->width; x++) { SetPixelRed(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelRed(q)*HighlightFactor+(MagickRealType) foreground* (QuantumRange-HighlightFactor)))); SetPixelGreen(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelGreen(q)*HighlightFactor+(MagickRealType) foreground* (QuantumRange-HighlightFactor)))); SetPixelBlue(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelBlue(q)*HighlightFactor+(MagickRealType) foreground* (QuantumRange-HighlightFactor)))); q++; } for ( ; x < (ssize_t) (image->columns-raise_info->width); x++) q++; for ( ; x < (ssize_t) image->columns; x++) { SetPixelRed(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelRed(q)*ShadowFactor+(MagickRealType) background* (QuantumRange-ShadowFactor)))); SetPixelGreen(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelGreen(q)*ShadowFactor+(MagickRealType) background* (QuantumRange-ShadowFactor)))); SetPixelBlue(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelBlue(q)*ShadowFactor+(MagickRealType) background* (QuantumRange-ShadowFactor)))); q++; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_RaiseImage) #endif proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); if (proceed == MagickFalse) status=MagickFalse; } } #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,1,1) #endif for (y=(ssize_t) (image->rows-raise_info->height); y < (ssize_t) image->rows; y++) { register ssize_t x; register PixelPacket *restrict q; if (status == MagickFalse) continue; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } for (x=0; x < (ssize_t) (image->rows-y); x++) { SetPixelRed(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelRed(q)*HighlightFactor+(MagickRealType) foreground* (QuantumRange-HighlightFactor)))); SetPixelGreen(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelGreen(q)*HighlightFactor+(MagickRealType) foreground* (QuantumRange-HighlightFactor)))); SetPixelBlue(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelBlue(q)*HighlightFactor+(MagickRealType) foreground* (QuantumRange-HighlightFactor)))); q++; } for ( ; x < (ssize_t) (image->columns-(image->rows-y)); x++) { SetPixelRed(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelRed(q)*TroughFactor+(MagickRealType) background* (QuantumRange-TroughFactor)))); SetPixelGreen(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelGreen(q)*TroughFactor+(MagickRealType) background* (QuantumRange-TroughFactor)))); SetPixelBlue(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelBlue(q)*TroughFactor+(MagickRealType) background* (QuantumRange-TroughFactor)))); q++; } for ( ; x < (ssize_t) image->columns; x++) { SetPixelRed(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelRed(q)*ShadowFactor+(MagickRealType) background* (QuantumRange-ShadowFactor)))); SetPixelGreen(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelGreen(q)*ShadowFactor+(MagickRealType) background* (QuantumRange-ShadowFactor)))); SetPixelBlue(q,ClampToQuantum(QuantumScale*((MagickRealType) GetPixelBlue(q)*ShadowFactor+(MagickRealType) background* (QuantumRange-ShadowFactor)))); q++; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; if (image->progress_monitor != (MagickProgressMonitor) NULL) { MagickBooleanType proceed; #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp critical (MagickCore_RaiseImage) #endif proceed=SetImageProgress(image,RaiseImageTag,progress++,image->rows); if (proceed == MagickFalse) status=MagickFalse; } } image_view=DestroyCacheView(image_view); return(status); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % F l o o d f i l l P a i n t I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % FloodfillPaintImage() changes the color value of any pixel that matches % target and is an immediate neighbor. If the method FillToBorderMethod is % specified, the color value is changed for any neighbor pixel that does not % match the bordercolor member of image. % % By default target must match a particular pixel color exactly. However, % in many cases two colors may differ by a small amount. The fuzz member of % image defines how much tolerance is acceptable to consider two colors as % the same. For example, set fuzz to 10 and the color red at intensities of % 100 and 102 respectively are now interpreted as the same color for the % purposes of the floodfill. % % The format of the FloodfillPaintImage method is: % % MagickBooleanType FloodfillPaintImage(Image *image, % const DrawInfo *draw_info,const PixelInfo target, % const ssize_t x_offset,const ssize_t y_offset, % const MagickBooleanType invert,ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % % o draw_info: the draw info. % % o target: the RGB value of the target color. % % o x_offset,y_offset: the starting location of the operation. % % o invert: paint any pixel that does not match the target color. % % o exception: return any errors or warnings in this structure. % */ MagickExport MagickBooleanType FloodfillPaintImage(Image *image, const DrawInfo *draw_info,const PixelInfo *target,const ssize_t x_offset, const ssize_t y_offset,const MagickBooleanType invert, ExceptionInfo *exception) { #define MaxStacksize 131072UL #define PushSegmentStack(up,left,right,delta) \ { \ if (s >= (segment_stack+MaxStacksize)) \ ThrowBinaryException(DrawError,"SegmentStackOverflow",image->filename) \ else \ { \ if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (ssize_t) image->rows)) \ { \ s->x1=(double) (left); \ s->y1=(double) (up); \ s->x2=(double) (right); \ s->y2=(double) (delta); \ s++; \ } \ } \ } CacheView *floodplane_view, *image_view; Image *floodplane_image; MagickBooleanType skip, status; 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 == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(draw_info != (DrawInfo *) NULL); assert(draw_info->signature == MagickSignature); if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns)) return(MagickFalse); if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows)) return(MagickFalse); if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) return(MagickFalse); if (IsGrayColorspace(image->colorspace) != MagickFalse) (void) SetImageColorspace(image,sRGBColorspace,exception); if ((image->alpha_trait != BlendPixelTrait) && (draw_info->fill.alpha_trait == BlendPixelTrait)) (void) SetImageAlpha(image,OpaqueAlpha,exception); /* Set floodfill state. */ floodplane_image=CloneImage(image,image->columns,image->rows,MagickTrue, exception); if (floodplane_image == (Image *) NULL) return(MagickFalse); floodplane_image->alpha_trait=UndefinedPixelTrait; floodplane_image->colorspace=GRAYColorspace; (void) QueryColorCompliance("#000",AllCompliance, &floodplane_image->background_color,exception); (void) SetImageBackgroundColor(floodplane_image,exception); segment_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); } for (y=0; y < (ssize_t) image->rows; y++) { register const Quantum *restrict p; register Quantum *restrict q; register ssize_t x; /* Tile fill color onto floodplane. */ p=GetCacheViewVirtualPixels(floodplane_view,0,y,image->columns,1,exception); q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) break; for (x=0; x < (ssize_t) image->columns; x++) { if (GetPixelGray(floodplane_image,p) != 0) { (void) GetFillColor(draw_info,x,y,&fill_color,exception); SetPixelInfoPixel(image,&fill_color,q); } p+=GetPixelChannels(floodplane_image); q+=GetPixelChannels(image); } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) break; } floodplane_view=DestroyCacheView(floodplane_view); image_view=DestroyCacheView(image_view); segment_info=RelinquishVirtualMemory(segment_info); floodplane_image=DestroyImage(floodplane_image); return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse); }
MagickExport MagickBooleanType GradientImage(Image *image, const GradientType type,const SpreadMethod method, const PixelInfo *start_color,const PixelInfo *stop_color, ExceptionInfo *exception) { DrawInfo *draw_info; GradientInfo *gradient; MagickBooleanType status; register ssize_t i; /* Set gradient start-stop end points. */ assert(image != (const Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(start_color != (const PixelInfo *) NULL); assert(stop_color != (const PixelInfo *) NULL); draw_info=AcquireDrawInfo(); gradient=(&draw_info->gradient); gradient->type=type; gradient->bounding_box.width=image->columns; gradient->bounding_box.height=image->rows; gradient->gradient_vector.x2=(double) image->columns-1.0; gradient->gradient_vector.y2=(double) image->rows-1.0; if ((type == LinearGradient) && (gradient->gradient_vector.y2 != 0.0)) gradient->gradient_vector.x2=0.0; gradient->center.x=(double) gradient->gradient_vector.x2/2.0; gradient->center.y=(double) gradient->gradient_vector.y2/2.0; gradient->radius=MagickMax(gradient->center.x,gradient->center.y); gradient->spread=method; /* Define the gradient to fill between the stops. */ gradient->number_stops=2; gradient->stops=(StopInfo *) AcquireQuantumMemory(gradient->number_stops, sizeof(*gradient->stops)); if (gradient->stops == (StopInfo *) NULL) ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); (void) ResetMagickMemory(gradient->stops,0,gradient->number_stops* sizeof(*gradient->stops)); for (i=0; i < (ssize_t) gradient->number_stops; i++) GetPixelInfo(image,&gradient->stops[i].color); gradient->stops[0].color=(*start_color); gradient->stops[0].offset=0.0; gradient->stops[1].color=(*stop_color); gradient->stops[1].offset=1.0; /* Draw a gradient on the image. */ (void) SetImageColorspace(image,start_color->colorspace,exception); status=DrawGradientImage(image,draw_info,exception); draw_info=DestroyDrawInfo(draw_info); return(status); }
MagickExport MagickBooleanType SortColormapByIntensity(Image *image, ExceptionInfo *exception) { CacheView *image_view; MagickBooleanType status; register ssize_t i; ssize_t y; unsigned short *pixels; assert(image != (Image *) NULL); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); assert(image->signature == MagickSignature); if (image->storage_class != PseudoClass) return(MagickTrue); /* Allocate memory for pixel indexes. */ pixels=(unsigned short *) AcquireQuantumMemory((size_t) image->colors, sizeof(*pixels)); if (pixels == (unsigned short *) NULL) ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); /* Assign index values to colormap entries. */ #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) \ magick_threads(image,image,1,1) #endif for (i=0; i < (ssize_t) image->colors; i++) image->colormap[i].alpha=(double) i; /* Sort image colormap by decreasing color popularity. */ qsort((void *) image->colormap,(size_t) image->colors, sizeof(*image->colormap),IntensityCompare); /* Update image colormap indexes to sorted colormap order. */ #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(static,4) shared(status) #endif for (i=0; i < (ssize_t) image->colors; i++) pixels[(ssize_t) image->colormap[i].alpha]=(unsigned short) i; status=MagickTrue; image_view=AcquireAuthenticCacheView(image,exception); for (y=0; y < (ssize_t) image->rows; y++) { Quantum index; register ssize_t x; register Quantum *restrict q; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) { status=MagickFalse; break; } for (x=0; x < (ssize_t) image->columns; x++) { index=(Quantum) pixels[(ssize_t) GetPixelIndex(image,q)]; SetPixelIndex(image,index,q); SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q); q+=GetPixelChannels(image); } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; if (status == MagickFalse) break; } image_view=DestroyCacheView(image_view); pixels=(unsigned short *) RelinquishMagickMemory(pixels); return(status); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % P a i n t F l o o d f i l l I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % PaintFloodfill() 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 PaintFloodfillImage method is: % % MagickBooleanType PaintFloodfillImage(Image *image, % const ChannelType channel,const MagickPixelPacket target, % const long x_offset,const long y_offset,const DrawInfo *draw_info, % const PaintMethod method) % % A description of each parameter follows: % % o image: The image. % % o channel: The channel(s). % % o target: The RGB value of the target color. % % o x_offset,y_offset: The starting location of the operation. % % o draw_info: The draw info. % % o method: Choose either FloodfillMethod or FillToBorderMethod. % */ MagickExport MagickBooleanType PaintFloodfillImage(Image *image, const ChannelType channel,const MagickPixelPacket *target, const long x_offset,const long y_offset,const DrawInfo *draw_info, const PaintMethod method) { #define MaxStacksize (1UL << 15) #define PushSegmentStack(up,left,right,delta) \ { \ if (s >= (segment_stack+MaxStacksize)) \ ThrowBinaryException(DrawError,"SegmentStackOverflow",image->filename) \ else \ { \ if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (long) image->rows)) \ { \ s->x1=(double) (left); \ s->y1=(double) (up); \ s->x2=(double) (right); \ s->y2=(double) (delta); \ s++; \ } \ } \ } Image *floodplane_image; long offset, start, x1, x2, y; MagickBooleanType skip; MagickPixelPacket fill, pixel; PixelPacket fill_color; register const PixelPacket *p; register IndexPacket *indexes; register long x; register PixelPacket *q; register SegmentInfo *s; SegmentInfo *segment_stack; /* Check boundary conditions. */ assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(draw_info != (DrawInfo *) NULL); assert(draw_info->signature == MagickSignature); if ((x_offset < 0) || (x_offset >= (long) image->columns)) return(MagickFalse); if ((y_offset < 0) || (y_offset >= (long) image->rows)) return(MagickFalse); if (SetImageStorageClass(image,DirectClass) == MagickFalse) return(MagickFalse); if (image->matte == MagickFalse) (void) SetImageOpacity(image,OpaqueOpacity); /* Set floodfill state. */ floodplane_image=CloneImage(image,image->columns,image->rows,MagickTrue, &image->exception); if (floodplane_image == (Image *) NULL) return(MagickFalse); (void) SetImageOpacity(floodplane_image,OpaqueOpacity); segment_stack=(SegmentInfo *) AcquireQuantumMemory(MaxStacksize, sizeof(*segment_stack)); if (segment_stack == (SegmentInfo *) NULL) { floodplane_image=DestroyImage(floodplane_image); ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); } /* Push initial segment on stack. */ x=x_offset; y=y_offset; start=0; s=segment_stack; PushSegmentStack(y,x,x,1); PushSegmentStack(y+1,x,x,-1); GetMagickPixelPacket(image,&fill); GetMagickPixelPacket(image,&pixel); while (s > segment_stack) { /* Pop segment off stack. */ s--; x1=(long) s->x1; x2=(long) s->x2; offset=(long) s->y2; y=(long) s->y1+offset; /* Recolor neighboring pixels. */ p=AcquireImagePixels(image,0,y,(unsigned long) (x1+1),1,&image->exception); q=GetImagePixels(floodplane_image,0,y,(unsigned long) (x1+1),1); if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetIndexes(image); p+=x1; q+=x1; for (x=x1; x >= 0; x--) { if (q->opacity == (Quantum) TransparentOpacity) break; SetMagickPixelPacket(image,p,indexes+x,&pixel); if (method == FloodfillMethod) { if (IsMagickColorSimilar(&pixel,target) == MagickFalse) break; } else if (IsMagickColorSimilar(&pixel,target) != MagickFalse) break; q->opacity=(Quantum) TransparentOpacity; p--; q--; } if (SyncImagePixels(floodplane_image) == 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 < (long) image->columns) { p=AcquireImagePixels(image,x,y,image->columns-x,1, &image->exception); q=GetImagePixels(floodplane_image,x,y,image->columns-x,1); if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetIndexes(image); for ( ; x < (long) image->columns; x++) { if (q->opacity == (Quantum) TransparentOpacity) break; SetMagickPixelPacket(image,p,indexes+x,&pixel); if (method == FloodfillMethod) { if (IsMagickColorSimilar(&pixel,target) == MagickFalse) break; } else if (IsMagickColorSimilar(&pixel,target) != MagickFalse) break; q->opacity=(Quantum) TransparentOpacity; p++; q++; } if (SyncImagePixels(floodplane_image) == 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=AcquireImagePixels(image,x,y,(unsigned long) (x2-x+1),1, &image->exception); q=GetImagePixels(floodplane_image,x,y,(unsigned long) (x2-x+1),1); if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetIndexes(image); for ( ; x <= x2; x++) { if (q->opacity == (Quantum) TransparentOpacity) break; SetMagickPixelPacket(image,p,indexes+x,&pixel); if (method == FloodfillMethod) { if (IsMagickColorSimilar(&pixel,target) != MagickFalse) break; } else if (IsMagickColorSimilar(&pixel,target) == MagickFalse) break; p++; q++; } } start=x; } while (x <= x2); } for (y=0; y < (long) image->rows; y++) { /* Tile fill color onto floodplane. */ p=AcquireImagePixels(floodplane_image,0,y,image->columns,1, &image->exception); q=GetImagePixels(image,0,y,image->columns,1); if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetIndexes(image); for (x=0; x < (long) image->columns; x++) { if (p->opacity != OpaqueOpacity) { fill_color=GetFillColor(draw_info,x,y); SetMagickPixelPacket(image,&fill_color,(IndexPacket *) NULL,&fill); if (image->colorspace == CMYKColorspace) ConvertRGBToCMYK(&fill); if ((channel & RedChannel) != 0) q->red=RoundToQuantum(fill.red); if ((channel & GreenChannel) != 0) q->green=RoundToQuantum(fill.green); if ((channel & BlueChannel) != 0) q->blue=RoundToQuantum(fill.blue); if ((channel & OpacityChannel) != 0) q->opacity=RoundToQuantum(fill.opacity); if (((channel & IndexChannel) != 0) && (image->colorspace == CMYKColorspace)) indexes[x]=RoundToQuantum(fill.index); } p++; q++; } if (SyncImagePixels(image) == MagickFalse) break; } segment_stack=(SegmentInfo *) RelinquishMagickMemory(segment_stack); floodplane_image=DestroyImage(floodplane_image); return(y == (long) image->rows ? MagickTrue : MagickFalse); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % S i g n a t u r e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % SignatureImage() computes a message digest from an image pixel stream with % an implementation of the NIST SHA-256 Message Digest algorithm. This % signature uniquely identifies the image and is convenient for determining % if an image has been modified or whether two images are identical. % % The format of the SignatureImage method is: % % MagickBooleanType SignatureImage(Image *image) % % A description of each parameter follows: % % o image: the image. % */ MagickExport MagickBooleanType SignatureImage(Image *image) { CacheView *image_view; char *hex_signature; ExceptionInfo *exception; ssize_t y; QuantumInfo *quantum_info; QuantumType quantum_type; register const PixelPacket *p; SignatureInfo *signature_info; size_t length; StringInfo *signature; unsigned char *pixels; /* Compute image digital signature. */ assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); quantum_info=AcquireQuantumInfo((const ImageInfo *) NULL,image); if (quantum_info == (QuantumInfo *) NULL) ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); quantum_type=RGBQuantum; if (image->matte != MagickFalse) quantum_type=RGBAQuantum; if (image->colorspace == CMYKColorspace) { quantum_type=CMYKQuantum; if (image->matte != MagickFalse) quantum_type=CMYKAQuantum; } signature_info=AcquireSignatureInfo(); signature=AcquireStringInfo(quantum_info->extent); pixels=GetQuantumPixels(quantum_info); exception=(&image->exception); image_view=AcquireCacheView(image); for (y=0; y < (ssize_t) image->rows; y++) { p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); if (p == (const PixelPacket *) NULL) break; length=ExportQuantumPixels(image,image_view,quantum_info,quantum_type, pixels,&image->exception); SetStringInfoLength(signature,length); SetStringInfoDatum(signature,pixels); UpdateSignature(signature_info,signature); } image_view=DestroyCacheView(image_view); quantum_info=DestroyQuantumInfo(quantum_info); FinalizeSignature(signature_info); hex_signature=StringInfoToHexString(GetSignatureDigest(signature_info)); (void) DeleteImageProperty(image,"signature"); (void) SetImageProperty(image,"signature",hex_signature); /* Free resources. */ hex_signature=DestroyString(hex_signature); signature=DestroyStringInfo(signature); signature_info=DestroySignatureInfo(signature_info); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % 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 ChannelType channel,const DrawInfo *draw_info, % const MagickPixelPacket target,const ssize_t x_offset, % const ssize_t y_offset,const MagickBooleanType invert) % % A description of each parameter follows: % % o image: the image. % % o channel: the channel(s). % % 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. % */ MagickExport MagickBooleanType FloodfillPaintImage(Image *image, const ChannelType channel,const DrawInfo *draw_info, const MagickPixelPacket *target,const ssize_t x_offset,const ssize_t y_offset, const MagickBooleanType invert) { #define MaxStacksize (1UL << 15) #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; ExceptionInfo *exception; Image *floodplane_image; MagickBooleanType skip; MagickPixelPacket fill, pixel; PixelPacket fill_color; register SegmentInfo *s; SegmentInfo *segment_stack; ssize_t offset, start, x, x1, x2, y; /* Check boundary conditions. */ assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(draw_info != (DrawInfo *) NULL); assert(draw_info->signature == MagickSignature); if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns)) return(MagickFalse); if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows)) return(MagickFalse); if (SetImageStorageClass(image,DirectClass) == MagickFalse) return(MagickFalse); if (image->matte == MagickFalse) (void) SetImageAlphaChannel(image,OpaqueAlphaChannel); /* Set floodfill state. */ floodplane_image=CloneImage(image,0,0,MagickTrue,&image->exception); if (floodplane_image == (Image *) NULL) return(MagickFalse); (void) SetImageAlphaChannel(floodplane_image,OpaqueAlphaChannel); segment_stack=(SegmentInfo *) AcquireQuantumMemory(MaxStacksize, sizeof(*segment_stack)); if (segment_stack == (SegmentInfo *) NULL) { floodplane_image=DestroyImage(floodplane_image); ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); } /* Push initial segment on stack. */ exception=(&image->exception); x=x_offset; y=y_offset; start=0; s=segment_stack; PushSegmentStack(y,x,x,1); PushSegmentStack(y+1,x,x,-1); GetMagickPixelPacket(image,&fill); GetMagickPixelPacket(image,&pixel); image_view=AcquireCacheView(image); floodplane_view=AcquireCacheView(floodplane_image); while (s > segment_stack) { register const IndexPacket *restrict indexes; register const PixelPacket *restrict p; register ssize_t x; register PixelPacket *restrict q; /* 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 PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetCacheViewVirtualIndexQueue(image_view); p+=x1; q+=x1; for (x=x1; x >= 0; x--) { if (q->opacity == (Quantum) TransparentOpacity) break; SetMagickPixelPacket(image,p,indexes+x,&pixel); if (IsMagickColorSimilar(&pixel,target) == invert) break; q->opacity=(Quantum) TransparentOpacity; p--; q--; } 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 PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetCacheViewVirtualIndexQueue(image_view); for ( ; x < (ssize_t) image->columns; x++) { if (q->opacity == (Quantum) TransparentOpacity) break; SetMagickPixelPacket(image,p,indexes+x,&pixel); if (IsMagickColorSimilar(&pixel,target) == invert) break; q->opacity=(Quantum) TransparentOpacity; p++; q++; } if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == 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 PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetCacheViewVirtualIndexQueue(image_view); for ( ; x <= x2; x++) { if (q->opacity == (Quantum) TransparentOpacity) break; SetMagickPixelPacket(image,p,indexes+x,&pixel); if (IsMagickColorSimilar(&pixel,target) != invert) break; p++; q++; } } start=x; } while (x <= x2); } for (y=0; y < (ssize_t) image->rows; y++) { register const PixelPacket *restrict p; register IndexPacket *restrict indexes; register ssize_t x; register PixelPacket *restrict q; /* Tile fill color onto floodplane. */ p=GetCacheViewVirtualPixels(floodplane_view,0,y,image->columns,1, exception); q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) break; indexes=GetCacheViewAuthenticIndexQueue(image_view); for (x=0; x < (ssize_t) image->columns; x++) { if (GetPixelOpacity(p) != OpaqueOpacity) { (void) GetFillColor(draw_info,x,y,&fill_color); SetMagickPixelPacket(image,&fill_color,(IndexPacket *) NULL,&fill); if (image->colorspace == CMYKColorspace) ConvertRGBToCMYK(&fill); if ((channel & RedChannel) != 0) SetPixelRed(q,ClampToQuantum(fill.red)); if ((channel & GreenChannel) != 0) SetPixelGreen(q,ClampToQuantum(fill.green)); if ((channel & BlueChannel) != 0) SetPixelBlue(q,ClampToQuantum(fill.blue)); if ((channel & OpacityChannel) != 0) SetPixelOpacity(q,ClampToQuantum(fill.opacity)); if (((channel & IndexChannel) != 0) && (image->colorspace == CMYKColorspace)) SetPixelIndex(indexes+x,ClampToQuantum(fill.index)); } p++; q++; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) break; } floodplane_view=DestroyCacheView(floodplane_view); image_view=DestroyCacheView(image_view); segment_stack=(SegmentInfo *) RelinquishMagickMemory(segment_stack); floodplane_image=DestroyImage(floodplane_image); return(y == (ssize_t) image->rows ? MagickTrue : MagickFalse); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % H u f f m a n 2 D E n c o d e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Method Huffman2DEncodeImage compresses an image via two-dimensional % Huffman-coding. % % The format of the Huffman2DEncodeImage method is: % % unsigned int Huffman2DEncodeImage(const ImageInfo *image_info, % Image *image) % % A description of each parameter follows: % % o status: Method Huffman2DEncodeImage returns True if all the pixels are % compressed without error, otherwise False. % % o image_info: The image info.. % % o image: The image. % */ static unsigned int Huffman2DEncodeImage(const ImageInfo *image_info, Image *image) { char filename[MaxTextExtent]; Image *huffman_image; ImageInfo *clone_info; long count, j; register long i; TIFF *tiff; uint16 fillorder; unsigned char *buffer; unsigned int status; unsigned long *byte_count, strip_size; /* Write image as CCITTFax4 TIFF image to a temporary file. */ assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); huffman_image=CloneImage(image,0,0,True,&image->exception); if (huffman_image == (Image *) NULL) return(False); (void) SetImageType(huffman_image,BilevelType); if(!AcquireTemporaryFileName(filename)) { DestroyImage(huffman_image); ThrowBinaryException(FileOpenError,UnableToCreateTemporaryFile, filename); } FormatString(huffman_image->filename,"tiff:%s",filename); clone_info=CloneImageInfo(image_info); clone_info->compression=Group4Compression; clone_info->type=BilevelType; (void) AddDefinitions(clone_info,"tiff:fill-order=msb2lsb", &image->exception); status=WriteImage(clone_info,huffman_image); DestroyImageInfo(clone_info); DestroyImage(huffman_image); if (status == False) return(False); tiff=TIFFOpen(filename,"rb"); if (tiff == (TIFF *) NULL) { (void) LiberateTemporaryFile(filename); ThrowBinaryException(FileOpenError,UnableToOpenFile, image_info->filename) }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % I s I m a g e s E q u a l % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % IsImagesEqual() measures the difference between colors at each pixel % location of two images. A value other than 0 means the colors match % exactly. Otherwise an error measure is computed by summing over all % pixels in an image the distance squared in RGB space between each image % pixel and its corresponding pixel in the reconstruct image. The error % measure is assigned to these image members: % % o mean_error_per_pixel: The mean error for any single pixel in % the image. % % o normalized_mean_error: The normalized mean quantization error for % any single pixel in the image. This distance measure is normalized to % a range between 0 and 1. It is independent of the range of red, green, % and blue values in the image. % % o normalized_maximum_error: The normalized maximum quantization % error for any single pixel in the image. This distance measure is % normalized to a range between 0 and 1. It is independent of the range % of red, green, and blue values in your image. % % A small normalized mean square error, accessed as % image->normalized_mean_error, suggests the images are very similar in % spatial layout and color. % % The format of the IsImagesEqual method is: % % MagickBooleanType IsImagesEqual(Image *image, % const Image *reconstruct_image) % % A description of each parameter follows. % % o image: The image. % % o reconstruct_image: The reconstruct image. % */ MagickExport MagickBooleanType IsImagesEqual(Image *image, const Image *reconstruct_image) { long y; MagickBooleanType status; MagickRealType area, distance, maximum_error, mean_error, mean_error_per_pixel; register const IndexPacket *indexes, *reconstruct_indexes; register const PixelPacket *p, *q; register long x; ViewInfo *image_view, *reconstruct_view; assert(image != (Image *) NULL); assert(image->signature == MagickSignature); assert(reconstruct_image != (const Image *) NULL); assert(reconstruct_image->signature == MagickSignature); if ((reconstruct_image->columns != image->columns) || (reconstruct_image->rows != image->rows)) ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename); area=0.0; maximum_error=0.0; mean_error_per_pixel=0.0; mean_error=0.0; image_view=OpenCacheView(image); reconstruct_view=OpenCacheView(reconstruct_image); for (y=0; y < (long) image->rows; y++) { p=AcquireCacheViewPixels(image_view,0,y,image->columns,1,&image->exception); q=AcquireCacheViewPixels(reconstruct_view,0,y,reconstruct_image->columns,1, &image->exception); if ((p == (const PixelPacket *) NULL) || (q == (const PixelPacket *) NULL)) break; indexes=AcquireCacheViewIndexes(image_view); reconstruct_indexes=AcquireCacheViewIndexes(reconstruct_view); for (x=0; x < (long) image->columns; x++) { distance=fabs(p->red-(double) q->red); mean_error_per_pixel+=distance; mean_error+=distance*distance; if (distance > maximum_error) maximum_error=distance; area++; distance=fabs(p->green-(double) q->green); mean_error_per_pixel+=distance; mean_error+=distance*distance; if (distance > maximum_error) maximum_error=distance; area++; distance=fabs(p->blue-(double) q->blue); mean_error_per_pixel+=distance; mean_error+=distance*distance; if (distance > maximum_error) maximum_error=distance; area++; distance=fabs(p->opacity-(double) q->opacity); mean_error_per_pixel+=distance; mean_error+=distance*distance; if (distance > maximum_error) maximum_error=distance; area++; if ((image->colorspace == CMYKColorspace) && (reconstruct_image->colorspace == CMYKColorspace)) { distance=fabs(indexes[x]-(double) reconstruct_indexes[x]); mean_error_per_pixel+=distance; mean_error+=distance*distance; if (distance > maximum_error) maximum_error=distance; area++; } p++; q++; } } reconstruct_view=CloseCacheView(reconstruct_view); image_view=CloseCacheView(image_view); image->error.mean_error_per_pixel=(double) (mean_error_per_pixel/area); image->error.normalized_mean_error=(double) (QuantumScale*QuantumScale* mean_error/area); image->error.normalized_maximum_error=(double) (QuantumScale*maximum_error); status=image->error.mean_error_per_pixel == 0.0 ? MagickTrue : MagickFalse; return(status); }
MagickExport MagickBooleanType GetImageChannelDistortion(Image *image, const Image *reconstruct_image,const ChannelType channel, const MetricType metric,double *distortion,ExceptionInfo *exception) { assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); assert(reconstruct_image != (const Image *) NULL); assert(reconstruct_image->signature == MagickSignature); assert(distortion != (double *) NULL); *distortion=0.0; if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if ((reconstruct_image->columns != image->columns) || (reconstruct_image->rows != image->rows)) ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename); /* Get image distortion. */ switch (metric) { case AbsoluteErrorMetric: { *distortion=(double) GetAbsoluteError(image,reconstruct_image,exception); break; } case MeanAbsoluteErrorMetric: { *distortion=(double) GetMeanAbsoluteError(image,reconstruct_image,channel, exception); break; } case MeanErrorPerPixelMetric: { *distortion=(double) GetMeanErrorPerPixel(image,reconstruct_image,channel, exception); break; } case MeanSquaredErrorMetric: { *distortion=(double) GetMeanSquaredError(image,reconstruct_image,channel, exception); break; } case PeakAbsoluteErrorMetric: default: { *distortion=(double) GetPeakAbsoluteError(image,reconstruct_image,channel, exception); break; } case PeakSignalToNoiseRatioMetric: { *distortion=(double) GetPeakSignalToNoiseRatio(image,reconstruct_image, channel,exception); break; } case RootMeanSquaredErrorMetric: { *distortion=(double) GetRootMeanSquaredError(image,reconstruct_image, channel,exception); break; } } return(MagickTrue); }
static MagickBooleanType load_level(Image *image,XCFDocInfo *inDocInfo, XCFLayerInfo *inLayerInfo) { ExceptionInfo *exception; int destLeft = 0, destTop = 0; Image* tile_image; MagickBooleanType status; MagickOffsetType saved_pos, offset, offset2; register ssize_t i; size_t width, height, ntiles, ntile_rows, ntile_cols, tile_image_width, tile_image_height; /* start reading the data */ exception=inDocInfo->exception; width=ReadBlobMSBLong(image); height=ReadBlobMSBLong(image); /* Read in the first tile offset. If it is '0', then this tile level is empty and we can simply return. */ offset=(MagickOffsetType) ReadBlobMSBLong(image); if (offset == 0) return(MagickTrue); /* Initialize the reference for the in-memory tile-compression. */ ntile_rows=(height+TILE_HEIGHT-1)/TILE_HEIGHT; ntile_cols=(width+TILE_WIDTH-1)/TILE_WIDTH; ntiles=ntile_rows*ntile_cols; for (i = 0; i < (ssize_t) ntiles; i++) { status=MagickFalse; if (offset == 0) ThrowBinaryException(CorruptImageError,"NotEnoughTiles",image->filename); /* save the current position as it is where the * next tile offset is stored. */ saved_pos=TellBlob(image); /* read in the offset of the next tile so we can calculate the amount of data needed for this tile*/ offset2=(MagickOffsetType)ReadBlobMSBLong(image); /* if the offset is 0 then we need to read in the maximum possible allowing for negative compression */ if (offset2 == 0) offset2=(MagickOffsetType) (offset + TILE_WIDTH * TILE_WIDTH * 4* 1.5); /* seek to the tile offset */ offset=SeekBlob(image, offset, SEEK_SET); /* allocate the image for the tile NOTE: the last tile in a row or column may not be a full tile! */ tile_image_width=(size_t) (destLeft == (int) ntile_cols-1 ? (int) width % TILE_WIDTH : TILE_WIDTH); if (tile_image_width == 0) tile_image_width=TILE_WIDTH; tile_image_height = (size_t) (destTop == (int) ntile_rows-1 ? (int) height % TILE_HEIGHT : TILE_HEIGHT); if (tile_image_height == 0) tile_image_height=TILE_HEIGHT; tile_image=CloneImage(inLayerInfo->image,tile_image_width, tile_image_height,MagickTrue,exception); /* read in the tile */ switch (inDocInfo->compression) { case COMPRESS_NONE: if (load_tile(image,tile_image,inDocInfo,inLayerInfo,(size_t) (offset2-offset)) == 0) status=MagickTrue; break; case COMPRESS_RLE: if (load_tile_rle (image,tile_image,inDocInfo,inLayerInfo, (int) (offset2-offset)) == 0) status=MagickTrue; break; case COMPRESS_ZLIB: ThrowBinaryException(CoderError,"ZipCompressNotSupported", image->filename) case COMPRESS_FRACTAL: ThrowBinaryException(CoderError,"FractalCompressNotSupported", image->filename) } /* composite the tile onto the layer's image, and then destroy it */ (void) CompositeImage(inLayerInfo->image,CopyCompositeOp,tile_image, destLeft * TILE_WIDTH,destTop*TILE_HEIGHT); tile_image=DestroyImage(tile_image); /* adjust tile position */ destLeft++; if (destLeft >= (int) ntile_cols) { destLeft = 0; destTop++; } if (status != MagickFalse) return(MagickFalse); /* restore the saved position so we'll be ready to * read the next offset. */ offset=SeekBlob(image, saved_pos, SEEK_SET); /* read in the offset of the next tile */ offset=(MagickOffsetType) ReadBlobMSBLong(image); } if (offset != 0) ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename) return(MagickTrue); }
MagickExport MagickBooleanType SortColormapByIntensity(Image *image) { CacheView *image_view; ExceptionInfo *exception; MagickBooleanType status; register ssize_t i; ssize_t y; unsigned short *pixels; assert(image != (Image *) NULL); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); assert(image->signature == MagickSignature); if (image->storage_class != PseudoClass) return(MagickTrue); /* Allocate memory for pixel indexes. */ pixels=(unsigned short *) AcquireQuantumMemory((size_t) image->colors, sizeof(*pixels)); if (pixels == (unsigned short *) NULL) ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); /* Assign index values to colormap entries. */ #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(status) #endif for (i=0; i < (ssize_t) image->colors; i++) image->colormap[i].opacity=(IndexPacket) i; /* Sort image colormap by decreasing color popularity. */ qsort((void *) image->colormap,(size_t) image->colors, sizeof(*image->colormap),IntensityCompare); /* Update image colormap indexes to sorted colormap order. */ #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(status) #endif for (i=0; i < (ssize_t) image->colors; i++) pixels[(ssize_t) image->colormap[i].opacity]=(unsigned short) i; status=MagickTrue; exception=(&image->exception); image_view=AcquireCacheView(image); for (y=0; y < (ssize_t) image->rows; y++) { IndexPacket index; register ssize_t x; register IndexPacket *restrict indexes; register PixelPacket *restrict q; q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) { status=MagickFalse; continue; } indexes=GetCacheViewAuthenticIndexQueue(image_view); for (x=0; x < (ssize_t) image->columns; x++) { index=(IndexPacket) pixels[(ssize_t) GetIndexPixelComponent(indexes+x)]; SetIndexPixelComponent(indexes+x,index); SetRGBOPixelComponents(q,image->colormap+(ssize_t) index); q++; } if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; if (status == MagickFalse) break; } image_view=DestroyCacheView(image_view); pixels=(unsigned short *) RelinquishMagickMemory(pixels); return(status); }
static MagickBooleanType ReadOneLayer(Image* image,XCFDocInfo* inDocInfo, XCFLayerInfo *outLayer, ExceptionInfo *exception ) { MagickOffsetType offset; unsigned int foundPropEnd = 0; size_t hierarchy_offset, layer_mask_offset; /* clear the block! */ (void) ResetMagickMemory( outLayer, 0, sizeof( XCFLayerInfo ) ); /* read in the layer width, height, type and name */ outLayer->width = ReadBlobMSBLong(image); outLayer->height = ReadBlobMSBLong(image); outLayer->type = ReadBlobMSBLong(image); (void) ReadBlobStringWithLongSize(image, outLayer->name, sizeof(outLayer->name),exception); /* allocate the image for this layer */ outLayer->image=CloneImage(image,outLayer->width, outLayer->height,MagickTrue, exception); if (outLayer->image == (Image *) NULL) return MagickFalse; /* read the layer properties! */ foundPropEnd = 0; while ( (foundPropEnd == MagickFalse) && (EOFBlob(image) == MagickFalse) ) { PropType prop_type = (PropType) ReadBlobMSBLong(image); size_t prop_size = ReadBlobMSBLong(image); switch (prop_type) { case PROP_END: foundPropEnd = 1; break; case PROP_ACTIVE_LAYER: outLayer->active = 1; break; case PROP_FLOATING_SELECTION: outLayer->floating_offset = ReadBlobMSBLong(image); break; case PROP_OPACITY: outLayer->opacity = ReadBlobMSBLong(image); break; case PROP_VISIBLE: outLayer->visible = ReadBlobMSBLong(image); break; case PROP_LINKED: outLayer->linked = ReadBlobMSBLong(image); break; case PROP_PRESERVE_TRANSPARENCY: outLayer->preserve_trans = ReadBlobMSBLong(image); break; case PROP_APPLY_MASK: outLayer->apply_mask = ReadBlobMSBLong(image); break; case PROP_EDIT_MASK: outLayer->edit_mask = ReadBlobMSBLong(image); break; case PROP_SHOW_MASK: outLayer->show_mask = ReadBlobMSBLong(image); break; case PROP_OFFSETS: outLayer->offset_x = (int) ReadBlobMSBLong(image); outLayer->offset_y = (int) ReadBlobMSBLong(image); break; case PROP_MODE: outLayer->mode = ReadBlobMSBLong(image); break; case PROP_TATTOO: outLayer->preserve_trans = ReadBlobMSBLong(image); break; case PROP_PARASITES: { if (DiscardBlobBytes(image,prop_size) == MagickFalse) ThrowFileException(exception,CorruptImageError, "UnexpectedEndOfFile",image->filename); /* ssize_t base = info->cp; GimpParasite *p; while (info->cp - base < prop_size) { p = xcf_load_parasite(info); gimp_drawable_parasite_attach(GIMP_DRAWABLE(layer), p); gimp_parasite_free(p); } if (info->cp - base != prop_size) g_message ("Error detected while loading a layer's parasites"); */ } break; default: /* g_message ("unexpected/unknown layer property: %d (skipping)", prop_type); */ { int buf[16]; ssize_t amount; /* read over it... */ while ((prop_size > 0) && (EOFBlob(image) == MagickFalse)) { amount = (ssize_t) MagickMin(16, prop_size); amount = ReadBlob(image, (size_t) amount, (unsigned char *) &buf); if (!amount) ThrowBinaryException(CorruptImageError,"CorruptImage", image->filename); prop_size -= (size_t) MagickMin(16, (size_t) amount); } } break; } } if (foundPropEnd == MagickFalse) return(MagickFalse); /* clear the image based on the layer opacity */ outLayer->image->background_color.opacity= ScaleCharToQuantum((unsigned char) (255-outLayer->opacity)); (void) SetImageBackgroundColor(outLayer->image); /* set the compositing mode */ outLayer->image->compose = GIMPBlendModeToCompositeOperator( outLayer->mode ); if ( outLayer->visible == MagickFalse ) { /* BOGUS: should really be separate member var! */ outLayer->image->compose = NoCompositeOp; } /* read the hierarchy and layer mask offsets */ hierarchy_offset = ReadBlobMSBLong(image); layer_mask_offset = ReadBlobMSBLong(image); /* read in the hierarchy */ offset=SeekBlob(image, (MagickOffsetType) hierarchy_offset, SEEK_SET); if (offset < 0) (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError, "InvalidImageHeader","`%s'",image->filename); if (load_hierarchy (image, inDocInfo, outLayer) == 0) return(MagickFalse); /* read in the layer mask */ if (layer_mask_offset != 0) { offset=SeekBlob(image, (MagickOffsetType) layer_mask_offset, SEEK_SET); #if 0 /* BOGUS: support layer masks! */ layer_mask = xcf_load_layer_mask (info, gimage); if (layer_mask == 0) goto error; /* set the offsets of the layer_mask */ GIMP_DRAWABLE (layer_mask)->offset_x = GIMP_DRAWABLE (layer)->offset_x; GIMP_DRAWABLE (layer_mask)->offset_y = GIMP_DRAWABLE (layer)->offset_y; gimp_layer_add_mask (layer, layer_mask, MagickFalse); layer->mask->apply_mask = apply_mask; layer->mask->edit_mask = edit_mask; layer->mask->show_mask = show_mask; #endif } /* attach the floating selection... */ #if 0 /* BOGUS: we may need to read this, even if we don't support it! */ if (add_floating_sel) { GimpLayer *floating_sel; floating_sel = info->floating_sel; floating_sel_attach (floating_sel, GIMP_DRAWABLE (layer)); } #endif return MagickTrue; }
static unsigned int DecodeImage(Image *image,unsigned char *luma, unsigned char *chroma1,unsigned char *chroma2) { typedef struct PCDTable { unsigned int length, sequence; unsigned int mask; unsigned char key; } PCDTable; long count, quantum; PCDTable *pcd_table[3]; register long i, j; register PCDTable *r; register unsigned char *p, *q; size_t length; unsigned char *buffer; unsigned int bits, plane, pcd_length[3], row, sum; /* Initialize Huffman tables. */ assert(image != (const Image *) NULL); assert(luma != (unsigned char *) NULL); assert(chroma1 != (unsigned char *) NULL); assert(chroma2 != (unsigned char *) NULL); buffer=MagickAllocateMemory(unsigned char *,0x800); if (buffer == (unsigned char *) NULL) ThrowBinaryException(ResourceLimitError,MemoryAllocationFailed, (char *) NULL); sum=0; bits=32; p=buffer+0x800; for (i=0; i < (image->columns > 1536 ? 3 : 1); i++) { PCDGetBits(8); length=(sum & 0xff)+1; pcd_table[i]=MagickAllocateMemory(PCDTable *,length*sizeof(PCDTable)); if (pcd_table[i] == (PCDTable *) NULL) { MagickFreeMemory(buffer); ThrowBinaryException(ResourceLimitError,MemoryAllocationFailed, (char *) NULL) } r=pcd_table[i]; for (j=0; j < (long) length; j++) { PCDGetBits(8); r->length=(sum & 0xff)+1; if (r->length > 16) { MagickFreeMemory(buffer); return(False); } PCDGetBits(16); r->sequence=(sum & 0xffff) << 16; PCDGetBits(8); r->key=(unsigned char) (sum & 0xff); r->mask=(~((((unsigned int) 1) << (32-r->length))-1)); r++; } pcd_length[i]=(unsigned int) length; }