00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "magick/studio.h"
00044 #include "magick/artifact.h"
00045 #include "magick/color-private.h"
00046 #include "magick/cache.h"
00047 #include "magick/draw.h"
00048 #include "magick/exception-private.h"
00049 #include "magick/gem.h"
00050 #include "magick/image.h"
00051 #include "magick/image-private.h"
00052 #include "magick/log.h"
00053 #include "magick/memory_.h"
00054 #include "magick/pixel-private.h"
00055 #include "magick/quantum.h"
00056 #include "magick/random_.h"
00057 #include "magick/resample.h"
00058 #include "magick/resize.h"
00059 #include "magick/resize-private.h"
00060 #include "magick/transform.h"
00061 #include "magick/signature-private.h"
00062
00063
00064
00065 #define WLUT_WIDTH 1024
00066 struct _ResampleFilter
00067 {
00068 Image
00069 *image;
00070
00071 ViewInfo
00072 *view;
00073
00074 ExceptionInfo
00075 *exception;
00076
00077 MagickBooleanType
00078 debug;
00079
00080
00081 long
00082 image_area;
00083
00084 InterpolatePixelMethod
00085 interpolate;
00086
00087 VirtualPixelMethod
00088 virtual_pixel;
00089
00090 FilterTypes
00091 filter;
00092
00093
00094 MagickBooleanType
00095 limit_reached,
00096 do_interpolate,
00097 average_defined;
00098
00099 MagickPixelPacket
00100 average_pixel;
00101
00102
00103 double
00104 A, B, C,
00105 sqrtA, sqrtC, sqrtU, slope;
00106
00107
00108 double
00109 filter_lut[WLUT_WIDTH],
00110 support;
00111
00112 unsigned long
00113 signature;
00114 };
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 MagickExport ResampleFilter *AcquireResampleFilter(const Image *image,
00169 ExceptionInfo *exception)
00170 {
00171 register ResampleFilter
00172 *resample_filter;
00173
00174 assert(image != (Image *) NULL);
00175 assert(image->signature == MagickSignature);
00176 if (image->debug != MagickFalse)
00177 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00178 assert(exception != (ExceptionInfo *) NULL);
00179 assert(exception->signature == MagickSignature);
00180
00181 resample_filter=(ResampleFilter *) AcquireMagickMemory(
00182 sizeof(*resample_filter));
00183 if (resample_filter == (ResampleFilter *) NULL)
00184 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00185 (void) ResetMagickMemory(resample_filter,0,sizeof(*resample_filter));
00186
00187 resample_filter->image=ReferenceImage((Image *) image);
00188 resample_filter->view=AcquireCacheView(resample_filter->image);
00189 resample_filter->exception=exception;
00190
00191 resample_filter->debug=IsEventLogging();
00192 resample_filter->signature=MagickSignature;
00193
00194 resample_filter->image_area = (long) resample_filter->image->columns *
00195 resample_filter->image->rows;
00196 resample_filter->average_defined = MagickFalse;
00197
00198
00199 SetResampleFilter(resample_filter, resample_filter->image->filter,
00200 resample_filter->image->blur);
00201 resample_filter->interpolate = resample_filter->image->interpolate;
00202 resample_filter->virtual_pixel=GetImageVirtualPixelMethod(image);
00203
00204
00205 ScaleResampleFilter(resample_filter, 1.0, 0.0, 0.0, 1.0);
00206
00207 return(resample_filter);
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 MagickExport ResampleFilter *DestroyResampleFilter(
00235 ResampleFilter *resample_filter)
00236 {
00237 assert(resample_filter != (ResampleFilter *) NULL);
00238 assert(resample_filter->signature == MagickSignature);
00239 assert(resample_filter->image != (Image *) NULL);
00240 if (resample_filter->debug != MagickFalse)
00241 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
00242 resample_filter->image->filename);
00243 resample_filter->view=DestroyCacheView(resample_filter->view);
00244 resample_filter->image=DestroyImage(resample_filter->image);
00245 resample_filter->signature=(~MagickSignature);
00246 resample_filter=(ResampleFilter *) RelinquishMagickMemory(resample_filter);
00247 return(resample_filter);
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 static inline double MagickMax(const double x,const double y)
00285 {
00286 if (x > y)
00287 return(x);
00288 return(y);
00289 }
00290
00291 static void BicubicInterpolate(const MagickPixelPacket *pixels,const double dx,
00292 MagickPixelPacket *pixel)
00293 {
00294 MagickRealType
00295 dx2,
00296 p,
00297 q,
00298 r,
00299 s;
00300
00301 dx2=dx*dx;
00302 p=(pixels[3].red-pixels[2].red)-(pixels[0].red-pixels[1].red);
00303 q=(pixels[0].red-pixels[1].red)-p;
00304 r=pixels[2].red-pixels[0].red;
00305 s=pixels[1].red;
00306 pixel->red=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
00307 p=(pixels[3].green-pixels[2].green)-(pixels[0].green-pixels[1].green);
00308 q=(pixels[0].green-pixels[1].green)-p;
00309 r=pixels[2].green-pixels[0].green;
00310 s=pixels[1].green;
00311 pixel->green=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
00312 p=(pixels[3].blue-pixels[2].blue)-(pixels[0].blue-pixels[1].blue);
00313 q=(pixels[0].blue-pixels[1].blue)-p;
00314 r=pixels[2].blue-pixels[0].blue;
00315 s=pixels[1].blue;
00316 pixel->blue=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
00317 p=(pixels[3].opacity-pixels[2].opacity)-(pixels[0].opacity-pixels[1].opacity);
00318 q=(pixels[0].opacity-pixels[1].opacity)-p;
00319 r=pixels[2].opacity-pixels[0].opacity;
00320 s=pixels[1].opacity;
00321 pixel->opacity=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
00322 if (pixel->colorspace == CMYKColorspace)
00323 {
00324 p=(pixels[3].index-pixels[2].index)-(pixels[0].index-pixels[1].index);
00325 q=(pixels[0].index-pixels[1].index)-p;
00326 r=pixels[2].index-pixels[0].index;
00327 s=pixels[1].index;
00328 pixel->index=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
00329 }
00330 }
00331
00332 static inline MagickRealType CubicWeightingFunction(const MagickRealType x)
00333 {
00334 MagickRealType
00335 alpha,
00336 gamma;
00337
00338 alpha=MagickMax(x+2.0,0.0);
00339 gamma=1.0*alpha*alpha*alpha;
00340 alpha=MagickMax(x+1.0,0.0);
00341 gamma-=4.0*alpha*alpha*alpha;
00342 alpha=MagickMax(x+0.0,0.0);
00343 gamma+=6.0*alpha*alpha*alpha;
00344 alpha=MagickMax(x-1.0,0.0);
00345 gamma-=4.0*alpha*alpha*alpha;
00346 return(gamma/6.0);
00347 }
00348
00349 static inline double MeshInterpolate(const PointInfo *delta,const double p,
00350 const double x,const double y)
00351 {
00352 return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
00353 }
00354
00355 static inline long NearestNeighbor(MagickRealType x)
00356 {
00357 if (x >= 0.0)
00358 return((long) (x+0.5));
00359 return((long) (x-0.5));
00360 }
00361
00362 static MagickBooleanType InterpolateResampleFilter(
00363 ResampleFilter *resample_filter,const InterpolatePixelMethod method,
00364 const double x,const double y,MagickPixelPacket *pixel)
00365 {
00366 MagickBooleanType
00367 status;
00368
00369 register const IndexPacket
00370 *indexes;
00371
00372 register const PixelPacket
00373 *p;
00374
00375 register long
00376 i;
00377
00378 assert(resample_filter != (ResampleFilter *) NULL);
00379 assert(resample_filter->signature == MagickSignature);
00380 status=MagickTrue;
00381 switch (method)
00382 {
00383 case AverageInterpolatePixel:
00384 {
00385 MagickPixelPacket
00386 pixels[16];
00387
00388 MagickRealType
00389 alpha[16],
00390 gamma;
00391
00392 GetMagickPixelPacket(resample_filter->image,pixel);
00393 p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x)-1,(long)
00394 floor(y)-1,4,4,resample_filter->exception);
00395 if (p == (const PixelPacket *) NULL)
00396 {
00397 status=MagickFalse;
00398 break;
00399 }
00400 indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
00401 for (i=0; i < 16L; i++)
00402 {
00403 GetMagickPixelPacket(resample_filter->image,pixels+i);
00404 SetMagickPixelPacket(resample_filter->image,p,indexes+i,pixels+i);
00405 alpha[i]=1.0;
00406 if (resample_filter->image->matte != MagickFalse)
00407 {
00408 alpha[i]=QuantumScale*((MagickRealType) QuantumRange-p->opacity);
00409 pixels[i].red*=alpha[i];
00410 pixels[i].green*=alpha[i];
00411 pixels[i].blue*=alpha[i];
00412 if (resample_filter->image->colorspace == CMYKColorspace)
00413 pixels[i].index*=alpha[i];
00414 }
00415 gamma=alpha[i];
00416 gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
00417 pixel->red+=gamma*0.0625*pixels[i].red;
00418 pixel->green+=gamma*0.0625*pixels[i].green;
00419 pixel->blue+=gamma*0.0625*pixels[i].blue;
00420 pixel->opacity+=0.0625*pixels[i].opacity;
00421 if (resample_filter->image->colorspace == CMYKColorspace)
00422 pixel->index+=gamma*0.0625*pixels[i].index;
00423 p++;
00424 }
00425 break;
00426 }
00427 case BicubicInterpolatePixel:
00428 {
00429 MagickPixelPacket
00430 pixels[16],
00431 u[4];
00432
00433 MagickRealType
00434 alpha[16];
00435
00436 PointInfo
00437 delta;
00438
00439 GetMagickPixelPacket(resample_filter->image,pixel);
00440 p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x)-1,(long)
00441 floor(y)-1,4,4,resample_filter->exception);
00442 if (p == (const PixelPacket *) NULL)
00443 {
00444 status=MagickFalse;
00445 break;
00446 }
00447 indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
00448 for (i=0; i < 16L; i++)
00449 {
00450 GetMagickPixelPacket(resample_filter->image,pixels+i);
00451 SetMagickPixelPacket(resample_filter->image,p,indexes+i,pixels+i);
00452 alpha[i]=1.0;
00453 if (resample_filter->image->matte != MagickFalse)
00454 {
00455 alpha[i]=QuantumScale*((MagickRealType) QuantumRange-p->opacity);
00456 pixels[i].red*=alpha[i];
00457 pixels[i].green*=alpha[i];
00458 pixels[i].blue*=alpha[i];
00459 if (resample_filter->image->colorspace == CMYKColorspace)
00460 pixels[i].index*=alpha[i];
00461 }
00462 p++;
00463 }
00464 delta.x=x-floor(x);
00465 for (i=0; i < 4L; i++)
00466 BicubicInterpolate(pixels+4*i,delta.x,u+i);
00467 delta.y=y-floor(y);
00468 BicubicInterpolate(u,delta.y,pixel);
00469 break;
00470 }
00471 case BilinearInterpolatePixel:
00472 default:
00473 {
00474 MagickPixelPacket
00475 pixels[4];
00476
00477 MagickRealType
00478 alpha[4],
00479 gamma;
00480
00481 PointInfo
00482 delta;
00483
00484 p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x),(long)
00485 floor(y),2,2,resample_filter->exception);
00486 if (p == (const PixelPacket *) NULL)
00487 {
00488 status=MagickFalse;
00489 break;
00490 }
00491 indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
00492 for (i=0; i < 4L; i++)
00493 {
00494 pixels[i].red=(MagickRealType) p[i].red;
00495 pixels[i].green=(MagickRealType) p[i].green;
00496 pixels[i].blue=(MagickRealType) p[i].blue;
00497 pixels[i].opacity=(MagickRealType) p[i].opacity;
00498 alpha[i]=1.0;
00499 }
00500 if (resample_filter->image->matte != MagickFalse)
00501 for (i=0; i < 4L; i++)
00502 {
00503 alpha[i]=QuantumScale*((MagickRealType) QuantumRange-p[i].opacity);
00504 pixels[i].red*=alpha[i];
00505 pixels[i].green*=alpha[i];
00506 pixels[i].blue*=alpha[i];
00507 }
00508 if (indexes != (IndexPacket *) NULL)
00509 for (i=0; i < 4L; i++)
00510 {
00511 pixels[i].index=(MagickRealType) indexes[i];
00512 if (resample_filter->image->colorspace == CMYKColorspace)
00513 pixels[i].index*=alpha[i];
00514 }
00515 delta.x=x-floor(x);
00516 delta.y=y-floor(y);
00517 gamma=(((1.0-delta.y)*((1.0-delta.x)*alpha[0]+delta.x*alpha[1])+delta.y*
00518 ((1.0-delta.x)*alpha[2]+delta.x*alpha[3])));
00519 gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
00520 pixel->red=gamma*((1.0-delta.y)*((1.0-delta.x)*pixels[0].red+delta.x*
00521 pixels[1].red)+delta.y*((1.0-delta.x)*pixels[2].red+delta.x*
00522 pixels[3].red));
00523 pixel->green=gamma*((1.0-delta.y)*((1.0-delta.x)*pixels[0].green+delta.x*
00524 pixels[1].green)+delta.y*((1.0-delta.x)*pixels[2].green+
00525 delta.x*pixels[3].green));
00526 pixel->blue=gamma*((1.0-delta.y)*((1.0-delta.x)*pixels[0].blue+delta.x*
00527 pixels[1].blue)+delta.y*((1.0-delta.x)*pixels[2].blue+delta.x*
00528 pixels[3].blue));
00529 pixel->opacity=((1.0-delta.y)*((1.0-delta.x)*pixels[0].opacity+delta.x*
00530 pixels[1].opacity)+delta.y*((1.0-delta.x)*pixels[2].opacity+delta.x*
00531 pixels[3].opacity));
00532 if (resample_filter->image->colorspace == CMYKColorspace)
00533 pixel->index=gamma*((1.0-delta.y)*((1.0-delta.x)*pixels[0].index+
00534 delta.x*pixels[1].index)+delta.y*((1.0-delta.x)*pixels[2].index+
00535 delta.x*pixels[3].index));
00536 break;
00537 }
00538 case FilterInterpolatePixel:
00539 {
00540 Image
00541 *excerpt_image,
00542 *filter_image;
00543
00544 MagickPixelPacket
00545 pixels[1];
00546
00547 RectangleInfo
00548 geometry;
00549
00550 ViewInfo
00551 *filter_view;
00552
00553 GetMagickPixelPacket(resample_filter->image,pixel);
00554 geometry.width=4L;
00555 geometry.height=4L;
00556 geometry.x=(long) floor(x)-1L;
00557 geometry.y=(long) floor(y)-1L;
00558 excerpt_image=ExcerptImage(resample_filter->image,&geometry,
00559 resample_filter->exception);
00560 if (excerpt_image == (Image *) NULL)
00561 {
00562 status=MagickFalse;
00563 break;
00564 }
00565 filter_image=ResizeImage(excerpt_image,1,1,resample_filter->image->filter,
00566 resample_filter->image->blur,resample_filter->exception);
00567 excerpt_image=DestroyImage(excerpt_image);
00568 if (filter_image == (Image *) NULL)
00569 break;
00570 filter_view=AcquireCacheView(filter_image);
00571 p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,
00572 resample_filter->exception);
00573 if (p != (const PixelPacket *) NULL)
00574 {
00575 indexes=GetVirtualIndexQueue(filter_image);
00576 GetMagickPixelPacket(resample_filter->image,pixels);
00577 SetMagickPixelPacket(resample_filter->image,p,indexes,pixel);
00578 }
00579 filter_view=DestroyCacheView(filter_view);
00580 filter_image=DestroyImage(filter_image);
00581 break;
00582 }
00583 case IntegerInterpolatePixel:
00584 {
00585 MagickPixelPacket
00586 pixels[1];
00587
00588 GetMagickPixelPacket(resample_filter->image,pixel);
00589 p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x),(long)
00590 floor(y),1,1,resample_filter->exception);
00591 if (p == (const PixelPacket *) NULL)
00592 {
00593 status=MagickFalse;
00594 break;
00595 }
00596 indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
00597 GetMagickPixelPacket(resample_filter->image,pixels);
00598 SetMagickPixelPacket(resample_filter->image,p,indexes,pixel);
00599 break;
00600 }
00601 case MeshInterpolatePixel:
00602 {
00603 MagickPixelPacket
00604 pixels[4];
00605
00606 MagickRealType
00607 alpha[4],
00608 gamma;
00609
00610 PointInfo
00611 delta,
00612 luminance;
00613
00614 GetMagickPixelPacket(resample_filter->image,pixel);
00615 p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x),(long)
00616 floor(y),2,2,resample_filter->exception);
00617 if (p == (const PixelPacket *) NULL)
00618 {
00619 status=MagickFalse;
00620 break;
00621 }
00622 indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
00623 for (i=0; i < 4L; i++)
00624 {
00625 GetMagickPixelPacket(resample_filter->image,pixels+i);
00626 SetMagickPixelPacket(resample_filter->image,p,indexes+i,pixels+i);
00627 alpha[i]=1.0;
00628 if (resample_filter->image->matte != MagickFalse)
00629 {
00630 alpha[i]=QuantumScale*((MagickRealType) QuantumRange-p->opacity);
00631 pixels[i].red*=alpha[i];
00632 pixels[i].green*=alpha[i];
00633 pixels[i].blue*=alpha[i];
00634 if (resample_filter->image->colorspace == CMYKColorspace)
00635 pixels[i].index*=alpha[i];
00636 }
00637 p++;
00638 }
00639 delta.x=x-floor(x);
00640 delta.y=y-floor(y);
00641 luminance.x=MagickPixelLuminance(pixels+0)-MagickPixelLuminance(pixels+3);
00642 luminance.y=MagickPixelLuminance(pixels+1)-MagickPixelLuminance(pixels+2);
00643 if (fabs(luminance.x) < fabs(luminance.y))
00644 {
00645
00646
00647
00648 if (delta.x <= delta.y)
00649 {
00650
00651
00652
00653 delta.y=1.0-delta.y;
00654 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
00655 gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
00656 pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
00657 pixels[3].red,pixels[0].red);
00658 pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
00659 pixels[3].green,pixels[0].green);
00660 pixel->blue=gamma*MeshInterpolate(&delta,pixels[2].blue,
00661 pixels[3].blue,pixels[0].blue);
00662 pixel->opacity=gamma*MeshInterpolate(&delta,pixels[2].opacity,
00663 pixels[3].opacity,pixels[0].opacity);
00664 if (resample_filter->image->colorspace == CMYKColorspace)
00665 pixel->index=gamma*MeshInterpolate(&delta,pixels[2].index,
00666 pixels[3].index,pixels[0].index);
00667 }
00668 else
00669 {
00670
00671
00672
00673 delta.x=1.0-delta.x;
00674 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
00675 gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
00676 pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
00677 pixels[0].red,pixels[3].red);
00678 pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
00679 pixels[0].green,pixels[3].green);
00680 pixel->blue=gamma*MeshInterpolate(&delta,pixels[1].blue,
00681 pixels[0].blue,pixels[3].blue);
00682 pixel->opacity=gamma*MeshInterpolate(&delta,pixels[1].opacity,
00683 pixels[0].opacity,pixels[3].opacity);
00684 if (resample_filter->image->colorspace == CMYKColorspace)
00685 pixel->index=gamma*MeshInterpolate(&delta,pixels[1].index,
00686 pixels[0].index,pixels[3].index);
00687 }
00688 }
00689 else
00690 {
00691
00692
00693
00694 if (delta.x <= (1.0-delta.y))
00695 {
00696
00697
00698
00699 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
00700 gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
00701 pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
00702 pixels[1].red,pixels[2].red);
00703 pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
00704 pixels[1].green,pixels[2].green);
00705 pixel->blue=gamma*MeshInterpolate(&delta,pixels[0].blue,
00706 pixels[1].blue,pixels[2].blue);
00707 pixel->opacity=gamma*MeshInterpolate(&delta,pixels[0].opacity,
00708 pixels[1].opacity,pixels[2].opacity);
00709 if (resample_filter->image->colorspace == CMYKColorspace)
00710 pixel->index=gamma*MeshInterpolate(&delta,pixels[0].index,
00711 pixels[1].index,pixels[2].index);
00712 }
00713 else
00714 {
00715
00716
00717
00718 delta.x=1.0-delta.x;
00719 delta.y=1.0-delta.y;
00720 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
00721 gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
00722 pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
00723 pixels[2].red,pixels[1].red);
00724 pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
00725 pixels[2].green,pixels[1].green);
00726 pixel->blue=gamma*MeshInterpolate(&delta,pixels[3].blue,
00727 pixels[2].blue,pixels[1].blue);
00728 pixel->opacity=gamma*MeshInterpolate(&delta,pixels[3].opacity,
00729 pixels[2].opacity,pixels[1].opacity);
00730 if (resample_filter->image->colorspace == CMYKColorspace)
00731 pixel->index=gamma*MeshInterpolate(&delta,pixels[3].index,
00732 pixels[2].index,pixels[1].index);
00733 }
00734 }
00735 break;
00736 }
00737 case NearestNeighborInterpolatePixel:
00738 {
00739 MagickPixelPacket
00740 pixels[1];
00741
00742 GetMagickPixelPacket(resample_filter->image,pixel);
00743 p=GetCacheViewVirtualPixels(resample_filter->view,NearestNeighbor(x),
00744 NearestNeighbor(y),1,1,resample_filter->exception);
00745 if (p == (const PixelPacket *) NULL)
00746 {
00747 status=MagickFalse;
00748 break;
00749 }
00750 indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
00751 GetMagickPixelPacket(resample_filter->image,pixels);
00752 SetMagickPixelPacket(resample_filter->image,p,indexes,pixel);
00753 break;
00754 }
00755 case SplineInterpolatePixel:
00756 {
00757 long
00758 j,
00759 n;
00760
00761 MagickPixelPacket
00762 pixels[16];
00763
00764 MagickRealType
00765 alpha[16],
00766 dx,
00767 dy,
00768 gamma;
00769
00770 PointInfo
00771 delta;
00772
00773 GetMagickPixelPacket(resample_filter->image,pixel);
00774 p=GetCacheViewVirtualPixels(resample_filter->view,(long) floor(x)-1,(long)
00775 floor(y)-1,4,4,resample_filter->exception);
00776 if (p == (const PixelPacket *) NULL)
00777 {
00778 status=MagickFalse;
00779 break;
00780 }
00781 indexes=GetCacheViewVirtualIndexQueue(resample_filter->view);
00782 n=0;
00783 delta.x=x-floor(x);
00784 delta.y=y-floor(y);
00785 for (i=(-1); i < 3L; i++)
00786 {
00787 dy=CubicWeightingFunction((MagickRealType) i-delta.y);
00788 for (j=(-1); j < 3L; j++)
00789 {
00790 GetMagickPixelPacket(resample_filter->image,pixels+n);
00791 SetMagickPixelPacket(resample_filter->image,p,indexes+n,pixels+n);
00792 alpha[n]=1.0;
00793 if (resample_filter->image->matte != MagickFalse)
00794 {
00795 alpha[n]=QuantumScale*((MagickRealType) QuantumRange-p->opacity);
00796 pixels[n].red*=alpha[n];
00797 pixels[n].green*=alpha[n];
00798 pixels[n].blue*=alpha[n];
00799 if (resample_filter->image->colorspace == CMYKColorspace)
00800 pixels[n].index*=alpha[n];
00801 }
00802 dx=CubicWeightingFunction(delta.x-(MagickRealType) j);
00803 gamma=alpha[n];
00804 gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
00805 pixel->red+=gamma*dx*dy*pixels[n].red;
00806 pixel->green+=gamma*dx*dy*pixels[n].green;
00807 pixel->blue+=gamma*dx*dy*pixels[n].blue;
00808 if (resample_filter->image->matte != MagickFalse)
00809 pixel->opacity+=dx*dy*pixels[n].opacity;
00810 if (resample_filter->image->colorspace == CMYKColorspace)
00811 pixel->index+=gamma*dx*dy*pixels[n].index;
00812 n++;
00813 p++;
00814 }
00815 }
00816 break;
00817 }
00818 }
00819 return(status);
00820 }
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853 MagickExport MagickBooleanType ResamplePixelColor(
00854 ResampleFilter *resample_filter,const double u0,const double v0,
00855 MagickPixelPacket *pixel)
00856 {
00857 MagickBooleanType
00858 status;
00859
00860 long u,v, uw,v1,v2, hit;
00861 double u1;
00862 double U,V,Q,DQ,DDQ;
00863 double divisor_c,divisor_m;
00864 register double weight;
00865 register const PixelPacket *pixels;
00866 register const IndexPacket *indexes;
00867 assert(resample_filter != (ResampleFilter *) NULL);
00868 assert(resample_filter->signature == MagickSignature);
00869
00870 if ( resample_filter->do_interpolate ) {
00871 status=InterpolateResampleFilter(resample_filter,
00872 resample_filter->interpolate,u0,v0,pixel);
00873 return(status);
00874 }
00875
00876
00877
00878
00879
00880 status=MagickTrue;
00881 GetMagickPixelPacket(resample_filter->image,pixel);
00882 hit = 0;
00883 switch ( resample_filter->virtual_pixel ) {
00884 case BackgroundVirtualPixelMethod:
00885 case ConstantVirtualPixelMethod:
00886 case TransparentVirtualPixelMethod:
00887 case BlackVirtualPixelMethod:
00888 case GrayVirtualPixelMethod:
00889 case WhiteVirtualPixelMethod:
00890 case MaskVirtualPixelMethod:
00891 if ( resample_filter->limit_reached
00892 || u0 + resample_filter->sqrtC < 0.0
00893 || u0 - resample_filter->sqrtC > (double) resample_filter->image->columns
00894 || v0 + resample_filter->sqrtA < 0.0
00895 || v0 - resample_filter->sqrtA > (double) resample_filter->image->rows
00896 )
00897 hit++;
00898 break;
00899
00900 case UndefinedVirtualPixelMethod:
00901 case EdgeVirtualPixelMethod:
00902 if ( ( u0 + resample_filter->sqrtC < 0.0 && v0 + resample_filter->sqrtA < 0.0 )
00903 || ( u0 + resample_filter->sqrtC < 0.0
00904 && v0 - resample_filter->sqrtA > (double) resample_filter->image->rows )
00905 || ( u0 - resample_filter->sqrtC > (double) resample_filter->image->columns
00906 && v0 + resample_filter->sqrtA < 0.0 )
00907 || ( u0 - resample_filter->sqrtC > (double) resample_filter->image->columns
00908 && v0 - resample_