From d76c51ed30cf4084f4434ba08925d16001d1e340 Mon Sep 17 00:00:00 2001 From: cristy Date: Sat, 26 Mar 2011 00:21:26 +0000 Subject: [PATCH] --- magick/composite.c | 16 +- magick/draw.c | 9 +- magick/effect.c | 45 ++-- magick/enhance.c | 46 ++-- magick/fx.c | 73 ++---- magick/pixel.c | 573 +++++++++++++++++++++++++++++++++++++++++++ magick/pixel.h | 21 +- magick/resample.c | 593 ++------------------------------------------- magick/resample.h | 20 +- magick/resize.c | 16 +- 10 files changed, 683 insertions(+), 729 deletions(-) diff --git a/magick/composite.c b/magick/composite.c index 4dc81e8d8..511a44ecc 100644 --- a/magick/composite.c +++ b/magick/composite.c @@ -1840,7 +1840,8 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image, { CacheView *composite_view, - *destination_view; + *destination_view, + *image_view; MagickPixelPacket pixel; @@ -1859,9 +1860,6 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image, register PixelPacket *restrict r; - ResampleFilter - *resample_filter; - /* Displace/Distort based on overlay gradient map: X = red_channel; Y = green_channel; @@ -1950,7 +1948,7 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image, */ pixel=zero; exception=(&image->exception); - resample_filter=AcquireResampleFilter(image,&image->exception); + image_view=AcquireCacheView(image); destination_view=AcquireCacheView(destination_image); composite_view=AcquireCacheView(composite_image); for (y=0; y < (ssize_t) composite_image->rows; y++) @@ -1989,8 +1987,8 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image, offset.y=(vertical_scale*(p->green-(((MagickRealType) QuantumRange+ 1.0)/2.0)))/(((MagickRealType) QuantumRange+1.0)/2.0)+ center.y+((compose == DisplaceCompositeOp) ? y : 0); - (void) ResamplePixelColor(resample_filter,(double) offset.x, - (double) offset.y,&pixel); + (void) InterpolatePixelPacket(image,image_view,image->interpolate, + (double) offset.x,(double) offset.y,&pixel,exception); /* Mask with the 'invalid pixel mask' in alpha channel. */ @@ -2004,9 +2002,9 @@ MagickExport MagickBooleanType CompositeImageChannel(Image *image, if (sync == MagickFalse) break; } - resample_filter=DestroyResampleFilter(resample_filter); - composite_view=DestroyCacheView(composite_view); destination_view=DestroyCacheView(destination_view); + composite_view=DestroyCacheView(composite_view); + image_view=DestroyCacheView(image_view); composite_image=destination_image; break; } diff --git a/magick/draw.c b/magick/draw.c index 4d57c5f10..f026d721b 100644 --- a/magick/draw.c +++ b/magick/draw.c @@ -1109,9 +1109,6 @@ MagickExport MagickBooleanType DrawAffineImage(Image *image, register ssize_t i; - ResampleFilter - **restrict resample_filter; - SegmentInfo edge; @@ -1168,8 +1165,6 @@ MagickExport MagickBooleanType DrawAffineImage(Image *image, inverse_affine=InverseAffineMatrix(affine); GetMagickPixelPacket(image,&zero); exception=(&image->exception); - resample_filter=AcquireResampleFilterThreadSet(source, - UndefinedVirtualPixelMethod,MagickTrue,exception); image_view=AcquireCacheView(image); source_view=AcquireCacheView(source); #if defined(MAGICKCORE_OPENMP_SUPPORT) @@ -1220,7 +1215,8 @@ MagickExport MagickBooleanType DrawAffineImage(Image *image, inverse_affine.tx; point.y=(double) x*inverse_affine.rx+y*inverse_affine.sy+ inverse_affine.ty; - (void) ResamplePixelColor(resample_filter[id],point.x,point.y,&pixel); + (void) InterpolatePixelPacket(image,image_view,image->interpolate, + point.x,point.y,&pixel,exception); SetMagickPixelPacket(image,q,indexes+x_offset,&composite); MagickPixelCompositeOver(&pixel,pixel.opacity,&composite, composite.opacity,&composite); @@ -1231,7 +1227,6 @@ MagickExport MagickBooleanType DrawAffineImage(Image *image, if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) status=MagickFalse; } - resample_filter=DestroyResampleFilterThreadSet(resample_filter); source_view=DestroyCacheView(source_view); image_view=DestroyCacheView(image_view); return(status); diff --git a/magick/effect.c b/magick/effect.c index 6e86d47d8..f9dabee3b 100644 --- a/magick/effect.c +++ b/magick/effect.c @@ -3124,8 +3124,8 @@ MagickExport Image *PreviewImage(const Image *image,const PreviewType preview, break; } } - preview_image=StatisticImage(thumbnail,NonpeakStatistic,i,i, - exception); + preview_image=StatisticImage(thumbnail,NonpeakStatistic,(size_t) i, + (size_t) i,exception); (void) FormatMagickString(label,MaxTextExtent,"+noise %s",factor); break; } @@ -4418,9 +4418,6 @@ MagickExport Image *SpreadImage(const Image *image,const double radius, RandomInfo **restrict random_info; - ResampleFilter - **restrict resample_filter; - size_t width; @@ -4453,8 +4450,6 @@ MagickExport Image *SpreadImage(const Image *image,const double radius, progress=0; GetMagickPixelPacket(spread_image,&bias); width=GetOptimalKernelWidth1D(radius,0.5); - resample_filter=AcquireResampleFilterThreadSet(image, - UndefinedVirtualPixelMethod,MagickTrue,exception); random_info=AcquireRandomInfoThreadSet(); image_view=AcquireCacheView(spread_image); #if defined(MAGICKCORE_OPENMP_SUPPORT) @@ -4490,9 +4485,10 @@ MagickExport Image *SpreadImage(const Image *image,const double radius, pixel=bias; for (x=0; x < (ssize_t) spread_image->columns; x++) { - (void) ResamplePixelColor(resample_filter[id],(double) x+width* - (GetPseudoRandomValue(random_info[id])-0.5),(double) y+width* - (GetPseudoRandomValue(random_info[id])-0.5),&pixel); + (void) InterpolatePixelPacket(image,image_view,image->interpolate, + (double) x+width*(GetPseudoRandomValue(random_info[id])-0.5),(double) + y+width*(GetPseudoRandomValue(random_info[id])-0.5),&pixel, + exception); SetPixelPacket(spread_image,&pixel,q,indexes+x); q++; } @@ -4513,7 +4509,6 @@ MagickExport Image *SpreadImage(const Image *image,const double radius, } image_view=DestroyCacheView(image_view); random_info=DestroyRandomInfoThreadSet(random_info); - resample_filter=DestroyResampleFilterThreadSet(resample_filter); return(spread_image); } @@ -4738,14 +4733,14 @@ static MagickPixelPacket GetMaximumPixelList(PixelList *pixel_list) channel; size_t - color; + color, + maximum; ssize_t count; unsigned short - channels[ListChannels], - maximum; + channels[ListChannels]; /* Find the maximum value for each of the color. @@ -4762,7 +4757,7 @@ static MagickPixelPacket GetMaximumPixelList(PixelList *pixel_list) if (color > maximum) maximum=color; count+=list->nodes[color].count; - } while (count < pixel_list->length); + } while (count < (ssize_t) pixel_list->length); channels[channel]=(unsigned short) maximum; } GetMagickPixelPacket((const Image *) NULL,&pixel); @@ -4809,7 +4804,7 @@ static MagickPixelPacket GetMeanPixelList(PixelList *pixel_list) color=list->nodes[color].next[0]; mean+=list->nodes[color].count*color; count+=list->nodes[color].count; - } while (count < pixel_list->length); + } while (count < (ssize_t) pixel_list->length); channels[channel]=(unsigned short) (mean/pixel_list->length); } GetMagickPixelPacket((const Image *) NULL,&pixel); @@ -4853,7 +4848,7 @@ static MagickPixelPacket GetMedianPixelList(PixelList *pixel_list) { color=list->nodes[color].next[0]; count+=list->nodes[color].count; - } while (count <= (pixel_list->length >> 1)); + } while (count <= (ssize_t) (pixel_list->length >> 1)); channels[channel]=(unsigned short) color; } GetMagickPixelPacket((const Image *) NULL,&pixel); @@ -4877,14 +4872,14 @@ static MagickPixelPacket GetMinimumPixelList(PixelList *pixel_list) channel; size_t - color; + color, + minimum; ssize_t count; unsigned short - channels[ListChannels], - minimum; + channels[ListChannels]; /* Find the minimum value for each of the color. @@ -4901,7 +4896,7 @@ static MagickPixelPacket GetMinimumPixelList(PixelList *pixel_list) if (color < minimum) minimum=color; count+=list->nodes[color].count; - } while (count < pixel_list->length); + } while (count < (ssize_t) pixel_list->length); channels[channel]=(unsigned short) minimum; } GetMagickPixelPacket((const Image *) NULL,&pixel); @@ -4954,7 +4949,7 @@ static MagickPixelPacket GetModePixelList(PixelList *pixel_list) max_count=list->nodes[mode].count; } count+=list->nodes[color].count; - } while (count < pixel_list->length); + } while (count < (ssize_t) pixel_list->length); channels[channel]=(unsigned short) mode; } GetMagickPixelPacket((const Image *) NULL,&pixel); @@ -5003,7 +4998,7 @@ static MagickPixelPacket GetNonpeakPixelList(PixelList *pixel_list) color=next; next=list->nodes[color].next[0]; count+=list->nodes[color].count; - } while (count <= (pixel_list->length >> 1)); + } while (count <= (ssize_t) (pixel_list->length >> 1)); if ((previous == 65536UL) && (next != 65536UL)) color=next; else @@ -5106,9 +5101,9 @@ MagickExport Image *StatisticImageChannel(const Image *image, const size_t height,ExceptionInfo *exception) { #define StatisticWidth \ - (width == 0 ? GetOptimalKernelWidth2D(width,0.5) : width) + (width == 0 ? GetOptimalKernelWidth2D((double) width,0.5) : width) #define StatisticHeight \ - (height == 0 ? GetOptimalKernelWidth2D(height,0.5) : height) + (height == 0 ? GetOptimalKernelWidth2D((double) height,0.5) : height) #define StatisticImageTag "Statistic/Image" CacheView diff --git a/magick/enhance.c b/magick/enhance.c index 12f80e223..b0a91aa6f 100644 --- a/magick/enhance.c +++ b/magick/enhance.c @@ -715,9 +715,6 @@ MagickExport MagickBooleanType ClutImageChannel(Image *image, register ssize_t i; - ResampleFilter - **restrict resample_filter; - ssize_t adjust, y; @@ -742,23 +739,17 @@ MagickExport MagickBooleanType ClutImageChannel(Image *image, progress=0; adjust=(ssize_t) (clut_image->interpolate == IntegerInterpolatePixel ? 0 : 1); exception=(&image->exception); - resample_filter=AcquireResampleFilterThreadSet(clut_image, - UndefinedVirtualPixelMethod,MagickTrue,exception); + image_view=AcquireCacheView(image); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) #endif for (i=0; i <= (ssize_t) MaxMap; i++) { - const int - id = GetOpenMPThreadId(); - GetMagickPixelPacket(clut_image,clut_map+i); - (void) ResamplePixelColor(resample_filter[id],QuantumScale*i* - (clut_image->columns-adjust),QuantumScale*i*(clut_image->rows-adjust), - clut_map+i); + (void) InterpolatePixelPacket(image,image_view,image->interpolate, + QuantumScale*i*(clut_image->columns-adjust),QuantumScale*i* + (clut_image->rows-adjust),clut_map+i,exception); } - resample_filter=DestroyResampleFilterThreadSet(resample_filter); - image_view=AcquireCacheView(image); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(progress,status) #endif @@ -802,11 +793,11 @@ MagickExport MagickBooleanType ClutImageChannel(Image *image, { if (clut_image->matte == MagickFalse) q->opacity=(Quantum) (QuantumRange-MagickPixelIntensityToQuantum( - clut_map+ScaleQuantumToMap(GetAlphaPixelComponent(q)))); + clut_map+ScaleQuantumToMap((Quantum) GetAlphaPixelComponent(q)))); else if (image->matte == MagickFalse) SetOpacityPixelComponent(q,ClampOpacityPixelComponent(clut_map+ - ScaleQuantumToMap(MagickPixelIntensity(&pixel)))); + ScaleQuantumToMap((Quantum) MagickPixelIntensity(&pixel)))); else SetOpacityPixelComponent(q,ClampOpacityPixelComponent( clut_map+ScaleQuantumToMap(q->opacity))); @@ -2250,9 +2241,6 @@ MagickExport MagickBooleanType HaldClutImageChannel(Image *image, MagickPixelPacket zero; - ResampleFilter - **restrict resample_filter; - size_t cube_size, length, @@ -2283,17 +2271,12 @@ MagickExport MagickBooleanType HaldClutImageChannel(Image *image, width=(double) hald_image->columns; GetMagickPixelPacket(hald_image,&zero); exception=(&image->exception); - resample_filter=AcquireResampleFilterThreadSet(hald_image, - UndefinedVirtualPixelMethod,MagickTrue,exception); image_view=AcquireCacheView(image); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(progress,status) #endif for (y=0; y < (ssize_t) image->rows; y++) { - const int - id = GetOpenMPThreadId(); - double offset; @@ -2339,17 +2322,17 @@ MagickExport MagickBooleanType HaldClutImageChannel(Image *image, point.x-=floor(point.x); point.y-=floor(point.y); point.z-=floor(point.z); - (void) ResamplePixelColor(resample_filter[id],fmod(offset,width), - floor(offset/width),&pixel1); - (void) ResamplePixelColor(resample_filter[id],fmod(offset+level,width), - floor((offset+level)/width),&pixel2); + (void) InterpolatePixelPacket(image,image_view,image->interpolate, + fmod(offset,width),floor(offset/width),&pixel1,exception); + (void) InterpolatePixelPacket(image,image_view,image->interpolate, + fmod(offset+level,width),floor((offset+level)/width),&pixel2,exception); MagickPixelCompositeAreaBlend(&pixel1,pixel1.opacity,&pixel2, pixel2.opacity,point.y,&pixel3); offset+=cube_size; - (void) ResamplePixelColor(resample_filter[id],fmod(offset,width), - floor(offset/width),&pixel1); - (void) ResamplePixelColor(resample_filter[id],fmod(offset+level,width), - floor((offset+level)/width),&pixel2); + (void) InterpolatePixelPacket(image,image_view,image->interpolate, + fmod(offset,width),floor(offset/width),&pixel1,exception); + (void) InterpolatePixelPacket(image,image_view,image->interpolate, + fmod(offset+level,width),floor((offset+level)/width),&pixel2,exception); MagickPixelCompositeAreaBlend(&pixel1,pixel1.opacity,&pixel2, pixel2.opacity,point.y,&pixel4); MagickPixelCompositeAreaBlend(&pixel3,pixel3.opacity,&pixel4, @@ -2383,7 +2366,6 @@ MagickExport MagickBooleanType HaldClutImageChannel(Image *image, } } image_view=DestroyCacheView(image_view); - resample_filter=DestroyResampleFilterThreadSet(resample_filter); return(status); } diff --git a/magick/fx.c b/magick/fx.c index bb91bd2d7..9df3a1c78 100644 --- a/magick/fx.c +++ b/magick/fx.c @@ -115,8 +115,8 @@ struct _FxInfo *colors, *symbols; - ResampleFilter - **resample_filter; + CacheView + **view; RandomInfo *random_info; @@ -173,18 +173,15 @@ MagickExport FxInfo *AcquireFxInfo(const Image *image,const char *expression) RelinquishMagickMemory); fx_info->symbols=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory, RelinquishMagickMemory); - fx_info->resample_filter=(ResampleFilter **) AcquireQuantumMemory( - GetImageListLength(fx_info->images),sizeof(*fx_info->resample_filter)); - if (fx_info->resample_filter == (ResampleFilter **) NULL) + fx_info->view=(CacheView **) AcquireQuantumMemory(GetImageListLength( + fx_info->images),sizeof(*fx_info->view)); + if (fx_info->view == (CacheView **) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); i=0; next=GetFirstImageInList(fx_info->images); for ( ; next != (Image *) NULL; next=next->next) { - fx_info->resample_filter[i]=AcquireResampleFilter(next,fx_info->exception); - SetResampleFilter(fx_info->resample_filter[i],PointFilter,1.0); - (void) SetResampleFilterInterpolateMethod(fx_info->resample_filter[i], - NearestNeighborInterpolatePixel); + fx_info->view[i]=AcquireCacheView(next); i++; } fx_info->random_info=AcquireRandomInfo(); @@ -1080,10 +1077,8 @@ MagickExport FxInfo *DestroyFxInfo(FxInfo *fx_info) fx_info->symbols=DestroySplayTree(fx_info->symbols); fx_info->colors=DestroySplayTree(fx_info->colors); for (i=(ssize_t) GetImageListLength(fx_info->images)-1; i >= 0; i--) - fx_info->resample_filter[i]=DestroyResampleFilter( - fx_info->resample_filter[i]); - fx_info->resample_filter=(ResampleFilter **) RelinquishMagickMemory( - fx_info->resample_filter); + fx_info->view[i]=DestroyCacheView(fx_info->view[i]); + fx_info->view=(CacheView **) RelinquishMagickMemory(fx_info->view); fx_info->random_info=DestroyRandomInfo(fx_info->random_info); fx_info=(FxInfo *) RelinquishMagickMemory(fx_info); return(fx_info); @@ -1448,7 +1443,8 @@ static MagickRealType FxGetSymbol(FxInfo *fx_info,const ChannelType channel, "NoSuchImage","`%s'",expression); return(0.0); } - (void) ResamplePixelColor(fx_info->resample_filter[i],point.x,point.y,&pixel); + (void) InterpolatePixelPacket(image,fx_info->view[i], + NearestNeighborInterpolatePixel,point.x,point.y,&pixel,exception); if ((strlen(p) > 2) && (LocaleCompare(p,"intensity") != 0) && (LocaleCompare(p,"luminance") != 0) && @@ -3125,9 +3121,6 @@ MagickExport Image *ImplodeImage(const Image *image,const double amount, center, scale; - ResampleFilter - **restrict resample_filter; - ssize_t y; @@ -3173,8 +3166,6 @@ MagickExport Image *ImplodeImage(const Image *image,const double amount, status=MagickTrue; progress=0; GetMagickPixelPacket(implode_image,&zero); - resample_filter=AcquireResampleFilterThreadSet(image, - UndefinedVirtualPixelMethod,MagickTrue,exception); image_view=AcquireCacheView(image); implode_view=AcquireCacheView(implode_image); #if defined(MAGICKCORE_OPENMP_SUPPORT) @@ -3182,9 +3173,6 @@ MagickExport Image *ImplodeImage(const Image *image,const double amount, #endif for (y=0; y < (ssize_t) image->rows; y++) { - const int - id = GetOpenMPThreadId(); - MagickPixelPacket pixel; @@ -3234,9 +3222,9 @@ MagickExport Image *ImplodeImage(const Image *image,const double amount, if (distance > 0.0) factor=pow(sin((double) (MagickPI*sqrt((double) distance)/ radius/2)),-amount); - (void) ResamplePixelColor(resample_filter[id],(double) - (factor*delta.x/scale.x+center.x),(double) (factor*delta.y/ - scale.y+center.y),&pixel); + (void) InterpolatePixelPacket(image,image_view, + image->interpolate,(double) (factor*delta.x/scale.x+center.x), + (double) (factor*delta.y/scale.y+center.y),&pixel,exception); SetPixelPacket(implode_image,&pixel,q,implode_indexes+x); } q++; @@ -3258,7 +3246,6 @@ MagickExport Image *ImplodeImage(const Image *image,const double amount, } implode_view=DestroyCacheView(implode_view); image_view=DestroyCacheView(image_view); - resample_filter=DestroyResampleFilterThreadSet(resample_filter); if (status == MagickFalse) implode_image=DestroyImage(implode_image); return(implode_image); @@ -4884,9 +4871,6 @@ MagickExport Image *SwirlImage(const Image *image,double degrees, center, scale; - ResampleFilter - **restrict resample_filter; - ssize_t y; @@ -4930,8 +4914,6 @@ MagickExport Image *SwirlImage(const Image *image,double degrees, status=MagickTrue; progress=0; GetMagickPixelPacket(swirl_image,&zero); - resample_filter=AcquireResampleFilterThreadSet(image, - UndefinedVirtualPixelMethod,MagickTrue,exception); image_view=AcquireCacheView(image); swirl_view=AcquireCacheView(swirl_image); #if defined(MAGICKCORE_OPENMP_SUPPORT) @@ -4939,9 +4921,6 @@ MagickExport Image *SwirlImage(const Image *image,double degrees, #endif for (y=0; y < (ssize_t) image->rows; y++) { - const int - id = GetOpenMPThreadId(); - MagickPixelPacket pixel; @@ -4992,9 +4971,10 @@ MagickExport Image *SwirlImage(const Image *image,double degrees, factor=1.0-sqrt((double) distance)/radius; sine=sin((double) (degrees*factor*factor)); cosine=cos((double) (degrees*factor*factor)); - (void) ResamplePixelColor(resample_filter[id],(double) ((cosine* - delta.x-sine*delta.y)/scale.x+center.x),(double) ((sine*delta.x+ - cosine*delta.y)/scale.y+center.y),&pixel); + (void) InterpolatePixelPacket(image,image_view, + image->interpolate,(double) ((cosine*delta.x-sine*delta.y)/scale.x+ + center.x),(double) ((sine*delta.x+cosine*delta.y)/scale.y+ + center.y),&pixel,exception); SetPixelPacket(swirl_image,&pixel,q,swirl_indexes+x); } q++; @@ -5016,7 +4996,6 @@ MagickExport Image *SwirlImage(const Image *image,double degrees, } swirl_view=DestroyCacheView(swirl_view); image_view=DestroyCacheView(image_view); - resample_filter=DestroyResampleFilterThreadSet(resample_filter); if (status == MagickFalse) swirl_image=DestroyImage(swirl_image); return(swirl_image); @@ -5335,6 +5314,7 @@ MagickExport Image *WaveImage(const Image *image,const double amplitude, #define WaveImageTag "Wave/Image" CacheView + *image_view, *wave_view; Image @@ -5355,9 +5335,6 @@ MagickExport Image *WaveImage(const Image *image,const double amplitude, register ssize_t i; - ResampleFilter - **restrict resample_filter; - ssize_t y; @@ -5401,17 +5378,15 @@ MagickExport Image *WaveImage(const Image *image,const double amplitude, status=MagickTrue; progress=0; GetMagickPixelPacket(wave_image,&zero); - resample_filter=AcquireResampleFilterThreadSet(image, - BackgroundVirtualPixelMethod,MagickTrue,exception); + image_view=AcquireCacheView(image); wave_view=AcquireCacheView(wave_image); + (void) SetCacheViewVirtualPixelMethod(image_view, + BackgroundVirtualPixelMethod); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(progress,status) #endif for (y=0; y < (ssize_t) wave_image->rows; y++) { - const int - id = GetOpenMPThreadId(); - MagickPixelPacket pixel; @@ -5437,8 +5412,8 @@ MagickExport Image *WaveImage(const Image *image,const double amplitude, pixel=zero; for (x=0; x < (ssize_t) wave_image->columns; x++) { - (void) ResamplePixelColor(resample_filter[id],(double) x,(double) (y- - sine_map[x]),&pixel); + (void) InterpolatePixelPacket(image,image_view,image->interpolate, + (double) x,(double) (y-sine_map[x]),&pixel,exception); SetPixelPacket(wave_image,&pixel,q,indexes+x); q++; } @@ -5458,7 +5433,7 @@ MagickExport Image *WaveImage(const Image *image,const double amplitude, } } wave_view=DestroyCacheView(wave_view); - resample_filter=DestroyResampleFilterThreadSet(resample_filter); + image_view=DestroyCacheView(image_view); sine_map=(MagickRealType *) RelinquishMagickMemory(sine_map); if (status == MagickFalse) wave_image=DestroyImage(wave_image); diff --git a/magick/pixel.c b/magick/pixel.c index a9c999e54..56876b12c 100644 --- a/magick/pixel.c +++ b/magick/pixel.c @@ -43,6 +43,7 @@ #include "magick/blob.h" #include "magick/blob-private.h" #include "magick/color-private.h" +#include "magick/draw.h" #include "magick/exception.h" #include "magick/exception-private.h" #include "magick/cache.h" @@ -62,6 +63,7 @@ #include "magick/statistic.h" #include "magick/stream.h" #include "magick/string_.h" +#include "magick/transform.h" #include "magick/utility.h" /* @@ -3372,3 +3374,574 @@ MagickExport MagickBooleanType ImportImagePixels(Image *image, quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map); return(MagickTrue); } + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% I n t e r p o l a t e P i x e l P a c k e t % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% InterpolatePixelPacket() applies bi-linear or tri-linear interpolation +% between a floating point coordinate and the pixels surrounding that +% coordinate. No pixel area resampling, or scaling of the result is +% performed. +% +% The format of the InterpolatePixelPacket method is: +% +% MagickBooleanType InterpolatePixelPacket(const Image *image, +% CacheView *image_view,const InterpolatePixelMethod method, +% const double x,const double y,MagickPixelPacket *pixel, +% ExceptionInfo *exception) +% +% A description of each parameter follows: +% +% o image: the image. +% +% o image_view: the image view. +% +% o method: the pixel color interpolation method. +% +% o x,y: A double representing the current (x,y) position of the pixel. +% +% o pixel: return the interpolated pixel here. +% +% o exception: return any errors or warnings in this structure. +% +*/ + +static inline double MagickMax(const double x,const double y) +{ + if (x > y) + return(x); + return(y); +} + +static void BicubicInterpolate(const MagickPixelPacket *pixels,const double dx, + MagickPixelPacket *pixel) +{ + MagickRealType + dx2, + p, + q, + r, + s; + + dx2=dx*dx; + p=(pixels[3].red-pixels[2].red)-(pixels[0].red-pixels[1].red); + q=(pixels[0].red-pixels[1].red)-p; + r=pixels[2].red-pixels[0].red; + s=pixels[1].red; + pixel->red=(dx*dx2*p)+(dx2*q)+(dx*r)+s; + p=(pixels[3].green-pixels[2].green)-(pixels[0].green-pixels[1].green); + q=(pixels[0].green-pixels[1].green)-p; + r=pixels[2].green-pixels[0].green; + s=pixels[1].green; + pixel->green=(dx*dx2*p)+(dx2*q)+(dx*r)+s; + p=(pixels[3].blue-pixels[2].blue)-(pixels[0].blue-pixels[1].blue); + q=(pixels[0].blue-pixels[1].blue)-p; + r=pixels[2].blue-pixels[0].blue; + s=pixels[1].blue; + pixel->blue=(dx*dx2*p)+(dx2*q)+(dx*r)+s; + p=(pixels[3].opacity-pixels[2].opacity)-(pixels[0].opacity-pixels[1].opacity); + q=(pixels[0].opacity-pixels[1].opacity)-p; + r=pixels[2].opacity-pixels[0].opacity; + s=pixels[1].opacity; + pixel->opacity=(dx*dx2*p)+(dx2*q)+(dx*r)+s; + if (pixel->colorspace == CMYKColorspace) + { + p=(pixels[3].index-pixels[2].index)-(pixels[0].index-pixels[1].index); + q=(pixels[0].index-pixels[1].index)-p; + r=pixels[2].index-pixels[0].index; + s=pixels[1].index; + pixel->index=(dx*dx2*p)+(dx2*q)+(dx*r)+s; + } +} + +static inline MagickRealType CubicWeightingFunction(const MagickRealType x) +{ + MagickRealType + alpha, + gamma; + + alpha=MagickMax(x+2.0,0.0); + gamma=1.0*alpha*alpha*alpha; + alpha=MagickMax(x+1.0,0.0); + gamma-=4.0*alpha*alpha*alpha; + alpha=MagickMax(x+0.0,0.0); + gamma+=6.0*alpha*alpha*alpha; + alpha=MagickMax(x-1.0,0.0); + gamma-=4.0*alpha*alpha*alpha; + return(gamma/6.0); +} + +static inline double MeshInterpolate(const PointInfo *delta,const double p, + const double x,const double y) +{ + return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p); +} + +static inline ssize_t NearestNeighbor(MagickRealType x) +{ + if (x >= 0.0) + return((ssize_t) (x+0.5)); + return((ssize_t) (x-0.5)); +} + +MagickExport MagickBooleanType InterpolatePixelPacket(const Image *image, + CacheView *image_view,const InterpolatePixelMethod method,const double x, + const double y,MagickPixelPacket *pixel,ExceptionInfo *exception) +{ + MagickBooleanType + status; + + register const IndexPacket + *indexes; + + register const PixelPacket + *p; + + register ssize_t + i; + + assert(image != (Image *) NULL); + assert(image->signature == MagickSignature); + assert(image_view != (CacheView *) NULL); + status=MagickTrue; + switch (method) + { + case AverageInterpolatePixel: + { + MagickPixelPacket + pixels[16]; + + MagickRealType + alpha[16], + gamma; + + p=GetCacheViewVirtualPixels(image_view,(ssize_t) floor(x)-1, + (ssize_t) floor(y)-1,4,4,exception); + if (p == (const PixelPacket *) NULL) + { + status=MagickFalse; + break; + } + indexes=GetCacheViewVirtualIndexQueue(image_view); + for (i=0; i < 16L; i++) + { + GetMagickPixelPacket(image,pixels+i); + SetMagickPixelPacket(image,p,indexes+i,pixels+i); + alpha[i]=1.0; + if (pixels[i].matte != MagickFalse) + { + alpha[i]=QuantumScale*((MagickRealType) GetAlphaPixelComponent(p)); + pixels[i].red*=alpha[i]; + pixels[i].green*=alpha[i]; + pixels[i].blue*=alpha[i]; + if (pixels[i].colorspace == CMYKColorspace) + pixels[i].index*=alpha[i]; + } + gamma=alpha[i]; + gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); + pixel->red+=gamma*0.0625*pixels[i].red; + pixel->green+=gamma*0.0625*pixels[i].green; + pixel->blue+=gamma*0.0625*pixels[i].blue; + pixel->opacity+=0.0625*pixels[i].opacity; + if (pixel->colorspace == CMYKColorspace) + pixel->index+=gamma*0.0625*pixels[i].index; + p++; + } + break; + } + case BicubicInterpolatePixel: + { + MagickPixelPacket + pixels[16], + u[4]; + + MagickRealType + alpha[16]; + + PointInfo + delta; + + p=GetCacheViewVirtualPixels(image_view,(ssize_t) floor(x)-1,(ssize_t) + floor(y)-1,4,4,exception); + if (p == (const PixelPacket *) NULL) + { + status=MagickFalse; + break; + } + indexes=GetCacheViewVirtualIndexQueue(image_view); + for (i=0; i < 16L; i++) + { + GetMagickPixelPacket(image,pixels+i); + SetMagickPixelPacket(image,p,indexes+i,pixels+i); + alpha[i]=1.0; + if (pixels[i].matte != MagickFalse) + { + alpha[i]=QuantumScale*((MagickRealType) GetAlphaPixelComponent(p)); + pixels[i].red*=alpha[i]; + pixels[i].green*=alpha[i]; + pixels[i].blue*=alpha[i]; + if (pixels[i].colorspace == CMYKColorspace) + pixels[i].index*=alpha[i]; + } + p++; + } + delta.x=x-floor(x); + for (i=0; i < 4L; i++) + BicubicInterpolate(pixels+4*i,delta.x,u+i); + delta.y=y-floor(y); + BicubicInterpolate(u,delta.y,pixel); + break; + } + case BilinearInterpolatePixel: + default: + { + MagickPixelPacket + pixels[4]; + + MagickRealType + alpha[4], + gamma; + + PointInfo + delta, + epsilon; + + p=GetCacheViewVirtualPixels(image_view,(ssize_t) floor(x),(ssize_t) + floor(y),2,2,exception); + if (p == (const PixelPacket *) NULL) + { + status=MagickFalse; + break; + } + indexes=GetCacheViewVirtualIndexQueue(image_view); + for (i=0; i < 4L; i++) + { + GetMagickPixelPacket(image,pixels+i); + pixels[i].red=(MagickRealType) p[i].red; + pixels[i].green=(MagickRealType) p[i].green; + pixels[i].blue=(MagickRealType) p[i].blue; + pixels[i].opacity=(MagickRealType) p[i].opacity; + alpha[i]=1.0; + if (pixels[i].matte != MagickFalse) + { + alpha[i]=QuantumScale*((MagickRealType) QuantumRange-p[i].opacity); + pixels[i].red*=alpha[i]; + pixels[i].green*=alpha[i]; + pixels[i].blue*=alpha[i]; + } + if (indexes != (IndexPacket *) NULL) + { + pixels[i].index=(MagickRealType) indexes[i]; + if (pixels[i].colorspace == CMYKColorspace) + pixels[i].index*=alpha[i]; + } + } + delta.x=x-floor(x); + delta.y=y-floor(y); + epsilon.x=1.0-delta.x; + epsilon.y=1.0-delta.y; + gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y* + (epsilon.x*alpha[2]+delta.x*alpha[3]))); + gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); + pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x* + pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red)); + pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x* + pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x* + pixels[3].green)); + pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x* + pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x* + pixels[3].blue)); + pixel->opacity=(epsilon.y*(epsilon.x*pixels[0].opacity+delta.x* + pixels[1].opacity)+delta.y*(epsilon.x*pixels[2].opacity+delta.x* + pixels[3].opacity)); + if (pixel->colorspace == CMYKColorspace) + pixel->index=gamma*(epsilon.y*(epsilon.x*pixels[0].index+delta.x* + pixels[1].index)+delta.y*(epsilon.x*pixels[2].index+delta.x* + pixels[3].index)); + break; + } + case FilterInterpolatePixel: + { + CacheView + *filter_view; + + Image + *excerpt_image, + *filter_image; + + MagickPixelPacket + pixels[1]; + + RectangleInfo + geometry; + + geometry.width=4L; + geometry.height=4L; + geometry.x=(ssize_t) floor(x)-1L; + geometry.y=(ssize_t) floor(y)-1L; + excerpt_image=ExcerptImage(image,&geometry,exception); + if (excerpt_image == (Image *) NULL) + { + status=MagickFalse; + break; + } + filter_image=ResizeImage(excerpt_image,1,1,image->filter,image->blur, + exception); + excerpt_image=DestroyImage(excerpt_image); + if (filter_image == (Image *) NULL) + break; + filter_view=AcquireCacheView(filter_image); + p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception); + if (p != (const PixelPacket *) NULL) + { + indexes=GetVirtualIndexQueue(filter_image); + GetMagickPixelPacket(image,pixels); + SetMagickPixelPacket(image,p,indexes,pixel); + } + filter_view=DestroyCacheView(filter_view); + filter_image=DestroyImage(filter_image); + break; + } + case IntegerInterpolatePixel: + { + MagickPixelPacket + pixels[1]; + + p=GetCacheViewVirtualPixels(image_view,(ssize_t) floor(x),(ssize_t) + floor(y),1,1,exception); + if (p == (const PixelPacket *) NULL) + { + status=MagickFalse; + break; + } + indexes=GetCacheViewVirtualIndexQueue(image_view); + GetMagickPixelPacket(image,pixels); + SetMagickPixelPacket(image,p,indexes,pixel); + break; + } + case MeshInterpolatePixel: + { + MagickPixelPacket + pixels[4]; + + MagickRealType + alpha[4], + gamma; + + PointInfo + delta, + luminance; + + p=GetCacheViewVirtualPixels(image_view,(ssize_t) floor(x),(ssize_t) + floor(y),2,2,exception); + if (p == (const PixelPacket *) NULL) + { + status=MagickFalse; + break; + } + indexes=GetCacheViewVirtualIndexQueue(image_view); + for (i=0; i < 4L; i++) + { + GetMagickPixelPacket(image,pixels+i); + SetMagickPixelPacket(image,p,indexes+i,pixels+i); + alpha[i]=1.0; + if (pixels[i].matte != MagickFalse) + { + alpha[i]=QuantumScale*((MagickRealType) GetAlphaPixelComponent(p)); + pixels[i].red*=alpha[i]; + pixels[i].green*=alpha[i]; + pixels[i].blue*=alpha[i]; + if (pixels[i].colorspace == CMYKColorspace) + pixels[i].index*=alpha[i]; + } + p++; + } + delta.x=x-floor(x); + delta.y=y-floor(y); + luminance.x=MagickPixelLuminance(pixels+0)-MagickPixelLuminance(pixels+3); + luminance.y=MagickPixelLuminance(pixels+1)-MagickPixelLuminance(pixels+2); + if (fabs(luminance.x) < fabs(luminance.y)) + { + /* + Diagonal 0-3 NW-SE. + */ + if (delta.x <= delta.y) + { + /* + Bottom-left triangle (pixel:2, diagonal: 0-3). + */ + delta.y=1.0-delta.y; + gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]); + gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); + pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red, + pixels[3].red,pixels[0].red); + pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green, + pixels[3].green,pixels[0].green); + pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue, + pixels[3].blue,pixels[0].blue); + pixel->opacity=gamma*MeshInterpolate(&delta,pixels[2].opacity, + pixels[3].opacity,pixels[0].opacity); + if (pixel->colorspace == CMYKColorspace) + pixel->index=gamma*MeshInterpolate(&delta,pixels[2].index, + pixels[3].index,pixels[0].index); + } + else + { + /* + Top-right triangle (pixel:1, diagonal: 0-3). + */ + delta.x=1.0-delta.x; + gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]); + gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); + pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red, + pixels[0].red,pixels[3].red); + pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green, + pixels[0].green,pixels[3].green); + pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue, + pixels[0].blue,pixels[3].blue); + pixel->opacity=gamma*MeshInterpolate(&delta,pixels[1].opacity, + pixels[0].opacity,pixels[3].opacity); + if (pixel->colorspace == CMYKColorspace) + pixel->index=gamma*MeshInterpolate(&delta,pixels[1].index, + pixels[0].index,pixels[3].index); + } + } + else + { + /* + Diagonal 1-2 NE-SW. + */ + if (delta.x <= (1.0-delta.y)) + { + /* + Top-left triangle (pixel 0, diagonal: 1-2). + */ + gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]); + gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); + pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red, + pixels[1].red,pixels[2].red); + pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green, + pixels[1].green,pixels[2].green); + pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue, + pixels[1].blue,pixels[2].blue); + pixel->opacity=gamma*MeshInterpolate(&delta,pixels[0].opacity, + pixels[1].opacity,pixels[2].opacity); + if (pixel->colorspace == CMYKColorspace) + pixel->index=gamma*MeshInterpolate(&delta,pixels[0].index, + pixels[1].index,pixels[2].index); + } + else + { + /* + Bottom-right triangle (pixel: 3, diagonal: 1-2). + */ + delta.x=1.0-delta.x; + delta.y=1.0-delta.y; + gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]); + gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); + pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red, + pixels[2].red,pixels[1].red); + pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green, + pixels[2].green,pixels[1].green); + pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue, + pixels[2].blue,pixels[1].blue); + pixel->opacity=gamma*MeshInterpolate(&delta,pixels[3].opacity, + pixels[2].opacity,pixels[1].opacity); + if (pixel->colorspace == CMYKColorspace) + pixel->index=gamma*MeshInterpolate(&delta,pixels[3].index, + pixels[2].index,pixels[1].index); + } + } + break; + } + case NearestNeighborInterpolatePixel: + { + MagickPixelPacket + pixels[1]; + + p=GetCacheViewVirtualPixels(image_view,NearestNeighbor(x), + NearestNeighbor(y),1,1,exception); + if (p == (const PixelPacket *) NULL) + { + status=MagickFalse; + break; + } + indexes=GetCacheViewVirtualIndexQueue(image_view); + GetMagickPixelPacket(image,pixels); + SetMagickPixelPacket(image,p,indexes,pixel); + break; + } + case SplineInterpolatePixel: + { + MagickPixelPacket + pixels[16]; + + MagickRealType + alpha[16], + dx, + dy, + gamma; + + PointInfo + delta; + + ssize_t + j, + n; + + p=GetCacheViewVirtualPixels(image_view,(ssize_t) floor(x)-1,(ssize_t) + floor(y)-1,4,4,exception); + if (p == (const PixelPacket *) NULL) + { + status=MagickFalse; + break; + } + indexes=GetCacheViewVirtualIndexQueue(image_view); + n=0; + delta.x=x-floor(x); + delta.y=y-floor(y); + for (i=(-1); i < 3L; i++) + { + dy=CubicWeightingFunction((MagickRealType) i-delta.y); + for (j=(-1); j < 3L; j++) + { + GetMagickPixelPacket(image,pixels+n); + SetMagickPixelPacket(image,p,indexes+n,pixels+n); + alpha[n]=1.0; + if (pixels[i].matte != MagickFalse) + { + alpha[n]=QuantumScale*((MagickRealType) + GetAlphaPixelComponent(p)); + pixels[n].red*=alpha[n]; + pixels[n].green*=alpha[n]; + pixels[n].blue*=alpha[n]; + if (pixels[i].colorspace == CMYKColorspace) + pixels[n].index*=alpha[n]; + } + dx=CubicWeightingFunction(delta.x-(MagickRealType) j); + gamma=alpha[n]; + gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); + pixel->red+=gamma*dx*dy*pixels[n].red; + pixel->green+=gamma*dx*dy*pixels[n].green; + pixel->blue+=gamma*dx*dy*pixels[n].blue; + if (pixel->matte != MagickFalse) + pixel->opacity+=dx*dy*pixels[n].opacity; + if (pixel->colorspace == CMYKColorspace) + pixel->index+=gamma*dx*dy*pixels[n].index; + n++; + p++; + } + } + break; + } + } + return(status); +} diff --git a/magick/pixel.h b/magick/pixel.h index f51a7b0f2..fdf6523bb 100644 --- a/magick/pixel.h +++ b/magick/pixel.h @@ -67,6 +67,19 @@ extern "C" { #define SetYellowPixelComponent(q,value) ((q)->blue=(value)) #define SetBlackPixelComponent(p,x,value) (p[x]=(value)) +typedef enum +{ + UndefinedInterpolatePixel, + AverageInterpolatePixel, + BicubicInterpolatePixel, + BilinearInterpolatePixel, + FilterInterpolatePixel, + IntegerInterpolatePixel, + MeshInterpolatePixel, + NearestNeighborInterpolatePixel, + SplineInterpolatePixel +} InterpolatePixelMethod; + typedef struct _DoublePixelPacket { double @@ -133,11 +146,17 @@ typedef struct _PixelPacket #endif } PixelPacket; +typedef struct _CacheView + CacheView_; + extern MagickExport MagickBooleanType ExportImagePixels(const Image *,const ssize_t,const ssize_t,const size_t, const size_t,const char *,const StorageType,void *,ExceptionInfo *), ImportImagePixels(Image *,const ssize_t,const ssize_t,const size_t, - const size_t,const char *,const StorageType,const void *); + const size_t,const char *,const StorageType,const void *), + InterpolatePixelPacket(const Image *,CacheView_ *, + const InterpolatePixelMethod,const double,const double,MagickPixelPacket *, + ExceptionInfo *); extern MagickExport void GetMagickPixelPacket(const Image *,MagickPixelPacket *); diff --git a/magick/resample.c b/magick/resample.c index ed95cb91f..10253be8c 100644 --- a/magick/resample.c +++ b/magick/resample.c @@ -286,574 +286,6 @@ MagickExport ResampleFilter *DestroyResampleFilter( % % % % % % -% I n t e r p o l a t e R e s a m p l e F i l t e r % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% InterpolateResampleFilter() applies bi-linear or tri-linear interpolation -% between a floating point coordinate and the pixels surrounding that -% coordinate. No pixel area resampling, or scaling of the result is -% performed. -% -% The format of the InterpolateResampleFilter method is: -% -% MagickBooleanType InterpolateResampleFilter( -% ResampleInfo *resample_filter,const InterpolatePixelMethod method, -% const double x,const double y,MagickPixelPacket *pixel) -% -% A description of each parameter follows: -% -% o resample_filter: the resample filter. -% -% o method: the pixel clor interpolation method. -% -% o x,y: A double representing the current (x,y) position of the pixel. -% -% o pixel: return the interpolated pixel here. -% -*/ - -static inline double MagickMax(const double x,const double y) -{ - if (x > y) - return(x); - return(y); -} - -static void BicubicInterpolate(const MagickPixelPacket *pixels,const double dx, - MagickPixelPacket *pixel) -{ - MagickRealType - dx2, - p, - q, - r, - s; - - dx2=dx*dx; - p=(pixels[3].red-pixels[2].red)-(pixels[0].red-pixels[1].red); - q=(pixels[0].red-pixels[1].red)-p; - r=pixels[2].red-pixels[0].red; - s=pixels[1].red; - pixel->red=(dx*dx2*p)+(dx2*q)+(dx*r)+s; - p=(pixels[3].green-pixels[2].green)-(pixels[0].green-pixels[1].green); - q=(pixels[0].green-pixels[1].green)-p; - r=pixels[2].green-pixels[0].green; - s=pixels[1].green; - pixel->green=(dx*dx2*p)+(dx2*q)+(dx*r)+s; - p=(pixels[3].blue-pixels[2].blue)-(pixels[0].blue-pixels[1].blue); - q=(pixels[0].blue-pixels[1].blue)-p; - r=pixels[2].blue-pixels[0].blue; - s=pixels[1].blue; - pixel->blue=(dx*dx2*p)+(dx2*q)+(dx*r)+s; - p=(pixels[3].opacity-pixels[2].opacity)-(pixels[0].opacity-pixels[1].opacity); - q=(pixels[0].opacity-pixels[1].opacity)-p; - r=pixels[2].opacity-pixels[0].opacity; - s=pixels[1].opacity; - pixel->opacity=(dx*dx2*p)+(dx2*q)+(dx*r)+s; - if (pixel->colorspace == CMYKColorspace) - { - p=(pixels[3].index-pixels[2].index)-(pixels[0].index-pixels[1].index); - q=(pixels[0].index-pixels[1].index)-p; - r=pixels[2].index-pixels[0].index; - s=pixels[1].index; - pixel->index=(dx*dx2*p)+(dx2*q)+(dx*r)+s; - } -} - -static inline MagickRealType CubicWeightingFunction(const MagickRealType x) -{ - MagickRealType - alpha, - gamma; - - alpha=MagickMax(x+2.0,0.0); - gamma=1.0*alpha*alpha*alpha; - alpha=MagickMax(x+1.0,0.0); - gamma-=4.0*alpha*alpha*alpha; - alpha=MagickMax(x+0.0,0.0); - gamma+=6.0*alpha*alpha*alpha; - alpha=MagickMax(x-1.0,0.0); - gamma-=4.0*alpha*alpha*alpha; - return(gamma/6.0); -} - -static inline double MeshInterpolate(const PointInfo *delta,const double p, - const double x,const double y) -{ - return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p); -} - -static inline ssize_t NearestNeighbor(MagickRealType x) -{ - if (x >= 0.0) - return((ssize_t) (x+0.5)); - return((ssize_t) (x-0.5)); -} - -static MagickBooleanType InterpolateResampleFilter( - ResampleFilter *resample_filter,const InterpolatePixelMethod method, - const double x,const double y,MagickPixelPacket *pixel) -{ - MagickBooleanType - status; - - register const IndexPacket - *indexes; - - register const PixelPacket - *p; - - register ssize_t - i; - - assert(resample_filter != (ResampleFilter *) NULL); - assert(resample_filter->signature == MagickSignature); - status=MagickTrue; - - switch (method) - { - case AverageInterpolatePixel: - { - MagickPixelPacket - pixels[16]; - - MagickRealType - alpha[16], - gamma; - - p=GetCacheViewVirtualPixels(resample_filter->view,(ssize_t) floor(x)-1, - (ssize_t) floor(y)-1,4,4,resample_filter->exception); - if (p == (const PixelPacket *) NULL) - { - status=MagickFalse; - break; - } - indexes=GetCacheViewVirtualIndexQueue(resample_filter->view); - for (i=0; i < 16L; i++) - { - GetMagickPixelPacket(resample_filter->image,pixels+i); - SetMagickPixelPacket(resample_filter->image,p,indexes+i,pixels+i); - alpha[i]=1.0; - if (pixels[i].matte != MagickFalse) - { - alpha[i]=QuantumScale*((MagickRealType) GetAlphaPixelComponent(p)); - pixels[i].red*=alpha[i]; - pixels[i].green*=alpha[i]; - pixels[i].blue*=alpha[i]; - if (pixels[i].colorspace == CMYKColorspace) - pixels[i].index*=alpha[i]; - } - gamma=alpha[i]; - gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); - pixel->red+=gamma*0.0625*pixels[i].red; - pixel->green+=gamma*0.0625*pixels[i].green; - pixel->blue+=gamma*0.0625*pixels[i].blue; - pixel->opacity+=0.0625*pixels[i].opacity; - if (pixel->colorspace == CMYKColorspace) - pixel->index+=gamma*0.0625*pixels[i].index; - p++; - } - break; - } - case BicubicInterpolatePixel: - { - MagickPixelPacket - pixels[16], - u[4]; - - MagickRealType - alpha[16]; - - PointInfo - delta; - - p=GetCacheViewVirtualPixels(resample_filter->view,(ssize_t) floor(x)-1, - (ssize_t) floor(y)-1,4,4,resample_filter->exception); - if (p == (const PixelPacket *) NULL) - { - status=MagickFalse; - break; - } - indexes=GetCacheViewVirtualIndexQueue(resample_filter->view); - for (i=0; i < 16L; i++) - { - GetMagickPixelPacket(resample_filter->image,pixels+i); - SetMagickPixelPacket(resample_filter->image,p,indexes+i,pixels+i); - alpha[i]=1.0; - if (pixels[i].matte != MagickFalse) - { - alpha[i]=QuantumScale*((MagickRealType) GetAlphaPixelComponent(p)); - pixels[i].red*=alpha[i]; - pixels[i].green*=alpha[i]; - pixels[i].blue*=alpha[i]; - if (pixels[i].colorspace == CMYKColorspace) - pixels[i].index*=alpha[i]; - } - p++; - } - delta.x=x-floor(x); - for (i=0; i < 4L; i++) - BicubicInterpolate(pixels+4*i,delta.x,u+i); - delta.y=y-floor(y); - BicubicInterpolate(u,delta.y,pixel); - break; - } - case BilinearInterpolatePixel: - default: - { - MagickPixelPacket - pixels[4]; - - MagickRealType - alpha[4], - gamma; - - PointInfo - delta, - epsilon; - - p=GetCacheViewVirtualPixels(resample_filter->view,(ssize_t) floor(x), - (ssize_t) floor(y),2,2,resample_filter->exception); - if (p == (const PixelPacket *) NULL) - { - status=MagickFalse; - break; - } - indexes=GetCacheViewVirtualIndexQueue(resample_filter->view); - for (i=0; i < 4L; i++) - { - GetMagickPixelPacket(resample_filter->image,pixels+i); - pixels[i].red=(MagickRealType) p[i].red; - pixels[i].green=(MagickRealType) p[i].green; - pixels[i].blue=(MagickRealType) p[i].blue; - pixels[i].opacity=(MagickRealType) p[i].opacity; - alpha[i]=1.0; - if (pixels[i].matte != MagickFalse) - { - alpha[i]=QuantumScale*((MagickRealType) QuantumRange-p[i].opacity); - pixels[i].red*=alpha[i]; - pixels[i].green*=alpha[i]; - pixels[i].blue*=alpha[i]; - } - if (indexes != (IndexPacket *) NULL) - { - pixels[i].index=(MagickRealType) indexes[i]; - if (pixels[i].colorspace == CMYKColorspace) - pixels[i].index*=alpha[i]; - } - } - delta.x=x-floor(x); - delta.y=y-floor(y); - epsilon.x=1.0-delta.x; - epsilon.y=1.0-delta.y; - gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y* - (epsilon.x*alpha[2]+delta.x*alpha[3]))); - gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); - pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x* - pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red)); - pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x* - pixels[1].green)+delta.y*(epsilon.x*pixels[2].green+delta.x* - pixels[3].green)); - pixel->blue=gamma*(epsilon.y*(epsilon.x*pixels[0].blue+delta.x* - pixels[1].blue)+delta.y*(epsilon.x*pixels[2].blue+delta.x* - pixels[3].blue)); - pixel->opacity=(epsilon.y*(epsilon.x*pixels[0].opacity+delta.x* - pixels[1].opacity)+delta.y*(epsilon.x*pixels[2].opacity+delta.x* - pixels[3].opacity)); - if (pixel->colorspace == CMYKColorspace) - pixel->index=gamma*(epsilon.y*(epsilon.x*pixels[0].index+delta.x* - pixels[1].index)+delta.y*(epsilon.x*pixels[2].index+delta.x* - pixels[3].index)); - break; - } - case FilterInterpolatePixel: - { - CacheView - *filter_view; - - Image - *excerpt_image, - *filter_image; - - MagickPixelPacket - pixels[1]; - - RectangleInfo - geometry; - - geometry.width=4L; - geometry.height=4L; - geometry.x=(ssize_t) floor(x)-1L; - geometry.y=(ssize_t) floor(y)-1L; - excerpt_image=ExcerptImage(resample_filter->image,&geometry, - resample_filter->exception); - if (excerpt_image == (Image *) NULL) - { - status=MagickFalse; - break; - } - filter_image=ResizeImage(excerpt_image,1,1,resample_filter->image->filter, - resample_filter->image->blur,resample_filter->exception); - excerpt_image=DestroyImage(excerpt_image); - if (filter_image == (Image *) NULL) - break; - filter_view=AcquireCacheView(filter_image); - p=GetCacheViewVirtualPixels(filter_view,0,0,1,1, - resample_filter->exception); - if (p != (const PixelPacket *) NULL) - { - indexes=GetVirtualIndexQueue(filter_image); - GetMagickPixelPacket(resample_filter->image,pixels); - SetMagickPixelPacket(resample_filter->image,p,indexes,pixel); - } - filter_view=DestroyCacheView(filter_view); - filter_image=DestroyImage(filter_image); - break; - } - case IntegerInterpolatePixel: - { - MagickPixelPacket - pixels[1]; - - p=GetCacheViewVirtualPixels(resample_filter->view,(ssize_t) floor(x), - (ssize_t) floor(y),1,1,resample_filter->exception); - if (p == (const PixelPacket *) NULL) - { - status=MagickFalse; - break; - } - indexes=GetCacheViewVirtualIndexQueue(resample_filter->view); - GetMagickPixelPacket(resample_filter->image,pixels); - SetMagickPixelPacket(resample_filter->image,p,indexes,pixel); - break; - } - case MeshInterpolatePixel: - { - MagickPixelPacket - pixels[4]; - - MagickRealType - alpha[4], - gamma; - - PointInfo - delta, - luminance; - - p=GetCacheViewVirtualPixels(resample_filter->view,(ssize_t) floor(x), - (ssize_t) floor(y),2,2,resample_filter->exception); - if (p == (const PixelPacket *) NULL) - { - status=MagickFalse; - break; - } - indexes=GetCacheViewVirtualIndexQueue(resample_filter->view); - for (i=0; i < 4L; i++) - { - GetMagickPixelPacket(resample_filter->image,pixels+i); - SetMagickPixelPacket(resample_filter->image,p,indexes+i,pixels+i); - alpha[i]=1.0; - if (pixels[i].matte != MagickFalse) - { - alpha[i]=QuantumScale*((MagickRealType) GetAlphaPixelComponent(p)); - pixels[i].red*=alpha[i]; - pixels[i].green*=alpha[i]; - pixels[i].blue*=alpha[i]; - if (pixels[i].colorspace == CMYKColorspace) - pixels[i].index*=alpha[i]; - } - p++; - } - delta.x=x-floor(x); - delta.y=y-floor(y); - luminance.x=MagickPixelLuminance(pixels+0)-MagickPixelLuminance(pixels+3); - luminance.y=MagickPixelLuminance(pixels+1)-MagickPixelLuminance(pixels+2); - if (fabs(luminance.x) < fabs(luminance.y)) - { - /* - Diagonal 0-3 NW-SE. - */ - if (delta.x <= delta.y) - { - /* - Bottom-left triangle (pixel:2, diagonal: 0-3). - */ - delta.y=1.0-delta.y; - gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]); - gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); - pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red, - pixels[3].red,pixels[0].red); - pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green, - pixels[3].green,pixels[0].green); - pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue, - pixels[3].blue,pixels[0].blue); - pixel->opacity=gamma*MeshInterpolate(&delta,pixels[2].opacity, - pixels[3].opacity,pixels[0].opacity); - if (pixel->colorspace == CMYKColorspace) - pixel->index=gamma*MeshInterpolate(&delta,pixels[2].index, - pixels[3].index,pixels[0].index); - } - else - { - /* - Top-right triangle (pixel:1, diagonal: 0-3). - */ - delta.x=1.0-delta.x; - gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]); - gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); - pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red, - pixels[0].red,pixels[3].red); - pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green, - pixels[0].green,pixels[3].green); - pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue, - pixels[0].blue,pixels[3].blue); - pixel->opacity=gamma*MeshInterpolate(&delta,pixels[1].opacity, - pixels[0].opacity,pixels[3].opacity); - if (pixel->colorspace == CMYKColorspace) - pixel->index=gamma*MeshInterpolate(&delta,pixels[1].index, - pixels[0].index,pixels[3].index); - } - } - else - { - /* - Diagonal 1-2 NE-SW. - */ - if (delta.x <= (1.0-delta.y)) - { - /* - Top-left triangle (pixel 0, diagonal: 1-2). - */ - gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]); - gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); - pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red, - pixels[1].red,pixels[2].red); - pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green, - pixels[1].green,pixels[2].green); - pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue, - pixels[1].blue,pixels[2].blue); - pixel->opacity=gamma*MeshInterpolate(&delta,pixels[0].opacity, - pixels[1].opacity,pixels[2].opacity); - if (pixel->colorspace == CMYKColorspace) - pixel->index=gamma*MeshInterpolate(&delta,pixels[0].index, - pixels[1].index,pixels[2].index); - } - else - { - /* - Bottom-right triangle (pixel: 3, diagonal: 1-2). - */ - delta.x=1.0-delta.x; - delta.y=1.0-delta.y; - gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]); - gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); - pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red, - pixels[2].red,pixels[1].red); - pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green, - pixels[2].green,pixels[1].green); - pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue, - pixels[2].blue,pixels[1].blue); - pixel->opacity=gamma*MeshInterpolate(&delta,pixels[3].opacity, - pixels[2].opacity,pixels[1].opacity); - if (pixel->colorspace == CMYKColorspace) - pixel->index=gamma*MeshInterpolate(&delta,pixels[3].index, - pixels[2].index,pixels[1].index); - } - } - break; - } - case NearestNeighborInterpolatePixel: - { - MagickPixelPacket - pixels[1]; - - p=GetCacheViewVirtualPixels(resample_filter->view,NearestNeighbor(x), - NearestNeighbor(y),1,1,resample_filter->exception); - if (p == (const PixelPacket *) NULL) - { - status=MagickFalse; - break; - } - indexes=GetCacheViewVirtualIndexQueue(resample_filter->view); - GetMagickPixelPacket(resample_filter->image,pixels); - SetMagickPixelPacket(resample_filter->image,p,indexes,pixel); - break; - } - case SplineInterpolatePixel: - { - MagickPixelPacket - pixels[16]; - - MagickRealType - alpha[16], - dx, - dy, - gamma; - - PointInfo - delta; - - ssize_t - j, - n; - - p=GetCacheViewVirtualPixels(resample_filter->view,(ssize_t) floor(x)-1, - (ssize_t) floor(y)-1,4,4,resample_filter->exception); - if (p == (const PixelPacket *) NULL) - { - status=MagickFalse; - break; - } - indexes=GetCacheViewVirtualIndexQueue(resample_filter->view); - n=0; - delta.x=x-floor(x); - delta.y=y-floor(y); - for (i=(-1); i < 3L; i++) - { - dy=CubicWeightingFunction((MagickRealType) i-delta.y); - for (j=(-1); j < 3L; j++) - { - GetMagickPixelPacket(resample_filter->image,pixels+n); - SetMagickPixelPacket(resample_filter->image,p,indexes+n,pixels+n); - alpha[n]=1.0; - if (pixels[i].matte != MagickFalse) - { - alpha[n]=QuantumScale*((MagickRealType) - GetAlphaPixelComponent(p)); - pixels[n].red*=alpha[n]; - pixels[n].green*=alpha[n]; - pixels[n].blue*=alpha[n]; - if (pixels[i].colorspace == CMYKColorspace) - pixels[n].index*=alpha[n]; - } - dx=CubicWeightingFunction(delta.x-(MagickRealType) j); - gamma=alpha[n]; - gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma); - pixel->red+=gamma*dx*dy*pixels[n].red; - pixel->green+=gamma*dx*dy*pixels[n].green; - pixel->blue+=gamma*dx*dy*pixels[n].blue; - if (pixel->matte != MagickFalse) - pixel->opacity+=dx*dy*pixels[n].opacity; - if (pixel->colorspace == CMYKColorspace) - pixel->index+=gamma*dx*dy*pixels[n].index; - n++; - p++; - } - } - break; - } - } - return(status); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % % R e s a m p l e P i x e l C o l o r % % % % % @@ -900,8 +332,9 @@ MagickExport MagickBooleanType ResamplePixelColor( status=MagickTrue; GetMagickPixelPacket(resample_filter->image,pixel); if ( resample_filter->do_interpolate ) { - status=InterpolateResampleFilter(resample_filter, - resample_filter->interpolate,u0,v0,pixel); + status=InterpolatePixelPacket(resample_filter->image, + resample_filter->view,resample_filter->interpolate,u0,v0,pixel, + resample_filter->exception); return(status); } @@ -977,8 +410,9 @@ MagickExport MagickBooleanType ResamplePixelColor( } if ( hit ) { /* whole area is a solid color -- just return that color */ - status=InterpolateResampleFilter(resample_filter,IntegerInterpolatePixel, - u0,v0,pixel); + status=InterpolatePixelPacket(resample_filter->image, + resample_filter->view,IntegerInterpolatePixel,u0,v0,pixel, + resample_filter->exception); return(status); } @@ -1006,14 +440,16 @@ MagickExport MagickBooleanType ResamplePixelColor( works well in general, but falls down for TileEdge methods. This needs to be done properly!!!!!! */ - status=InterpolateResampleFilter(resample_filter, - AverageInterpolatePixel,u0,v0,pixel); + status=InterpolatePixelPacket(resample_filter->image, + resample_filter->view,AverageInterpolatePixel,u0,v0,pixel, + resample_filter->exception); break; case HorizontalTileVirtualPixelMethod: case VerticalTileVirtualPixelMethod: /* just return the background pixel - Is there more direct way? */ - status=InterpolateResampleFilter(resample_filter, - IntegerInterpolatePixel,(double)-1,(double)-1,pixel); + status=InterpolatePixelPacket(resample_filter->image, + resample_filter->view,IntegerInterpolatePixel,-1.0,-1.0,pixel, + resample_filter->exception); break; case TileVirtualPixelMethod: case MirrorVirtualPixelMethod: @@ -1210,8 +646,9 @@ MagickExport MagickBooleanType ResamplePixelColor( pixel->opacity = pixel->red = pixel->green = pixel->blue = 0; pixel->red = QuantumRange; /* show pixels for which EWA fails */ #else - status=InterpolateResampleFilter(resample_filter, - resample_filter->interpolate,u0,v0,pixel); + status=InterpolatePixelPacket(resample_filter->image, + resample_filter->view,resample_filter->interpolate,u0,v0,pixel, + resample_filter->exception); #endif return status; } diff --git a/magick/resample.h b/magick/resample.h index 07a817372..98e2cf669 100644 --- a/magick/resample.h +++ b/magick/resample.h @@ -25,10 +25,9 @@ extern "C" { #include /* - WARNING: The order of this table must also match the order - of a table located in AcquireResizeFilter() or "resize.c" - Otherwise the users filter will not match the actual filter - that is setup. + WARNING: The order of this table must also match the order of a table + located in AcquireResizeFilter() or "resize.c" otherwise the users filter + will not match the actual filter that is setup. */ typedef enum { @@ -69,19 +68,6 @@ typedef enum */ #define BesselFilter JincFilter -typedef enum -{ - UndefinedInterpolatePixel, - AverageInterpolatePixel, - BicubicInterpolatePixel, - BilinearInterpolatePixel, - FilterInterpolatePixel, - IntegerInterpolatePixel, - MeshInterpolatePixel, - NearestNeighborInterpolatePixel, - SplineInterpolatePixel -} InterpolatePixelMethod; - typedef struct _ResampleFilter ResampleFilter; diff --git a/magick/resize.c b/magick/resize.c index dd89256d8..802f869a7 100644 --- a/magick/resize.c +++ b/magick/resize.c @@ -1130,6 +1130,7 @@ MagickExport Image *AdaptiveResizeImage(const Image *image, #define AdaptiveResizeImageTag "Resize/Image" CacheView + *image_view, *resize_view; Image @@ -1141,9 +1142,6 @@ MagickExport Image *AdaptiveResizeImage(const Image *image, MagickOffsetType progress; - ResampleFilter - **resample_filter; - ssize_t y; @@ -1171,17 +1169,13 @@ MagickExport Image *AdaptiveResizeImage(const Image *image, } status=MagickTrue; progress=0; - resample_filter=AcquireResampleFilterThreadSet(image, - UndefinedVirtualPixelMethod,MagickTrue,exception); + image_view=AcquireCacheView(image); resize_view=AcquireCacheView(resize_image); #if defined(MAGICKCORE_OPENMP_SUPPORT) #pragma omp parallel for schedule(dynamic,4) shared(progress,status) omp_throttle(1) #endif for (y=0; y < (ssize_t) resize_image->rows; y++) { - const int - id = GetOpenMPThreadId(); - MagickPixelPacket pixel; @@ -1209,8 +1203,8 @@ MagickExport Image *AdaptiveResizeImage(const Image *image, for (x=0; x < (ssize_t) resize_image->columns; x++) { offset.x=((MagickRealType) x*image->columns/resize_image->columns); - (void) ResamplePixelColor(resample_filter[id],offset.x-0.5,offset.y-0.5, - &pixel); + (void) InterpolatePixelPacket(image,image_view,image->interpolate, + offset.x-0.5,offset.y-0.5,&pixel,exception); SetPixelPacket(resize_image,&pixel,q,resize_indexes+x); q++; } @@ -1230,8 +1224,8 @@ MagickExport Image *AdaptiveResizeImage(const Image *image, status=MagickFalse; } } - resample_filter=DestroyResampleFilterThreadSet(resample_filter); resize_view=DestroyCacheView(resize_view); + image_view=DestroyCacheView(image_view); if (status == MagickFalse) resize_image=DestroyImage(resize_image); return(resize_image); -- 2.40.0