Open checklist opened 8 years ago
Sorry that this is a very late reply, I'd like to get more information.
When you mention that "it does not seem to be working", could you describe what exactly you encountered, and what your expectations are?
I suspect this may be a misunderstanding of the crop
functionality, which is basically a way to enforce an certain output dimensions (which in turn has a certain aspect ratio) from input images which have differing aspect ratios.
For example, say we want to create thumbnails which are 100 x 100 (hence, we use size(100, 100)
) from images which can be a variety of sizes and aspect ratios, like 200 x 100, 200 x 400, etc. In this situation, we could use something like Positions.CENTER
, and crop out parts that overhang after resizing to 100 x 100 while keeping the aspect ratio (which is what the size
method does.)
In that case:
In general, using a Coordinate
as a parameter for crop
would probably lead to some unexpected results. This behavior may be a little bit difficult to understand from the explanation of the crop
method, so it might need some work to clarify that.
@coobird Thanks for the explanation!
Yes, this is how .crop(Position)
works and this is definitely useful behavior. But what if I want just a simple crop, like the author of the issue?
By simple crop I mean just a crop from X1, Y1
to X2, Y2
coordinates of original image. Without any resize at all.
Example:
X1=50, Y1=50
to X2=100, Y2=100
should create a 50 x 50 image with cut off 50 pixels from top and left of original image, and also cut off 100 pixels from the right and 0 pixels from the bottom.X1=50, Y1=50
to X2=100, Y2=100
should create a 50 x 50 image with cut off 50 pixels from top and left of original image, and also cut off 100 pixels from the right and 300 pixels from the bottom.This is useful when you let user to select cropping area on his image to focus on something important, like a face. :-) When user does this, we need to first crop the original image exactly at the user-provided coordinates, and only then resize it to thumbnail size.
Any advice to achieve that with this library? Custom filter maybe?
Nevermind, I found a solution!
.sourceRegion(int x, int y, int width, int height)
FTW!
It does exactly what I described. And I can even do source cropping and .crop()
cropping in one step, like:
BufferedImage dstBufferedImage = Thumbnails.fromImages(Collections.singleton(srcImage.getBufferedImage()))
.sourceRegion(180, 0, 413 - 180, 348)
.crop(Positions.CENTER)
.size(dstWidth, dstHeight)
.asBufferedImage();
And if I need to just simple cropping (described earlier) without resize, I can do this:
BufferedImage dstBufferedImage = Thumbnails.fromImages(Collections.singleton(srcImage.getBufferedImage()))
.sourceRegion(180, 0, 413 - 180,348)
.resizer(Resizers.NULL)
.scale(1.0)
.asBufferedImage();
The tricky part here is that you need to set resizer
to Resizers.NULL
and scale
to some value, because without scale
the builder complains on size is not set
, even with Resizers.NULL
resizer.
I understand the confusion of issue creator as I was confused too, because .crop()
method does not exactly what is usually called crop
in graphic editors like Gimp. It does more: resize and then crop. I glad I found .sourceRegion()
method. :) Thank you anyway for the good library!
The tricky part here is that you need to set
resizer
toResizers.NULL
and scale to some value, because without scale the builder complains onsize is not set
, even withResizers.NULL
resizer.
I would have thought that using scale(1.0)
would be enough, and that Resizers.NULL
wouldn't be necessary... (It's been a while since I've actually played around that part of the code base.)
Did you find that the final image's dimensions (cropped image) were the same as the original image? (That's the only reason I can guess that would require Resizers.NULL
as a workaround.)
I understand the confusion of issue creator as I was confused too, because
.crop()
method does not exactly what is usually calledcrop
in graphic editors like Gimp. It does more: resize and then crop. I glad I found.sourceRegion()
method.
Yeah, I probably should add more examples since cropping (and some other operations) are not very straightforward... (Many things were bolted on, so there's some rough edges..)
Right now, cropping and source region are only explained in detail in the Changes page, which it not very intuitive..
Thanks for comments!
Honestly, I'm not sure why Resizers.NULL
is required. I stole this "hack" from my old project. Maybe setting scale
is really enough, and I did set Resizers.NULL
just to be 100% sure that no processing other than I explicitly set will consume any CPU resources.
In my old project it looks like this:
BufferedImage dstBufferedImage = Thumbnails.fromImages(Collections.singleton(srcImage.getBufferedImage()))
.resizer(Resizers.NULL)
.scale(1.0)
.watermark(watermarkPosition, scaledWatermark, watermarkOpacity)
.asBufferedImage();
The idea here is to just watermark the image without any resizing. But yes, maybe scale(1.0)
is enough actually.
Thanks to pointing me to Changes page. Didn't know it even has images to illustrate the behavior of some methods! Behavior of some methods is really hard to understand for me even after reading their javadocs. It's funny that Changelog is more informative than documentation. :)
I need to crop an image starting at position x,y and it should be height,width in size (starting at x,y). I have the following code:
Thumbnails .of(url) .size(width, height) .crop(new Coordinate(x,y)) .toOutputStream(os); ; But it does not seem to be working. Any ideas?