I would like to export the image in my JPanel to a vector graphics file so it can be edited and printed at a higher-than-screen resolution. Essentially I want its paint() function to be called with a destination Graphics that saves the drawing commands into a vector graphic file.
What is a good, simple way to do this? What libraries are recommended? Which vector format would be best, and why?
Have a look at The Java EPS Graphics2D package.
Many Java programs use Graphics2D to draw stuff on the screen, and while it is easy to save the output as a png or jpeg file, it is a little harder to export it as an EPS for including in a document or paper.
This package makes the whole process extremely easy, because you can use the EpsGraphics2D object as if it's a Graphics2D object. The only difference is that all of the implemented methods create EPS output, which means the diagrams you draw can be resized without leading to any of the jagged edges you may see when resizing pixel-based images, such as JEPG and PNG files.
Apache Batik will let you paint to a specialised implementation of a Graphics2D object and then export as an scalable vector graphics (.svg) file. You can then view/process/print it using an SVG-enabled browser (Firefox will handle it nativly, ISTR, IE and others can use plugins).
See the SVGGraphics2D object (process documented here)
The Java EPS mentioned by Pierre looks good, but if it isn't you might also like to look at FreeHEP Vector Graphics. Written to allow Java reuse in the High Energy Physics field it includes a vector graphics package, done through an implementation of Graphics2D. We've used it to export EPS very successfull for a number of years.
I can recommend the VectorGraphics2D library (LGPL). Although it does not support all the features of Graphics2D, I used it successfully for my project. It provides implementations of java.awt.Graphics2D for various vector file formats. It simply exports all paint operations to EPS, SVG, or PDF files.
Additional libraries for people with the same requirement:
for SVG, JFreeSVG at http://www.jfree.org/jfreesvg/
for PDF, OrsonPDF at http://object-refinery.com/orsonpdf/index.html
Both of these GPLv3 and well tested via extensive usage in JFreeChart and Orson Charts.
FreeHEP seems to work quite well although it does not appear to be maintained anymore and its bug and forum pages are gone. With just a handful of lines you get a popup dialog that can save any component to a variety of scalable and regular image formats. We have some challenging images, using alpha channel, rotated text, areas bounded by curves, and they saved perfectly, much better with with VectorGraphics2D.
The only problem I've seen so far is in jpeg save, which comes out black for all my images. This isn't very important for us given that png works, plus all the vector modes, but I'm sure it would be an issue for some.
I had to add exactly this much code to save in all these modes:
public static void showImage(Component comp)
{
try
{
ExportDialog export = new ExportDialog();
export.showExportDialog( null, "Export view as ...", comp, "export" );
System.err.println("Image save complete");
}
catch(Exception e)
{
e.printStackTrace();
}
}
There are a bunch of library jars that must be added as well.
this is basically not possible directly, as the low level java api works in terms of raster (pixels) and is never stored in vector format.
(Check the API of java.awt.Graphics to see what I mean).
there are some general purpose program that convert raster to vector formats, this is one I found on a quick search:
http://autotrace.sourceforge.net/index.html
so, using such a program you can divide your problem into two smaller problems:
convert your JPanel into a bitmap or file (http://www.jguru.com/faq/view.jsp?EID=242020)
run autotrace on the file.
Related
I'm currently working on a project where I need to plot the predicted footprint of a satellite on a mercator-projected world map with possible scaling/cropping/etc. done to the map.
I thought Cairo would be a good library to use for this purpose. There are Java-bindings available for it. However, I just can't find a way to make it render onto a SWING GUI (e. g. onto the surface of a JPanel). I thought about rendering into a byte buffer and plotting it out pixel by pixel using Java2D, but I can't find any API call to make Cairo render into a buffer (which is weird, as this is one of the most fundamental functionalities I'd expect to get supported by such a library).
Any way I can achieve this? I know there is Java2D, but it is fairly basic. I'd really appreciate a more powerful, widespread, well-tested, high-quality, free (LGPL) graphics library for this purpose. Cairo would be such a perfect fit, if I could get it to work with SWING somehow.
Thank you very much for your proposals.
One of the fundamentals in Cairo is that any non-abstract image context is bound to one of the supported back ends.
I've never tried the Java bindings, but it is likely they are a thin layer, not providing a a new surface type - you should use the "Image Surface" type.
On the C documentation for the Library, there is a "cairo_image_surface_get_data()" call
(here: http://cairographics.org/manual/cairo-Image-Surfaces.html ) which gives one acess to the buffer.
Maybe the bindings didn't expose this to Java due to the low level memory access required to actually use its contents. If that is true, then I propose you the following work-around:
(1)Render your results to a Cairo Image Surface, (2) Write a temporary file with the surface contents,(3) Read and display the temporary file with the Java 2D API.
Here is a example.
I found this examples on http://java-gnome.sourceforge.net
It create a gtk window, and actually a gtk DrawingArea widget, the onDraw() event uses cairo.
I compiled and run it on linux, it works good.
however java-gnome seems only have linux binary. Maybe somebody could make a windows binary, but need some work.
It is a gtk window, so have nothing to do with swing.
Maybe you don't need swing if gtk(java-gnome) can fit your needs.
If you must use swing, you can use cairo to render to a image in memory, then show it to JComponent by somthing like overriding paintComponent() method. I don't know the performance.
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'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.
Alex explained what I'm looking for much better than I have:
You want an existing program that
allows you to draw a picture, captures
what you do as you draw, and writes
each action as a Java command. When
you click the "Drawl Oval" tool and
click at 0,0 and then at 50,50, it
would generate the line
g.drawOval(0,0,50,50).
If anybody knows of a program such as this, let me know. Thanks.
Original question:
I've been working with Java and custom drawing using the java.awt.Graphics library lately, but find it is taking too much time to write manually. Is there any simple graphics editor (like mspaint) which generates source code?
Example:
Drawing this:
Would generate:
public void update(Graphics g) {
g.translate(0, 0);
g.drawOval(0, 0, 50, 50);
}
Thanks.
If they are vectors, you could use an SVG Editor (eg, Inkscape) along with Kirill's SVG to Java2D Transcoder to simplify this. It isn't perfect, but Kirill is very responsive in responding to requests for enhancement.
It's unclear what you are asking. Two guesses:
You want an existing program that allows you to draw a picture, captures what you do as you draw, and writes each action as a Java command. When you click the "Drawl Oval" tool and click at 0,0 and then at 50,50, it would generate the line g.drawOval(0,0,50,50).
I do not know of any such tool. But the above might help you reword your question so that others can share their knowledge.
You want a program that takes an existing bitmap and converts it into a series of commands that will replicate the bitmap. Other than simply outputting pixels, such a tool is nearly impossible to write; attempting to decompose an arbitrary picture into simple drawing commands is very hard.
In this case, I would recommend simply importing the bitmap as a JPG, PNG, whatever, and using drawImage() instead of using Graphics calls.
While not what you were looking for, I should mention that XPM (X Pixmap) format is basically a subset of C programming language. XPM2 simplified it more by removing the trappings of C syntax. XPM3 brought them back again.
In a sense XPM image converters are source code generators and translators.
You are looking for something similar to output Java AWT, but for many real images or photographs it would be complicated to do analysis on the image to find oval,etc and create the code for drawing them with lines and shapes (well unless the image had filters applied to simplify it, or was an SVG as someone pointed out). It would probably have to convert to a bitmap of some form and keep it in an array in the generated Java source.
Well I've written a basic lossless jpeg joiner thing in java now but I'd like to compare the files it produces with the original files.
I can only compare so much in a hex editor, does anyone know of an easy way, software or java based (preferably software as I dont feel like any more coding for now!) that I can compare two images and produce a "difference map" of where the pixels aren't the same?
Thanks.
Thanks for the suggestions.
I tried the Gimp approach first which works well except when the difference between the images are very small. I couldn't find an "enhance differences" option to make the differences obvious and the histogram also only gives a rough representation of the differences.
In the end I used ImageMagick something I'd installed a while ago and forgot all about. Creating a difference/comparison image is as easy as typing:
compare first.jpg second.png difference.gif
in the command line.
It's all nicely explained here.
TortoiseIDiff is a free image diff viewer:
http://tortoisesvn.tigris.org/TortoiseIDiff.html
It is part of TortoiseSVN, but can be used without Subversion.
Depending on your project, not all files which are under version
control are text files. Most likely you will have images too, for
example screenshots and diagrams for the documentation/helpfile.
For those files it's not possible to use a common file diff tool,
because they only work with text files and diff line-by-line. Here is
where the Tortoise Image Diff tool (TortoiseIDiff) comes to the
rescue. It can show two images side-by-side, or even show the images
over each other alpha blended.
You could do a lot worse than Perceptual Diff.
The best approach would be to use Pix for windows (comes with the DirectX SDK). Supports Bitmap, PNG and Jpeg...Enjoy!
Use an image editor like Photoshop or the Gimp or whatever, which has multiple layers. Create an image where each source image in a separate layer.
At this point, you can visually compare the images by toggling the top layer's visibility off and on.
In most decent editors, you can also set the top layer to "difference" mode. Now each image pixel's value is the absolute difference of the pixel values in the underlying images. You can use e.g. a histogram tool to see if the images are identical. If they're identical, then all the pixel values will be exactly 0.
For stuff like this, I love the netpbm/pbmplus toolkit. You can use djpeg and pnmtoplainpnm to convert each image into a simple ASCII format. You then just read both files and emit a new image which shows where pixels differ. You could, for example, compute the Euclidean distance in RGB space between old and new pixels and emit a white pixel for zero difference, light gray for a small difference, darker for larger differences, and so on. The ASCII format is simple and is well documented on the man pages, and all the standard viewer programs can view it directly.
The latest version of Araxis Merge will do image diffs ( http://www.araxis.com/merge/topic_comparing_image_files.html ).
Unfortunately it's not a free app so whether or not you're willing to pay for it is another thing...
There's also a convenient web app called Resemble.js, which analyzes and compares images pixel by pixel. The different pixels in the images (if any) are highlighted with pink or yellow color depending on your preference.