Crop Bitmap without reading entire Bitmap first - java

I have a very large image and I only want to display a section the size of the display (no scaling), and the section should just be the center of the image. Because the image is very large I cannot read the entire image into memory and then crop it. This is what I have so far but it will give OutOfMemory for large images. Also I don't think inSampleSize applies because I want to crop the image, not lower the resolution.
Uri data = getIntent().getData();
InputStream is = getContentResolver().openInputStream(data);
Bitmap bitmap = BitmapFactory.decodeStream(is, null, null);
Any help would be great?

You can do this in 2 steps:
get the size of the bitmap, by using inJustDecodeBounds=true .
use BitmapRegionDecoder to decode just the part you want to .
The downside ? it works only from API 10 (but it's already the majority...).

I agree that the easiest way is to break the image up into many smaller tiled images and to just load the appropriate ones to make the image you are after.
However, if you do not want to do that, you may be forced to look into the encoding of the jpeg itself.
What you could do is something along the lines of copying the header from the file into a new file, and then extracting just the pixels you want in order to create a new file. Then reloading the new file will allow you to have just the subset of the image you are looking to work with, and all the regular java functionality and classes will be equally available for you to use.
I know it isn't necessarily an elegant or simple solution, however it does guarantee that you will be able to use the original java functionality which you expect to be able to use.

I think you're approaching the problem from the wrong direction.
If the bitmap is already so large it can't be loaded as a single continuous image, why store it as a single image? Slice it into tiles then load the center tile/tiles and act upon those.

Related

javaxt.io.Image doubles in size when using saveAs()

In an application, I need to use javaxt.io.Image to rotate the image and then save it into a new file. This is the code:
Image image = new Image(input);
image.rotate();
image.saveAs(output);
While the image does lose the EXIF rotation, which is the reason I needed this functionality, the image almost doubles in size. input.jpg is at 2.8MB, while output.jpg becomes 4.3MB. I couldn't find a parameter or function for compression in javaxt.io.Image.
Did I miss a step or is this behaviour wanted by the library? What would be the most efficient way to re-reduce the size?
As Thomas commented, I missed the function setOutputQuality(float quality) in the library documentation. Using that enables you to compress your images.

Java: Find image within image?

So, say I have two images, one which is a .bmp of some text and another which is a bufferedImage, how would I go about finding if the .bmp is inside the bufferedImage?
Im really lost on how to find an image within an image, a color is easier as its just one thing to search for but an image seems much harder...
One Solution to this Problem is "Template Matching".
This means sliding your Template (the image you want to find) over the Image (you want to search in) and at every Position compare the similiarity of all Pixels.
The Position of your Template in the Image is at the Maximum this procedure returned.
As suggested in the comments you can use OpenCV for this Task which support Template Matching.

How can I change the photo size dynamically from the server?

I have a large number of photos on the Server. The question is I have to save the photo into every size I need.
I find that many websites use the url such as http://www.abc.com/89-w100-h100.jpg to show the photo in any size. When I change w and h, I can get the photo in this size.
I just want to know how can I achieve this function.
ps: I can cut the photo into the given size. But I don't know how to show the photo on the browser.
Thanks in advance!
It is possible to scale down a photo dynamically upon request. You would need to devise a scheme of encoding the size in the URL (as you have shown in your question), then apply a scaling function to the original image, using the URL parameters as input. This is assuming you are doing this on the server side.
Your question mentions something about showing it in the browser, so if that is what you mean, you can simply size the <img> element to whatever size you want and the browser will automatically scale the image. This does require downloading the full-size image, however.
I dont think they scale it based on request. Image Resize is a expensive operation. Usually big corps, upon uplaoding an image, they resize it then. ex: yahoo resize an image with 9 different sizes and they all have some sort of scheme like 89-w100-h100.jpg which they use to identify them.
On the other hand, best you can do to resize an image is to define height and width tags to img tag. However that might have some unwanted consequences.

How to save optimized png images with java's ImageIO?

I am generating lots of images in java and saving them through the ImageIO.write method like this:
final BufferedImage img = createSomeImage();
ImageIO.write( img, "png", new File( "/some/file.png" );
I was happy with the results until Google's firefox addon 'Page Speed' told me that i can save up to 60% of the size if i optimize the images. The images are QR codes, their size is around 900B each and the firefox-plugin optimized versions are around 300B.
I'd like to save such optimized 300B Images directly from java.
So here my question again: How to save optimized png images with java's ImageIO?
Use PngEncoderB to convert your BufferedImage into a PNG encoded byte array.
You can apply a filter to it, which helps prepare the image for better optimization. This is what OptiPNG does, only OptiPNG calculates which filter will get you the best compression.
You might have to try applying each filter to see which one is consistently better for you. With 2 bit color, I think the only filter that might help is "up", so I'm guessing that's the one to use.
Once you get the image to a PNG encoded byte array, you can write that directly to a file.

How to make a thumb from a big image file in J2ME?

I'm trying to display a big image file in a J2ME application. But I found that when the image file is too big I can not even create the Image instance and get a OutOfMemory exception.
I suppose I can read the image file in small chunks and create a thumbnail to show to the user?
Is there a way to do this? Or is there any other method to display the image file in the application?
Thanks.
There are a number of things to try, depending on exactly what you are trying to do and what handset you want your application to run on.
If your image is packaged inside your MIDlet JAR file, You have less control over what the MIDP runtime does because the data needs to be unzipped before it can be loaded as an Image. In that case, I would suggest simply packaging a smaller image. Either reduce the number of pixels or the number of bytes used to encode each pixel.
If you can read the image bytes from a GCF-based InputStream (file, network...), You need to understand the image format (BMP is straightforward, JPEG less so...) so you can scale it down into a mutable Image object that would take less memory, one chunk at a time.
In that case, you also need to decide what your scaling algorithm should be. Turning 32 bits pixels in a file into 8 bits pixels in memory might not actually work as expected if the LCDUI implementation on your mobile phone was badly written.
Depending on the content of the image, simply removing half of the pixel columns and half of the pixel lines may be either exactly what you need or way too naive an approach. You may want to look at existing image scaling algorithms and write one into your application.
Remember that basic LCDUI may not be the only way to display an image on the screen. JSR-184, JSR-239, JSR-226 and eSWT could all allow you to do that in a way that may be totally independant from your handset LCDUI implementation.
Finally, let's face it, if your phone MIDP runtime doesn't allow you to create at least 2 images the size of your screen at full color depth at the same time, then it might be time to decide to not support that specific handset.

Categories

Resources