I have an application that uses JAI to process images. It takes TIFF files, reads them, wraps the content into a SeekableStream then uses JAI.create to create the PlanarImage.
What I want to do is change the source from TIFF files to a component, which already exists, and which serves me the image data in the form of a raster stored in a byte array. I know the format of the raster data (width, height, bits per sample etc.).But I can't find a way to create a PlanarImage for JAI in the same way as before.
My only idea is to create a java.awt.Image from the raster and use that with JAI.create. Is this OK, or is there a better solution?
You can use PlanarImage.wrap(bufferedImage) method.
Note: you can create bufferedImage from raster.
Furkan
Related
I want to write informations (former: int/String) into a PNG-file without making the changes visible to the human eye.
In order to achieve this i extract the file in the form of a Byte array:
byte[] imageAsBytes = fileInputStream.readAllBytes();
In the next step i jump the header (8 Bytes, already tried up to 300Bytes). I already have my information processed and can extract it bitwise.
I replace the last Bit from the picture`s Bytes with the Bitwise extracted information.
This works well with the .bmp file format but applying this technique to PNG-files distorts the image.
My guess is that the PNG-file contains additional information after the header.
So is there any information stored after the header and if so what marks this "information-part" as one?
In order to read and decode a .png file we can use BufferedImage as it follows:
File imageFile = new File("myimage.png");
BufferedImage image = ImageIO.read(imageFile);
No we can manipulate its pixels using getRGB and setRGB methods:
int pixel = image.getRGB(x, y);
// do some byte manipulation on the pixel
// ....
image.setRGB(x, y, pixel);
After this the BufferedImage should be piped to an output stream to be able to save the new image.
I think the best way will be not look at file bytes, but open it with some png decoder then change pixels at image itslef then save it again using png. When You will play with file bytes itself for sure You will broke the format of png, You didnt in bmp becasue bmp its jsut pixel by pixel saved drectly to file wihout any packaging or encoding
I would like to read an image and then change its format but without saving it.
For example I can read the image like this
BufferedImage img=ImageIO.read(new File(fileName));
Then I want to change the format of img, for example from jpeg to png.
The only way I found is to use ImageIO.read to write and then read the new image, but it does seem to be an efficient way to do it.
When you "read" the image via
BufferedImage img=ImageIO.read(new File('myimage.png'));
you are not only reading but also decoding it, i.e., transforming the raw bytes in the (say) PNG format to some "RAW" format that your aplication or API can manipulate (or display) - in this case, a BufferedImage. Once this is done, the fact that this image came from a PNG file is forgotten. To read it as PNG and save it as JPEG you need to decode it (as PNG) and then code it (as JPG).
I would like to read an image and then change its format but without saving it.
The "format" of the image (in the PNG/JPEG sense) gives you a way of packing an image in a sequence of bits. So, your desire makes little sense. At most, you could store those bits in memory (what for?), but that would be the same as "saving it" (to memory instead of disk).
I have a large swing component to write to TIFF. The component is too large to load the TIFF in memory, so I either need to make a big BufferedImage which is backed by a disk-based WritableRaster (as mentioned here) or use JAI.
JAI seems like the better answer, aside from the utter confusion of the project.
Given that, can someone outline steps for writing my swing component to a tiled TIFF without running out of Memory?
Image size will be maybe 10000x700
Ideally I would create some sort of disk-based image, and write parts of the component to it, each write being flushed to disk.
EDIT
I think I could do this with an ImageWriter, however I'm getting a NoSuchElementException when I call:
ImageWriter imageWriter = ImageIO.getImageWritersByFormatName("tif").next();
I have the jai_code.jar and jai_core.jar jars on my classpath, is there something else I need to do?
EDIT
I can create a very large TIFF using JAI, but JAI doesn't support TIFF compression, so the file is 92 MB.
If I install JAI-ImageIO, I can create a compressed TIFF Using an ImageWriter, but only from a Raster or BufferedImage, which I don't have enough memory for.
Is there some way to do a two-step approach, use JAI to create the large TIFF, then compress the large TIFF without loading the whole thing into memory?
I had to load and store a large tiff (59392x40192px) with JAI. My solution is: TiledImages.
I have used a TiledImage because I need tiles and subimages.
To use the TiledImage efficient you should construct it with your prefered tile size. JAI uses a TileCache so not the whole Image will be in memory, when it's not needed.
To write the TiledImage in a File use the option "writeTiled" (avoid OutOfMemory because it writes tile by tile):
public void storeImage(TiledImage img, String filepath) {
TIFFEncodeParam tep = new TIFFEncodeParam();
//important to avoid OutOfMemory
tep.setTileSize(256, 256);
tep.setWriteTiled(true);
//fast compression
tep.setCompression(TIFFEncodeParam.COMPRESSION_PACKBITS);
//write file
JAI.create("filestore", img, filepath, "TIFF", tep);
}
It works fine with images up to 690mb (compressed), for larger images i haven't tested yet.
But if you are working on WinXP 32-bit you may not able to have more as 1280m HeapSpace size, this is still a limit of Java VM.
My TiledImage is build with a IndexedColorModel from my image-source data:
//here you create a ColorModel for your Image
ColorModel cm = source.createColorModel();
//then create a compatible SampleModel, with the tilesize
SampleModel sm = cm.createCompatibleSampleModel(tileWidth,tileHeight);
TiledImage image = new TiledImage(0, 0, imageWidth, imageHeight, 0, 0, sm, cm);
I had the same situation and I used these steps:
Load as BufferedImage with JAI
Resize BufferedImage size to preferable size (600x600px) maintaining aspect-ratio using Image#getScaledInstance(int w, int h, Image.SCALE_SMOOTH)
Draw image using Graphics2d.drawImage(..) method in JComponent#paintComponent(java.awt.Graphics) method
That helped me with showing and manipulating TIFF images ~50MB (5000x5000px).
I am using a common format all over application for images as png.Any jpg image uploaded still gets saved as png using code as below.
java.awt.image.BufferedImage bufferedImage = ImageIO.read(jpgImagePAth);
if(!IsExtensionPng(jpgImagePath)){
ImageIO.write(bufferedImage, "png", new File(pptFolder, justNamePng));
}
But this preserves alpha even though it was not there in the jpg so makes a 2MB Image 7MB and 6MB to 16MB . Is there anyway to save png without maintaining the alpha ?
The reason I need to conver to PNG is that later on when I add text on image it looses the actual resolution. I already tried loseless JPEG which didnt fix it.
It's not the alpha channel that is causing the file size to grow, it's the file type. JPG uses lossy compression; PNG is lossless compression. In other words, JPG is throwing out some data to reduce the size of the file. That's why you get to choose a "quality" level when saving to JPG - that determines how much is thrown out.
How do you know you're getting the alpha channel anyway? If you still want PNG and want to be sure you're dropping the alpha channel, set the image type to BufferedImage.TYPE_RGB, e.g.
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_RGB);
You'll have to get the graphics object associated with your new BufferedImage and copy the jpg onto it, then write it out. This question isn't quite the same as yours but has sample code you may find useful.
Paul
I don't know exactly in what situation you are. But I should keep JPEG JPEG. The only advantage of converting JPEG to PNG is wasting hdd space.
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.