So I have this GIF file on my desktop (it's a 52 card deck of poker cards). I have been working on a program that cuts it up into little acm.graphics.GImages of each card. Now, however, I want to write those GImages or pixel arrays to a file so that I can use them later. I thought it would be as straight forward as writing .txt files, but a couple of Google searches later I am more confused than before.
So how do I go about making .gif files out of pixel arrays or GImages (I've got loads of both)?
Something along these lines should do the trick (modify the image type, dimensions and pixel array as appropriate):
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
WritableRaster raster = image.getRaster();
for ( i=0; i<width; i++ ) {
for ( j=0; j<height; j++ ) {
int[] colorArray = getColorForPixel(pixels[i][j]);
raster.setPixel(i, j, colorArray);
}
}
ImageIO.write(image, "gif", new File("CardImage"));
'getColorForPixel' will need to return an array representing the color for this pixel. In this case, using RGB, the colorArray will have three integers [red][green][blue].
Relevant javadoc: WritableRaster, BufferedImage and ImageIO.
I had to create GIF's out of Java Images for a university project, and I found this.
I would recommend Acme's Open-Source GifEncoder Class. Nice and easy to use, I still remember it over 2 years later.
Here's the link: http://www.acme.com/java/software/Acme.JPM.Encoders.GifEncoder.html
And here's the G-Link: http://www.google.com/search?hl=en&q=acme+java+gif&btnG=Search
It doesn't really answer your question directly, but wouldn't it be easier to use ImageMagick? It has Java bindings.
Related
I'm trying to reduce the filesize of a few PDF's in Java. I've found a few techniques to do this. But resizing images seems most effective.
I followed this piece of code which uses iText.
It works great on a few PDF's (reduction from 4.5MB to 800KB!) but some stayed unaffected.
I altered the code a bit as follows, so it would accept more Stream objects (and hopefully compress more):
PdfReader reader = new PdfReader(original.getPath());
int size = reader.getXrefSize();
for(int i=0;i<size;i++){
PdfObject object = reader.getPdfObject(i);
if (object == null || !object.isStream())
continue;
PRStream stream = (PRStream)object;
PdfImageObject image = new PdfImageObject(stream);
try{
BufferedImage bi = image.getBufferedImage();
//more stuff here
And it did! Some PDF's actually got compressed a lot more. However, I got a strange exception at some that didn't change at all:
javax.imageio.IIOException: Incompatible color conversion
at com.sun.imageio.plugins.jpeg.JPEGImageReader.checkColorConversion(JPEGImageReader.java:927)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1028)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:984)
at javax.imageio.ImageIO.read(ImageIO.java:1438)
at javax.imageio.ImageIO.read(ImageIO.java:1342)
at com.itextpdf.text.pdf.parser.PdfImageObject.getBufferedImage(PdfImageObject.java:302)
at com.example.compression.App.main(App.java:56)
(App.java:56 being the line that says image.getBufferedImage();)
Some research discovered, the Stream it was trying to open was a CMYK JPG.
I'm wondering why these wouldn't open, and how I can resize these images anyway.
Thanks
BufferedImage doesn't deal with CMYK nativally (and I'm not sure if Java does in other native components, anyway).
In the fields listed in Java 6 docs, there's no cmyk color model....
You can take a look at this site, someone tells you how to deal with BufferedImage and CMYK colorspace.
Good luck!
hi guys i am an infant for image processing technique in java , i have decided to develop one project in image processing so i need what are the algorithms are followed and also which one is easier to develop please some one guide me it may be great for me.....and also which technology is best for image processing java or Matlab? guide me...
I think the best image processing tool for you depends on the kind of project you're working on.
If you're working on a research project that needs productivity, quick validation and writting reports, Matlab and similar tools are the best option. On the other hand, if you're developing a software product, Java, C++, C, Objective-C, etc is more indicated. Matlab solutions are not easy to deliver and maintain in production.
Since you asked how to do image segmentation in Java, I'll provide an example using Java and Marvin Image Processing Framework. As suggested by #Asif Sharif, FloodFill segmentation is a good strategy and I used it!
INPUT IMAGE:
OUTPUT IMAGE:
HOW IT WORKS:
Load input image.
Change green pixels to white pixels.
Apply intensity thresholding for separating foreground from background.
Apply morphological closing to group separated parts of the same object
Use FloodFill segmentation to get the segments.
Draw the segments coordinates in the original image.
SOURCE:
import static marvin.MarvinPluginCollection.*;
public class SimpleSegmentation {
public SimpleSegmentation(){
// 1. Load image
MarvinImage original = MarvinImageIO.loadImage("./res/robocup.jpg");
MarvinImage image = original.clone();
// 2. Change green pixels to white
filterGreen(image);
// 3. Use threshold to separate foreground and background.
MarvinImage bin = MarvinColorModelConverter.rgbToBinary(image, 127);
// 4. Morphological closing to group separated parts of the same object
morphologicalClosing(bin.clone(), bin, MarvinMath.getTrueMatrix(30, 30));
// 5. Use Floodfill segmention to get image segments
image = MarvinColorModelConverter.binaryToRgb(bin);
MarvinSegment[] segments = floodfillSegmentation(image);
// 6. Show the segments in the original image
for(int i=1; i<segments.length; i++){
MarvinSegment seg = segments[i];
original.drawRect(seg.x1, seg.y1, seg.width, seg.height, Color.yellow);
original.drawRect(seg.x1+1, seg.y1+1, seg.width, seg.height, Color.yellow);
}
MarvinImageIO.saveImage(original, "./res/robocup_segmented.png");
}
private void filterGreen(MarvinImage image){
int r,g,b;
for(int y=0; y<image.getHeight(); y++){
for(int x=0; x<image.getWidth(); x++){
r = image.getIntComponent0(x, y);
g = image.getIntComponent1(x, y);
b = image.getIntComponent2(x, y);
if(g > r*1.5 && g > b*1.5){
image.setIntColor(x, y, 255,255,255);
}}}
}
public static void main(String[] args) { new SimpleSegmentation(); }
}
For image segmentation in JAVA you can also consider to use open-source IMMI tool (http://spl.utko.feec.vutbr.cz/en/). In comparison to Matlab, it is (in my opinion) more simple to use and simply enables also image mining.
You can use the Java Advanced Imaging (JAI) Library to do image processing in java. You have to decide for yourself whether Java or MATLAB is better for you.
Algorithm for Image segmentation depends upon what type of output you want after segmentation. Each algorithm performs a different segmentation. I think the region growing or Flood Fill is good for this purpose.
You can use Java/JAI and JavaCV for this Image processing tasks.
MATLAB is better for image processing. And the best way is to find special image processing tools (or libraries).
I need to translate colors in bitmap loaded to BufferedImage from RGB to YCbCr (luminance and 2 channels chrominance) and back after process.
I made it with functions used like rgb2ycbcr() in main method for each pixel, but it isn't so smart solution. I should use ColorSpace and ColorModel classes to get BufferedImage with correct color space. It would be more flexible method, but I don't know how to do that.
I'm lost and I need some tips. Can somebody help me?
As I understood your question, you want to do the following:
Load RGB image -> process YCbCr image -> Use RGB image again
And you want us to help you, to make this process as seamless as possible. First and foremost you want us to give you a simple way to avoid the -> (converting) parts.
Well I looked into the BufferedImage documentation. It seems, as if there doesn't exist a way to change the ColorSpace of an once created BufferedImage.
You could create a new BufferedImage with an YCbCr color space for that you can use the predefined ICC_ColorSpace. Then you copy the data from your old image possibly via ColorSpace.fromRGB to the YCbCr color space, do the image processing and then convert again via ColorSpace.toRGB. This method requires you to fully convert the image before and after processing via existing methods. Furthermore you have to know, how ICC_ColorSpace converts your image to YCbCr color space. Otherwise you can't know, which array indices corresponds to the same pixel.
If you just want to create a wrapper around the RGB-BufferedImage that lets you manipulate this image, as if it was an YCbCr image, that isn't possible with BufferedImage.
EDIT:
To convert the color space of a BufferedImage use ColorConvertOp. The code would look something like this:
ColorConvertOp cco = new ColorConvertOp(new YCbCrColorSpace(), null);
BufferedImage ycbcrImage = cco.filter( oldRGBImage, null );
This requires you to either write your own ColorSpace class or you could download and use the classes mentioned here. If you just want to load a JPEG image you should use the predefined classes.
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 have an int array containing gray scale values from 0-254, i also have the x and y size of the image. It is an easy thing to create an pgm image, but i want to display it in a jsp, so i need somehow to convert it to a jpeg or png image.
If you suggest jai, than please tell me at which classes to look, or how to actually do it in jai.
Thanks a lot, in advance.
Maybe skip the PGM entirely?
int[] myImage = getGreyscaleIntArray();
BufferedImage im = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
WritableRaster raster = im.getRaster();
for(int h=0;h<height;h++)
{
for(int w=0;w<width;w++)
{
raster.setSample(w,h,0, myImage[h * width + w]);
}
}
ByteArrayOutputStream myJpg = new ByteArrayOutputStream();
javax.imageio.ImageIO.write(im, "jpg", myJpg);
uses the JAI ImageIO api, specifically the ImageIO utility class
WriteableRaster sample from the Java Image Processing cookbook
ImageMagick works well for converting images and Jmagick provides an interface to call directly from java programs.