Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bicubic scaling looks like bilinear #179

Open
NathanSweet opened this issue Sep 30, 2021 · 2 comments
Open

Bicubic scaling looks like bilinear #179

NathanSweet opened this issue Sep 30, 2021 · 2 comments

Comments

@NathanSweet
Copy link

NathanSweet commented Sep 30, 2021

Expected behavior

Using ScalingMode.BICUBIC and downscaling to 50% I expect the output to be scaled using bicubic filtering.

Actual behavior

The scaled image looks poor, like bilinear was used. The expected image is Photoshop's bicubic. The actual image looks like Photoshop's bilinear.

Steps to reproduce the behavior

Code below and this image file: http://n4te.com/x/2546-test.png

static public void main (String[] args) throws Exception {
	BufferedImage image = ImageIO.read(new File("test.png"));
	Builder builder = Thumbnails.of(image) //
		.imageType(BufferedImage.TYPE_4BYTE_ABGR) //
		.scale(0.5f) //
		.alphaInterpolation(AlphaInterpolation.QUALITY) //
		.antialiasing(Antialiasing.ON) //
		.rendering(Rendering.QUALITY) //
		.scalingMode(ScalingMode.BICUBIC);
	BufferedImage image2 = builder.asBufferedImage();
	ImageIO.write(image2, "png", new File("test2.png"));
}

Environment

  • OS vendor and version: Windows 10
  • JDK vendor and version: Tried with JDK 16, 13, 10, and 8, all gave same results.
  • Thumbnailator version: 0.4.14

Notes

I traced it through BicubicResizer to AbstractResizer to Graphics2D#drawImage, eventually calling the native sun.java2d.loops.TransformHelper#Transform:

    public native void Transform(MaskBlit output,
                                 SurfaceData src, SurfaceData dst,
                                 Composite comp, Region clip,
                                 AffineTransform itx, int txtype,
                                 int sx1, int sy1, int sx2, int sy2,
                                 int dx1, int dy1, int dx2, int dy2,
                                 int[] edges, int dxoff, int dyoff);

The int txtype parameter is 3, which is the "interpolation type" and I assume is AffineTransformOp.TYPE_BICUBIC (which is 3). If that's right, why isn't bicubic used? I hate this AWT black box where only "hints" are provided.

@NathanSweet
Copy link
Author

Seems like getScaledInstance with SCALE_AREA_AVERAGING is the only sure way to get better results than bilinear.

@coobird
Copy link
Owner

coobird commented Nov 23, 2021

@NathanSweet, have you tried using BufferedImage.TYPE_INT_ARGB? I suspect that Java's Graphics2D rendering pipeline may act differently based on the image type that's being used. And yes, as you mentioned the black box nature of this pipeline makes it hard to chase these issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants