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

Bug in cubic scaling #593

Open
lukehutch opened this issue Nov 27, 2023 · 6 comments
Open

Bug in cubic scaling #593

lukehutch opened this issue Nov 27, 2023 · 6 comments

Comments

@lukehutch
Copy link

lukehutch commented Nov 27, 2023

If I scale an image down using cubic scaling, the pixels appear "locally jumbled", which in an image processing algorithm typically indicates that the weights in adjacent pixels were inadvertently switched, or similar.

For example, take this original image, at 1080x1920:

image

Scaling this down to 270x480 using copyResize(image, width: 270, interpolation: Interpolation.cubic) gives the following (zoom in to see the local pixel jumbling):

image

The same downscaling in Gimp, using cubic interpolation, gives the correct and expected result:

image

@lukehutch
Copy link
Author

I tried with Interpolation.linear, and got the exact same result.

@lukehutch
Copy link
Author

OK, so with Interpolation.average, the result is more reasonable:

image

It seems that the linear and cubic interpolation methods only sample from the immediate nearest 4 neighboring pixels:

https://github.com/brendan-duncan/image/blob/main/lib/src/transform/copy_resize.dart#L162

This is not what I would expect from a linear or cubic interpolation, as shown by the Gimp example above. for any scale factor smaller than 0.5, image is dropping an enormous amount of image information by sampling only the immediate neighborhood in this way.

@brendan-duncan
Copy link
Owner

Yeah, you're right, it should do a gather and interpolate over all of the pixels converging in the down sampling.
I would like to go in and rewrite that function to do the right thing, but it could be a while.

@lukehutch
Copy link
Author

This is a bit costly, but you could do the gather by just calling average for the pixel locations of the corners, then perform regular bilinear or bicubic interpolation between these values. That would get rid of artifacts, at the cost of some extra convolutional blurring.

@brendan-duncan
Copy link
Owner

The usual trick for cubic down sampling is to use a guassian blur on the image and then downsample. Which, as you said, is more costly. An average would be an approximation to that, a bilinear down sample. There's no getting around it being more costly to do decent down sampling.

@lukehutch
Copy link
Author

Right, what I was suggesting is equivalent to a convolution of a convolution of two box functions, which is a convolution with a triangle function, which is a 2nd order approximation of a Gaussian. It should be faster than convolving with a Gaussian, but give a similar result.

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