/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % W r i t e M G K I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % WriteMGKImage() writes an image to a file in red, green, and blue % MGK rasterfile format. % % The format of the WriteMGKImage method is: % % MagickBooleanType WriteMGKImage(const ImageInfo *image_info, % Image *image) % % A description of each parameter follows. % % o image_info: the image info. % % o image: The image. % */ static MagickBooleanType WriteMGKImage(const ImageInfo *image_info, Image *image) { char buffer[MaxTextExtent]; MagickBooleanType status; MagickOffsetType scene; register const PixelPacket *p; register ssize_t x; register unsigned char *q; ssize_t y; unsigned char *pixels; /* Open output image file. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); if (status == MagickFalse) return(status); scene=0; do { /* Allocate memory for pixels. */ if (image->colorspace != RGBColorspace) (void) SetImageColorspace(image,RGBColorspace); pixels=(unsigned char *) AcquireQuantumMemory((size_t) image->columns, 3UL*sizeof(*pixels)); if (pixels == (unsigned char *) NULL) ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); /* Initialize raster file header. */ (void) WriteBlobString(image,"id=mgk\n"); (void) FormatMagickString(buffer,MaxTextExtent,"%lu %lu\n",image->columns, image->rows); (void) WriteBlobString(image,buffer); for (y=0; y < (ssize_t) image->rows; y++) { p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); if (p == (const PixelPacket *) NULL) break; q=pixels; for (x=0; x < (ssize_t) image->columns; x++) { *q++=ScaleQuantumToChar(GetRedSample(p)); *q++=ScaleQuantumToChar(GetGreenSample(p)); *q++=ScaleQuantumToChar(GetBlueSample(p)); p++; } (void) WriteBlob(image,(size_t) (q-pixels),pixels); if ((image->previous == (Image *) NULL) && (SetImageProgress(image,SaveImageTag,y,image->rows) == MagickFalse)) break; } pixels=(unsigned char *) RelinquishMagickMemory(pixels); if (GetNextImageInList(image) == (Image *) NULL) break; image=SyncNextImageInList(image); status=SetImageProgress(image,SaveImagesTag,scene, GetImageListLength(image)); if (status == MagickFalse) break; scene++; } while (image_info->adjoin != MagickFalse); (void) CloseBlob(image); return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % D i f f e r e n c e I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % DifferenceImage() returns an annotated difference image based on the % the difference between a reference image and a compare image. % % The format of the DifferenceImage method is: % % Image *DifferenceImage(const Image *reference_image, % const Image *compare_image, % const DifferenceImageOptions *difference_options, % ExceptionInfo *exception) % % A description of each parameter follows: % % o reference_image: the reference image. % % o compare_image: the comparison image. % % o difference_options: options to use when differencing. % % o channel: the channel(s) to compare. % % o exception: Return any errors or warnings in this structure. % */ static MagickPassFail DifferenceImagePixels(void *mutable_data, /* User provided mutable data */ const void *immutable_data, /* User provided immutable data */ const Image *reference_image, /* Source 1 image */ const PixelPacket *reference_pixels, /* Pixel row in source 1 image */ const IndexPacket *reference_indexes,/* Pixel row indexes in source 1 image */ const Image *compare_image, /* Source 2 image */ const PixelPacket *compare_pixels, /* Pixel row in source 2 image */ const IndexPacket *compare_indexes, /* Pixel row indexes in source 2 image */ Image *result_image, /* Update image */ PixelPacket *result_pixels, /* Pixel row in update image */ IndexPacket *result_indexes, /* Pixel row indexes in update image */ const long npixels, /* Number of pixels in row */ ExceptionInfo *exception /* Exception report */ ) { const DifferenceImageOptions *difference_options = (const DifferenceImageOptions *) immutable_data; register ChannelType channels = difference_options->channel; register long i; register MagickBool change; ARG_NOT_USED(mutable_data); ARG_NOT_USED(compare_image); ARG_NOT_USED(result_image); ARG_NOT_USED(result_indexes); ARG_NOT_USED(exception); for (i=0; i < npixels; i++) { change=MagickFalse; if (IsCMYKColorspace(reference_image->colorspace)) { if (MagickChannelEnabled(channels,CyanChannel) && (GetCyanSample(&reference_pixels[i]) != GetCyanSample(&compare_pixels[i]))) change=MagickTrue; if (MagickChannelEnabled(channels,MagentaChannel) && (GetMagentaSample(&reference_pixels[i]) != GetMagentaSample(&compare_pixels[i]))) change=MagickTrue; if (MagickChannelEnabled(channels,YellowChannel) && (GetYellowSample(&reference_pixels[i]) != GetYellowSample(&compare_pixels[i]))) change=MagickTrue; if (MagickChannelEnabled(channels,BlackChannel) && (GetBlackSample(&reference_pixels[i]) != GetBlackSample(&compare_pixels[i]))) change=MagickTrue; if (MagickChannelEnabled(channels,OpacityChannel) && (reference_indexes[i] != compare_indexes[i])) change=MagickTrue; } else { if (MagickChannelEnabled(channels,RedChannel) && (GetRedSample(&reference_pixels[i]) != GetRedSample(&compare_pixels[i]))) change=MagickTrue; if (MagickChannelEnabled(channels,GreenChannel) && (GetGreenSample(&reference_pixels[i]) != GetGreenSample(&compare_pixels[i]))) change=MagickTrue; if (MagickChannelEnabled(channels,BlueChannel) && (GetBlueSample(&reference_pixels[i]) != GetBlueSample(&compare_pixels[i]))) change=MagickTrue; if (MagickChannelEnabled(channels,OpacityChannel) && (GetOpacitySample(&reference_pixels[i]) != GetOpacitySample(&compare_pixels[i]))) change=MagickTrue; } /* Modify result image to reflect change. */ switch (difference_options->highlight_style) { case UndefinedHighlightStyle: break; case AssignHighlightStyle: { /* Changed pixels are assigned the highlight color. */ if (change) result_pixels[i]=difference_options->highlight_color; else result_pixels[i]=compare_pixels[i]; break; } case ThresholdHighlightStyle: { /* For changed pixels, compare the pixel intensity. If the pixel intensity in the compare image is higher than the reference image, then set the pixel to white, otherwise set it to black. */ if (change) { Quantum compare_intensity, intensity, reference_intensity; compare_intensity=PixelIntensity(&compare_pixels[i]); reference_intensity=PixelIntensity(&reference_pixels[i]); if (compare_intensity > reference_intensity) intensity=MaxRGB; else intensity=0U; result_pixels[i].red = result_pixels[i].green = result_pixels[i].blue = intensity; result_pixels[i].opacity=compare_pixels[i].opacity; } else { result_pixels[i]=compare_pixels[i]; } break; } case TintHighlightStyle: { /* Alpha composite highlight color on top of change pixels. */ if (change) AlphaCompositePixel(&result_pixels[i],&difference_options->highlight_color,0.75*MaxRGBDouble, &compare_pixels[i],compare_pixels[i].opacity); else result_pixels[i]=compare_pixels[i]; break; } case XorHighlightStyle: { if (change) { result_pixels[i].red = compare_pixels[i].red ^ difference_options->highlight_color.red; result_pixels[i].green = compare_pixels[i].green ^ difference_options->highlight_color.green; result_pixels[i].blue = compare_pixels[i].blue ^ difference_options->highlight_color.blue; result_pixels[i].opacity = compare_pixels[i].opacity ^ difference_options->highlight_color.opacity; } else { result_pixels[i]=compare_pixels[i]; } break; } } } return MagickPass; }