In my eclipse-rcp application I need to create an image with dimensions 30000x10000 px or more. This image is NatTable representation. Using standard image creation approach, it fails with different problems: OutOfMemory, SWTError - IllegalArgument or my PC stops responding (btw, its windows 7, 64bit, 4 RAM - client have much slower laptops, but the picture is still needs to be created). Here is a code snippet:
private Image getNattableImageRepresentation(final Display display) {
final Rectangle totalGridArea = getTotalGridArea(); //this returns Rectangle(0,0,30000,10000)
setGridLayerSize(totalGridArea);
final Image nattableImage = new Image(display, totalGridArea);
final GC nattableGC = new GC(nattableImage);
gridLayer.getLayerPainter().paintLayer(gridLayer, nattableGC, 0, 0, totalGridArea, configRegistry);//nattable API, which draws an image into a specified gc
restoreGridLayerState();
return nattableImage;
}
return null;
}
Are there any tricks to create such huge images or may be API? Is Java Advanced Imaging Api suitable for this purpose?
Any suggestions are appreciated.
ImageMagick is neat tool for image processing like this.. new CG is not the way, definitely.. If you'll join all spare images to the big one, there should be no problem at all..
There is a simple solution for storing larger images in Java. BigBufferedImage stores the image on the hard drive in a very fast way:
https://stackoverflow.com/a/53205617/2631710
Related
I'm developping a simple image organizer in java to sort quickly hundred of photos taken with my camera. The program has a list of photos(file paths) and displays a given photo
When I want to display one of them, it takes more than a second to load the file (~ 10Mb).
In this case, the sorting isn't efficient.
FXML private ImageView preview;
....
private void showMedia(Media m) {
if(m != null) {
Image i = new Image(new File(m.getPath()).toURI().toString());
m.loadMediaProperties();
this.preview.setImage(i);
}
else
this.preview.setImage(null);
}
The constructor of Image class consumes time to loading the given file. I tried to keep the instance of Image for each Media but it I get "java.lang.OutOfMemoryError: Java heap space"
I'm looking for a way to load and display a photo almost instantaneous (like adobe lightroom if you know).
Your goal cannot be achieved by such a simple, brute force approach as you are trying and Adobe Lightroom also does not work that way. Lightroom maintains a database of thumbnails and preview images and uses a lot of caching in order to give you a good performance and you would have to do the same in your application if you want to achieve a similar result. Utitizing background loading and processing is also key to a good performance here.
I have a lot of images that taken by my Digital camera with very high resolution 3000 * 4000 and it takes a lot of Hard disk space, I used Photoshop to open each Image and re-size it o be with small resolution, but it needs a lot of time and effort
I think that I can write simple program that open the folder of images and read each file and get it's width and height and if it's very high change it and overwrite the image with the small one.
Here some code I use in a Java-EE project (should work in normal application to:
int rw = the width I needed;
BufferedImage image = ImageIO.read(new File(filename));
ResampleOp resampleOp = new ResampleOp(rw,(rw * image.getHeight()) / image.getWidth() );
resampleOp.setFilter(ResampleFilters.getLanczos3Filter());
image = resampleOp.filter(image, null);
File tmpFile = new File(tmpName);
ImageIO.write(image, "jpg", tmpFile);
The resample filter comes from java-image-scaling library. It also contains BSpline and Bicubic filters among others if you don't like the Lanczos3. If the images are not in sRGB color space Java silently converts the color space to sRGB (which accidentally was what I needed).
Also Java loses all EXIF data, thought it does provide some (very hard to use) methods to retrieve it. For color correct rendering you may wish to at least add a sRGB flag to the file. For that see here.
+1 to what some of the other folks said about not specifically needing Java for this, but I imagine you must have known this and were maybe asking because you either wanted to write such a utility or thought it would be fun?
Either way, getting the image file listing from a dir is straight forward, resizing them correctly can take a bit more leg work as you'll notice from Googling for best-practices and seeing about 9 different ways to actually resize the files.
I wrote imgscalr to address this exact issue; it's a dead-simple API (single class, bunch of static methods) and has some good adoption in webapps and other tools utilizing it.
Steps to resize would look like this (roughly):
Get file list
BufferedImage image = ImageIO.read(files[i]);
image = Scalr.resize(image, width);
ImageIO.write(image);
There are a multitude of "resize" methods to call on the Scalr class, and all of them honor the image's original proportions. So if you scale only using a targetWidth (say 1024 pixels) the height will be calculated for you to make sure the image still looks exactly right.
If you scale with width and height, but they would violate the proportions of the image and make it look "Stretched", then based on the orientation of the image (portrait or landscape) one dimension will be used as the anchor and the other incorrect dimension will be recalculated for you transparently.
There are also a multitude of different Quality settings and FIT-TO scaling modes you can use, but the library was designed to "do the right thing" always, so using it is very easy.
You can dig through the source, it is all Apache 2 licensed. You can see that it implements the Java2D team's best-practices for scaling images in Java and pedantically cleans up after itself so no memory gets leaked.
Hope that helps.
You do not need Java to do this. It's a waste of time and resources. If you have photoshop you can do it with recording actions: batch resize using actions
AffineTransformOp offers the additional flexibility of choosing the interpolation type, as shown here.
You can individually or batch resize with our desktop image resizing application called Sizester. There's a full functioning 15-day free trial on our site (www.sizester.com).
I develop an application in which I want to display a grid with a list of images. For each image I create an instance of a class myImage. MyImage class, extends JCompoment and create an thumbnail and after draw it with overide thepaintCompoment(Graphics g).
All is ok, but in big size images I have a lot of delay to create the thumbnail.
Now I think to when I scan the folders for image(to create the list I said above to create an thumbanail of each image and save it to disc. For each image I will have a database record to save the image path and thumbnail path.So is this a good solution of the problem?
Is there a way to get the thumbnails of the system creates for each image, in file manager. Or a more effective solution than I try.
Thank you!!
Your best bet is to use something like imagemagick to convert the image and create the thumbnail. There's a project called JMagick which provides JNI hooks into Imagemagick, but running a process work too.
Imagemagick is heavily optimized C code for manipulating images. It will also be able to handle images that Java won't and with much less memory usage.
I work for a website where we let users upload art and create thumbnails on the fly, and it absolutely needs to be fast, so that's what we use.
The following is Groovy code, but it can modified to Java code pretty easily:
public boolean createThumbnail(InputStream input, OutputStream output){
def cmd = "convert -colorspace RGB -auto-orient -thumbnail 125x125 -[0] jpg:-"
Process p = cmd.execute()
p.consumeProcessErrorStream(System.out)
p.consumeProcessOutputStream(output)
p.out << input
p.out.close()
p.waitForOrKill(8000)
return p.exitValue()==0
}
This creates a thumbnail using pipes without actually writing any data to disk. The outputStream can be to a file if you wanted to immediately write it as well.
One way to avoid OS dependance is to use getScaledInstance(), as shown in this example. See the cited articles for certain limitations. If it's taking too long, use a SwingWorker to do the load and scale in the background.
I haven't used it for the creation of thumbnails, but you may also want to take a look at the ImageIO API.
ImageIO
i want to write a mapviewer, i must to work small tile of big map image file and there is need to tiling the big image, the problem now is to tiling big image to small tiles (250 * 250 pixel or like this size)
so on, i used ImageMagic program to do it but there was problem
now is any other programing method or application that do tiling?
can i do it with JAI in java? how?
Have you tried doing it in java yourself? I tried this with (WARNING, big image, can crash your browser, use "save as...") this image. Needed to run with extra memory though (-Xmx400M).
public class ImageTile {
public static void main(String[] args) throws IOException {
Dimension tileDim = new Dimension(250, 250);
BufferedImage image = ImageIO.read(new File(args[0]));
Dimension imageDim = new Dimension(image.getWidth(), image.getHeight());
for(int y = 0; y < imageDim.height; y += tileDim.height) {
for(int x = 0; x < imageDim.width; x += tileDim.width) {
int w = Math.min(x + tileDim.width, imageDim.width) - x;
int h = Math.min(y + tileDim.height, imageDim.height) - y;
BufferedImage tile = image.getSubimage(x, y, w, h);
ImageIO.write(tile, "JPG", new File("tile-"+x+"-"+y+".jpg"));
}
}
}
}
For the large images sizes like you have, you will be best served with lossless editing of the JPEG files. Not only is this faster, since the image doesn't need to be rendered, but it also preserves quality, since the image is not recompressed.
Lossless editing works on blocks, typically 16px square. While restrictive for some applications, this seems a good fit for mapping. You could implement tiling at different zoom levels by first losslessly cropping the image to sized pieces. (This is quick an efficient since the image is not rendered.) This gives you tiles for full-zoom. To create lower-levels of zoom, combine 2x2 tiles and scale these down to the size of 1 tile. The next level uses 4x4 tiles, and 8x8 and so on, each time scaling down to one tile. At some point when the number of tiles beecomes too large, you can choose to use zoomed tiles as the base resource. For example, at zoom level 8, that would require 256x256 tiles. This might be too much to handle, so you could use 16x16 tiles from zoom level 4.
Wikipedia has more on lossless editing, and links to some implementing libraries.
imagemagick does tiling using -tile. It's more of a repitition of an image, but might be useful esp. since youre already using it. However If you mean generated seamless tiling I'm not sure if imagemagick can do that or not.
GDAL comes with a script called gdal2tiles.py that does exactly what you want, including formatting the tiles for use with Google Maps, OpenLayers, etc.
There seems to be an newer version of GDAL2Tiles as well.
How about a megatexture with an r-tree for efficient access? Apparently it can use images 128000x128000 pixels.
JAI is platform dependent and seems like a dead project today.
I advise using the open-source program imagemagick. Although it is platform dependent, it is available for the same platforms as JAI, but with full community support.
The trick about large images about imagemagick is using its "stream"-command instead of the convert command. Stream only reads the relevant portion of the image and saves the extracted part as raw data. You then need "convert" to save the small raw data as jpeg.
Example to save a tile from large.jpeg of size 800x600 from position 0x0 to tile.jpeg:
stream -extract 800x600+0+0 large.jpeg tile.rgb
convert -depth 8 -size 800x600 rgb:tile.rgb tile.jpeg
(When running on windows, be sure to use ImageMagick's convert.exe, as there is a windows command named "convert".)
When working with TIFF-images only, apache Sanselan could be the right choice - it is a pure-java imaging lib. Also, JAI seems to contain a platform independent codec for TIFF.
I'm trying to create thumbnails for uploaded images in a JRuby/Rails app using the Image Voodoo plugin - the problem is the resized thumbnails look like... ass.
It seems that the code to generate the thumbnails is absolutely doing everything correctly to set the interpolation rendering hint to "bicubic", but it isn't honoring them on our dev environment (OS X), or on the production web server (Linux).
I've extracted out the code to generate the thumbnails, rewritten it as a straight Java app (ie kicked off from a main() method) with the interpolation rendering hint explicitly set to "bicubic", and have reproduced the (lack of) bicubic and bilinear resizing.
As expected on both OS X and Linux the thumbanils are ugly and pixelated, but on Windows, it resizes the images nicely with bicubic interpolation used.
Is there any JVM environment setting and/or additional libraries that I'm missing to make it work? I'm doing a lot of banging of head against wall for this one.
I realize this question was asked a while ago, but incase anyone else is still running into this.
The reason the thumbnails look like ass are caused by two things (primarily the first one):
Non-incremental image scaling in Java is very rough, throws a lot of pixel data out and averages the result once regardless of the rendering hint.
Processing a poorly supported BufferedImage type in Java2D (typically GIFs) can result in very poor looking/dithered results.
As it turns out the old AreaAveragingScaleFilter does a decent job of making good looking thumbnails, but it is slow and deprecated by the Java2D team -- unfortunately they didn't replace it with any nice out-of-the-box alternative and left us sort of on our own.
Chris Campbell (from the Java2D team) addressed this a few years ago with the concept of incremental scaling -- instead of going from your starting resolution to the target resolution in one operation, you do it in steps, and the result looks much better.
Given that the code for this is decently large, I wrote all the best-practices up into a library called imgscalr and released it under the Apache 2 license.
The most basic usage looks like this:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 640);
In this use-case the library uses what is called it's "automatic" scaling mode and will fit the resulting image (honoring it's proportions) within a bounding box of 640x640. So if the image is not a square and is a standard 4:3 image, it will resize it to 640x480 -- the argument is just it's largest dimension.
There are a slew of other methods on the Scalr class (all static and easy to use) that allow you to control everything.
For the best looking thumbnails possible, the command would look like this:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY,
150, 100, Scalr.OP_ANTIALIAS);
The Scalr.OP_ANTIALIAS is optional, but a lot of users feel that when you scale down to a small enough thumbnail in Java, some of the transitions between pixel values are a little too discrete and make the image look "sharp", so a lot of users asked for a way to soften the thumbnail a bit.
That is done through a ConvolveOp and if you have never used them before, trying to figure out the right "kernel" to use is... a pain in the ass. That OP_ANTIALIAS constant defined on the class it the best looking anti-aliasing op I found after a week of testing with another user who had deployed imgscalr into their social network in Brazil (used to scale the profile photos). I included it to make everyone's life a bit easier.
Also, ontop of all these examples, you might have noticed when you scale GIFs and some other types of images (BMPs) that sometimes the scaled result looks TERRIBLE compared to the original... that is because of the image being in a poorly supported BufferedImage type and Java2D falling back to using it's software rendering pipeline instead of the hardware accelerated one for better supported image types.
imgscalr will take care of all of that for you and keep the image in the best supported image type possible to avoid that.
Anyway, that is a REALLY long way of saying "You can use imgscalr to do all that for you and not have to worry about anything".
maybe is this a solution for you:
public BufferedImage resizeImage(BufferedImage source, int width, int height)
{
BufferedImage result = new BufferedImage(widht, height, BufferedImage.TYPE_INT_ARGB);
Graphics g = result.getGraphics();
g.drawImage(source, 0, 0, widht, height, null);
g.dispose();
return result;
}
In the end, upgrading to the latest version of ImageVoodoo seemed to improve quality.
Looking through the source code, it looks like they're doing some funky AWT rendering, and then pulling that out. Nasty, but it seems to work.
Still not as good as ImageMagick, but better than it was.
#Riyad, the code for incremental scaling isn't "decently large", it's quite small (As you can see from a post back in 2007, http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html#creating-scaled-instances) having a library that gives other options might be useful, but making a library to use a library is nonsense.