From bce0859dc2c11635c0010976b760a13e23210718 Mon Sep 17 00:00:00 2001 From: dirk Date: Sat, 27 Jun 2015 20:26:03 +0000 Subject: [PATCH] Improved performance of QuantizeImage method when the number of colors don't need to be reduced. --- MagickCore/quantize.c | 152 +++++++++++++++++++++++++++++++----------- 1 file changed, 112 insertions(+), 40 deletions(-) diff --git a/MagickCore/quantize.c b/MagickCore/quantize.c index 772ef9b32..b3a1cce55 100644 --- a/MagickCore/quantize.c +++ b/MagickCore/quantize.c @@ -492,14 +492,9 @@ static inline size_t ColorToNodeId(const CubeInfo *cube_info, return(id); } -static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info, - ExceptionInfo *exception) +static inline MagickBooleanType PreAssignImageColors(Image *image, + CubeInfo *cube_info,ExceptionInfo *exception) { -#define AssignImageTag "Assign/Image" - - ssize_t - y; - /* Allocate image colormap. */ @@ -509,14 +504,61 @@ static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info, cube_info->quantize_info->colorspace,exception); else if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse) - (void) TransformImageColorspace((Image *) image,sRGBColorspace,exception); + (void) TransformImageColorspace((Image *) image,sRGBColorspace, + exception); if (AcquireImageColormap(image,cube_info->colors,exception) == MagickFalse) - ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", - image->filename); + return(MagickFalse); image->colors=0; cube_info->transparent_pixels=0; cube_info->transparent_index=(-1); (void) DefineImageColormap(image,cube_info,cube_info->root); + return(MagickTrue); +} + +static inline void PostAssignImageColors(Image *image,CubeInfo *cube_info, + ExceptionInfo *exception) +{ + if (cube_info->quantize_info->measure_error != MagickFalse) + (void) GetImageQuantizeError(image,exception); + if ((cube_info->quantize_info->number_colors == 2) && + (cube_info->quantize_info->colorspace == GRAYColorspace)) + { + double + intensity; + + register PixelInfo + *restrict q; + + register ssize_t + i; + + /* + Monochrome image. + */ + q=image->colormap; + for (i=0; i < (ssize_t) image->colors; i++) + { + intensity=(double) (GetPixelInfoLuma(q) < (QuantumRange/2.0) ? 0 : + QuantumRange); + q->red=intensity; + q->green=q->red; + q->blue=q->red; + q++; + } + } +} + +static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info, + ExceptionInfo *exception) +{ +#define AssignImageTag "Assign/Image" + + ssize_t + y; + + if (PreAssignImageColors(image,cube_info,exception) == MagickFalse) + ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", + image->filename); /* Create a reduced color image. */ @@ -641,34 +683,7 @@ static MagickBooleanType AssignImageColors(Image *image,CubeInfo *cube_info, } image_view=DestroyCacheView(image_view); } - if (cube_info->quantize_info->measure_error != MagickFalse) - (void) GetImageQuantizeError(image,exception); - if ((cube_info->quantize_info->number_colors == 2) && - (cube_info->quantize_info->colorspace == GRAYColorspace)) - { - double - intensity; - - register PixelInfo - *restrict q; - - register ssize_t - i; - - /* - Monochrome image. - */ - q=image->colormap; - for (i=0; i < (ssize_t) image->colors; i++) - { - intensity=(double) (GetPixelInfoLuma(q) < (QuantumRange/2.0) ? 0 : - QuantumRange); - q->red=intensity; - q->green=q->red; - q->blue=q->red; - q++; - } - } + PostAssignImageColors(image,cube_info,exception); (void) SyncImage(image,exception); if ((cube_info->quantize_info->colorspace != UndefinedColorspace) && (cube_info->quantize_info->colorspace != CMYKColorspace)) @@ -2640,6 +2655,59 @@ static void PruneToCubeDepth(const Image *image,CubeInfo *cube_info, % */ +static MagickBooleanType DirectToPseudoClassImage(Image *image, + CubeInfo *cube_info,ExceptionInfo *exception) +{ + MagickBooleanType + status; + + ssize_t + y; + + if (cube_info->colors > cube_info->maximum_colors) + return(MagickFalse); + if (PreAssignImageColors(image,cube_info,exception) == MagickFalse) + ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", + image->filename); +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp parallel for schedule(static,4) shared(status) \ + magick_threads(image,image,image->rows,1) +#endif + for (y=0; y < (ssize_t) image->rows; y++) + { + register Quantum + *restrict q; + + register ssize_t + x; + + if (status == MagickFalse) + continue; + q=GetAuthenticPixels(image,0,y,image->columns,1,exception); + if (q == (Quantum *) NULL) + continue; + for (x=0; x < (ssize_t) image->columns; x++) + { + register ssize_t + i; + + for (i=0; i < (ssize_t) image->colors; i++) + { + if (IsPixelEquivalent(image,q,&image->colormap[i]) == MagickFalse) + continue; + SetPixelIndex(image,(Quantum) i,q); + break; + } + q+=GetPixelChannels(image); + } + if (SyncAuthenticPixels(image,exception) == MagickFalse) + status=MagickFalse; + } + image->storage_class=PseudoClass; + PostAssignImageColors(image,cube_info,exception); + return(status); +} + static MagickBooleanType DirectToColormapImage(Image *image, ExceptionInfo *exception) { @@ -2776,8 +2844,12 @@ MagickExport MagickBooleanType QuantizeImage(const QuantizeInfo *quantize_info, /* Reduce the number of colors in the image. */ - ReduceImageColors(image,cube_info); - status=AssignImageColors(image,cube_info,exception); + status=DirectToPseudoClassImage(image,cube_info,exception); + if (status == MagickFalse) + { + ReduceImageColors(image,cube_info); + status=AssignImageColors(image,cube_info,exception); + } } DestroyCubeInfo(cube_info); return(status); -- 2.40.0