4

I am trying to re-size an image with Java, and I need to get the exact effect that is happening when you re-size with Photoshop Nearest Neighbor (Preserve hard edges).

The thing is I never get the exact same effect...

I tried following methods:

1) java-image-scale by mortennobel lib

resampleOp.setFilter(ResampleFilters.getBoxFilter());

this performs great, but leaves some artifacts in image, that are not there when photoshop does it.

2) TwelveMonkeys library for image manipulation. (here is the github link) Did not work as well, PointFilter completely destroys the gradient inside, and the Box filter does same thing as mortennobel getBoxFilter.

3) AWT AffineTransform, this was the worst one, completely unrealistic resize.

Now I am confused, does photoshop's nearest neighbor re-size differently then what the name means, or all the other libs do it wrong (in second case, what is the lib that will do it right?)

Here is the before and after images Photoshop generates

enter image description here enter image description here

And here is the image generated by get BoxFilter from mortennobel lib.

enter image description here

I scaled images a bit up so you can see the details, in reality they are smaller. Any help is really appreciated :) I am really stuck on this.

Avetis Zakharyan
  • 887
  • 2
  • 9
  • 20
  • The mortennobel library uses a box filter and as such is not what you ask for -- nearest neighbor. Have you considered writing the code yourself? Iterating over raw image pixels, without any filtering, is not that hard. – Jongware Sep 21 '14 at 11:39
  • Hmm.. I thought box filter and nearest neighbor is the same. Well I have considered that, but I thought it might be slow, and besides, there should be a lib that does that right? Instead of a fancy filter use the simple one, that's all I want. I feel like there is another name for what Photoshop does, and if I knew it, I would find the right lib. – Avetis Zakharyan Sep 21 '14 at 11:44
  • 2
    You might want to explain in how far the results of using `RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR` differ from what you want to achieve (also see https://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html#creating-scaled-instances ) – Marco13 Sep 21 '14 at 12:35
  • @Marco13, Actually that just solved it!!! Thank you! Do you want to post a sample code as an answer so I can upvote? or I can do that myself if you want :) – Avetis Zakharyan Sep 21 '14 at 16:48
  • I could only create a snippet heavily based on the code from the linked site, and guess about the details that helped to resolve the issue in your case. You can answer your own question (otherwise I'll try to create an appropriate answer, but I think that yours would be more to the point) – Marco13 Sep 21 '14 at 19:10
  • Strange... Using `ResampleOp` (from TwelveMonkeys/method 2) with `PointFilter` should produce exactly the same result as `AffineTransformOp` with `VALUE_INTERPOLATION_NEAREST_NEIGHBOR` (as that is what it uses internally). If it does not, that should be considered a bug. Oh no! ;-) – Harald K Sep 22 '14 at 11:14

1 Answers1

2

Huge Thanks to Marco13 for pointing this out! Apparently mortennobel lib doesnot do Nearest Neighbour, instead AWT's Graphics2D can if used with RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR rendering hint. Here is the code snippet that worked for me and produced photoshop's exact image.

destinationBufferedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = destinationBufferedImage.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
g2.drawImage(sourceBufferedImage, 0, 0, newWidth, newHeight, null);
g2.dispose();
Avetis Zakharyan
  • 887
  • 2
  • 9
  • 20