Sarke
Sarke

Reputation: 3235

Difference between Imagick::thumbnailImage() and Imagick::adaptiveResizeImage()

First off, I know Imagick::resizeImage gives me more options.

Could anyone tell me which filters the two methods use?

They seem to create almost identical images, except that (on my test image) the thumbnailImage() one is shifted one pixel top-left.

UPDATE

I have found that these two methods are ImageMagick's MagickThumbnailImage and MagickAdaptiveResizeImage. Their documentation does not specify which filters are used.

Upvotes: 0

Views: 1155

Answers (1)

Danack
Danack

Reputation: 25711

The chain of calls made to with thumbnailImage are MagickThumbnailImage -> ResizeImage where a filter type of LanczosFilter appears to be set as the default (unless somehow the image has a filter associated with it).

The chain of calls for adaptiveResize image is MagickAdaptiveResizeImage -> AdaptiveResizeImage -> InterpolativeResizeImage(image,columns,rows,MeshInterpolatePixel) -> InterpolateMagickPixelPacket

The code inside InterpolateMagickPixelPacket for the 'mesh interpolate pixel' type is below.

case MeshInterpolatePixel:
{
  PointInfo
    delta,
    luma;

  p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,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);
    AlphaBlendMagickPixelPacket(image,p+i,indexes+i,pixels+i,alpha+i);
  }
  delta.x=x-x_offset;
  delta.y=y-y_offset;
  luma.x=fabs(MagickPixelLuma(pixels+0)-MagickPixelLuma(pixels+3));
  luma.y=fabs(MagickPixelLuma(pixels+1)-MagickPixelLuma(pixels+2));
  if (luma.x < luma.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=PerceptibleReciprocal(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);
          if (image->colorspace == CMYKColorspace)
            pixel->index=gamma*MeshInterpolate(&delta,pixels[2].index,
              pixels[3].index,pixels[0].index);
          gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
          pixel->opacity=gamma*MeshInterpolate(&delta,pixels[2].opacity,
            pixels[3].opacity,pixels[0].opacity);
        }
      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=PerceptibleReciprocal(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);
          if (image->colorspace == CMYKColorspace)
            pixel->index=gamma*MeshInterpolate(&delta,pixels[1].index,
              pixels[0].index,pixels[3].index);
          gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
          pixel->opacity=gamma*MeshInterpolate(&delta,pixels[1].opacity,
            pixels[0].opacity,pixels[3].opacity);
        }
    }
  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=PerceptibleReciprocal(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);
          if (image->colorspace == CMYKColorspace)
            pixel->index=gamma*MeshInterpolate(&delta,pixels[0].index,
              pixels[1].index,pixels[2].index);
          gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
          pixel->opacity=gamma*MeshInterpolate(&delta,pixels[0].opacity,
            pixels[1].opacity,pixels[2].opacity);
        }
      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=PerceptibleReciprocal(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);
          if (image->colorspace == CMYKColorspace)
            pixel->index=gamma*MeshInterpolate(&delta,pixels[3].index,
              pixels[2].index,pixels[1].index);
          gamma=MeshInterpolate(&delta,1.0,1.0,1.0);
          pixel->opacity=gamma*MeshInterpolate(&delta,pixels[3].opacity,
            pixels[2].opacity,pixels[1].opacity);
        }
    }
  break;
}

So it's not using one of the defined filters.

Upvotes: 2

Related Questions