How can I modify image from java through ImageMagick? Is there any way of doing it?
Use JMagick (docs). Read the documentation. It provides all the functionality of ImageMagick. You may also look into another ImageMagick Java wrapper, im4java.
There is a good starters document for im4java here
Here is an example, I've worked out.
/** Typical scaling implementation using JMagick **/
ImageInfo origInfo = new ImageInfo(absPath); //load image info
MagickImage image = new MagickImage(origInfo); //load image
image = image.scaleImage(finalWidth, finalHeight); //to Scale image
image.setFileName(absNewFilePath); //give new location
image.writeImage(origInfo); //save
Edit #1:
If you are wondering for the Jar file of JMagick. Download jMagick tarball, untar it.
$ tar xvzf jmagick-linux-6.4.0-Q32.tar.gz
./jmagick-6.4.0.jar
./jmagick.jar
./libJMagick-6.4.0.so
./libJMagick.so
How to Install JMajick on Windows
Go to http://downloads.jmagick.org/6.3.9/ (or any other version of your choice)
Download ImageMagick-6.3.9-0-Q8-windows-dll.exe and jmagick-win-6.3.9-Q8.zip.
Install the exe file. This will install ImageMagick which is a prerequisite for JMagick to work.
Now extract the zip file. This will give jmagick.dll and jmagick.jar.
Copy the jmagick.jar to you lib folder and include it in the classpath.
Copy the jmagick.dll to the root installation directory of ImageMagic and add it as an entry to the PATH environment variable.
JMagick is installed :).
For ImageMagic 1.4.0
// create command
ConvertCmd cmd = new ConvertCmd();
// create the operation, add images and operators/options
IMOperation op = new IMOperation();
op.addImage("source_picture.jpg"); // source file
op.resize(800,600);
// of op.resize(800); // and height calculate automatically
op.addImage("resized_picture.jpg"); // destination file file
// execute the operation
cmd.run(op);
And if you like maven!
<dependency>
<groupId>org.im4java</groupId>
<artifactId>im4java</artifactId>
<version>1.4.0</version>
</dependency>
Resizing an image (using the easiest method) within the J2SE.
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.net.URL;
class ResizeImage {
public static void main(String[] args) throws Exception {
URL url = new URL("http://pscode.org/media/citymorn2.jpg");
final BufferedImage bi = ImageIO.read(url);
Runnable r = new Runnable() {
public void run() {
JLabel unresize = new JLabel(new ImageIcon(bi));
int width = (int)(bi.getWidth()*.75);
int height = (int)(bi.getHeight()*.75);
BufferedImage bi1 = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics g1 = bi1.getGraphics();
g1.drawImage( bi, 0, 0, width, height, null );
JLabel easyResize = new JLabel(new ImageIcon(bi1));
JPanel p = new JPanel();
p.add( unresize );
p.add( easyResize );
JOptionPane.showMessageDialog(null, p);
}
};
SwingUtilities.invokeLater(r);
}
}
I tried using imagemagick from Java but found hardware accelerated 100% java library for image operations.
https://github.com/thebuzzmedia/imgscalr
"This library makes uses of efficient Java2D scaling techniques advocated by the Java2D team which provides hardware accelerated operations on most platforms."
Related
I don't know what to do with TIFF images, but I can't read or write any of them using straight Java standard ImageIO library. Any thoughts?
Thanks.
If you don't like or can't use JAI for any reason I have written a TIFF ImageReader plugin for ImageIO, available on GitHub. It is pure Java and does not need any native installs, and comes with a very friendly open source license (BSD).
It supports any baseline TIFF option, along with a lot of standard extensions. From version 3.1 the TIFF plugin also has write support.
With the proper JARs in your class path, usage can be as simple as:
BufferedImage image = ImageIO.read(inputTIFF);
// ...modify image (compose, resize, sharpen, etc)...
ImageIO.write(image, "TIFF", outputTIFF);
According to JEP 262: TIFF Image I/O the TIFF plugin that used to be part of JAI will be available as part of the Java SE, starting from Java 9.
That means, using Java 9 or later, the following code will just work, without any extra imports or dependencies:
BufferedImage image = ImageIO.read(inputTIFF);
// ...modify image (compose, resize, sharpen, etc)...
ImageIO.write(image, "TIFF", outputTIFF);
I haven't yet been able to verify the support for non-baseline TIFF flavors in this plugin, but I assume at least baseline TIFFs should be fully supported.
I tried JAI, and it didn't work for me.
Where are you stuck? Does the following work for you?
import java.io.File;
import java.io.FileOutputStream;
import java.awt.image.RenderedImage;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import javax.media.jai.NullOpImage;
import javax.media.jai.OpImage;
import com.sun.media.jai.codec.SeekableStream;
import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.TIFFDecodeParam;
import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.ImageCodec;
public class Main {
public static void main(String args[]) {
File file = new File("input.tif");
try {
SeekableStream s = new FileSeekableStream(file);
TIFFDecodeParam param = null;
ImageDecoder dec = ImageCodec.createImageDecoder("tiff", s, param);
RenderedImage op = new NullOpImage(dec.decodeAsRenderedImage(0),
null,
OpImage.OP_IO_BOUND,
null);
FileOutputStream fos = new FileOutputStream("output.jpg");
JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(fos);
jpeg.encode(op.getData());
fos.close();
}
catch (java.io.IOException ioe) {
System.out.println(ioe);
}
}
}
Java supports TIFF format only from Java 9 release. If you are trying to use ImageIO for TIFF into older Java version it will give you exception.
If you want to use TIFF in earlier version as well, you Twelve Monkey plugin along with Java just by adding dependency of Twelve Monkey.
Maven Dependency for Twelve Monkey:
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.5</version>
</dependency>*
I'm also giving example to merge the multiple images into Single TIFF with pages using Twelve Monkey,
BufferedImage b1 = null;
BufferedImage b2 = null;
TIFFImageReaderSpi SPI = new TIFFImageReaderSpi();
ImageReader imageReader1 = SPI.createReaderInstance();
ImageInputStream iis1 = ImageIO.createImageInputStream(new File("1.tif"));
imageReader1.setInput(iis1);
b1 = imageReader1.read(0);
ImageReader imageReader2 = SPI.createReaderInstance();
ImageInputStream iis2 = ImageIO.createImageInputStream(new File("2.tif"));
imageReader2.setInput(iis2);
b2 = imageReader2.read(0);
ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next();
writer.setOutput(ImageIO.createImageOutputStream(new File("3.tif")));
ImageWriteParam writeParam = writer.getDefaultWriteParam();
//writeParam.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
//writeParam.setCompressionType("Deflate");
writer.prepareWriteSequence(null);
IIOImage i1 = new IIOImage(b1, null, null);
IIOImage i2 = new IIOImage(b2, null, null);
writer.writeToSequence(i1, writeParam);
writer.writeToSequence(i2, writeParam);
writer.endWriteSequence();
writer.dispose();
The above code will work with Java8 and written to open two TIFF image and merge into single.
Also, you may use compression as needed. Just use comment lines to add compression.
Add Maven dependency :
<dependency>
<groupId>org.geotoolkit</groupId>
<artifactId>geotk-coverageio</artifactId>
<version>3.17</version>
</dependency>
Code example :
import org.geotoolkit.image.io.plugin.RawTiffImageReader;
IIORegistry registry = IIORegistry.getDefaultInstance();
registry.registerServiceProvider(new RawTiffImageReader.Spi());
String[] a = ImageIO.getReaderFileSuffixes();
for (int i=0; i<a.length; i++) {
System.out.println(a[i]);
}
BufferedImage image = ImageIO.read(new File("C:\\mypic.tiff"));
ImageIO.write(image, "jpg",new File("C:\\out.jpg"));
ImageIO.write(image, "gif",new File("C:\\out.gif"));
ImageIO.write(image, "png",new File("C:\\out.png"));
ImageIO.write(image, "tif",new File("C:\\out.tiff"));
I'm am trying to get the Icon from a .lnk file, put it into a javafx Image and then save it as a .png file (to ensure it's working).
My current code compiles but does not work:
import java.io.*;
import java.util.*;
import javax.swing.filechooser.FileSystemView;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javafx.embed.swing.SwingFXUtils;
import java.awt.image.BufferedImage;
import java.awt.Graphics;
import javafx.scene.image.Image;
import javax.imageio.ImageIO;
class Iconic {
public static void main(String[] args) throws IOException{
File origin = new File("C:\\Users\\00001\\OneDrive.lnk");
Icon icn = FileSystemView.getFileSystemView().getSystemIcon(origin);
ImageIcon ico = ((ImageIcon) icn);
BufferedImage bi = new BufferedImage(
ico.getIconWidth(),
ico.getIconHeight(),
BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
ico.paintIcon(null,g,0,0);
g.dispose();
Image img = SwingFXUtils.toFXImage(bi,null);
File output = new File("C:\\Users\\00001\\");
BufferedImage bim = SwingFXUtils.fromFXImage(img,null);
ImageIO.write(bim,".png",output);
}
}
You are almost there, however, there are two issues in your code. Both are related to the ImageIO.write(...) method.
From the API doc of ImageIO.write(RenderedImage, String, File):
Writes an image using an arbitrary ImageWriter that supports the given format to a File. If there is already a File present, its contents are discarded.
Parameters:
im - a RenderedImage to be written.
formatName - a String containg the informal name of the format.
output - a File to be written to.
The second parameter is the format name, not the file extension. So, the second argument should be "PNG", not ".png". Because ImageIO does not find any plugins that can write ".png" format, the write(...) invocation will just silently return false. I recommend always checking the return value of ImageIO.write(...).
The third parameter is the destination file to write. The path of this file has to point to a file, however yours point only to a directory. If you fix only the format name above, you'll see that most likely you get an IOException.
So, a fixed version of your writing code would like like:
File output = new File(origin.getParentFile(), origin.getName().replace(".lnk", ".png"));
if (!ImageIO.write(bi, "PNG", output)) {
System.err.println("Could not write icon");
}
I deliberately left the conversion from FX Image out. You should be able to write bi directly, without conversion to and from FX Image(unless, of course, you manipulate the image in FX).
I have been trying to use Barcode4J on Android but I can not seem to get BufferedImage class and I am not sure how I am suppose to replace this class with anything from Android.graphic.* which does not seem to have something similar. Also the Barcode4J will not accept anything other then BufferedImage object for obvious reasons.
What could I use instead or is there a Barcode generator Lib better suited for Android?
I have tried Barcode4Android which really made no sense since the Example they gave on GIT used BufferedImage from the java.awt.image.BufferedReader package also >.< . So I was back at step 1.
I actually just need the QR generating function.
My Questions.
1. Is there an Alternative to Barcode4J for Android.
2. OR is there a work around for my problem ?
Here is one of the Java tutorials I tried to use
public class HelloExample1 {
public static void main(String[] args) throws Exception{
//Create the barcode bean
Code39Bean bean = new Code39Bean();
final int dpi = 150;
//Configure the barcode generator
bean.setModuleWidth(UnitConv.in2mm(1.0f / dpi)); //makes the narrow bar, width exactly one pixel
bean.setWideFactor(3);
bean.doQuietZone(false);
//Open output file
File outputFile = new File("resources"+"/"+"images"+"/"+"out.png");
OutputStream out = new FileOutputStream(outputFile);
try {
//Set up the canvas provider for monochrome PNG output
BitmapCanvasProvider canvas = new BitmapCanvasProvider(
out, "image/x-png", dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);
//Generate the barcode
bean.generateBarcode(canvas, "Hello World");
//Signal end of generation
canvas.finish();
} finally {
out.close();
}
}
}
Try Zxing, its a code generator and reader, easy to use in Android. Hope it helps.
I am attempting to display a .tif in Java using a minimal number of additional libraries:
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;
import javax.media.jai.widget.*;
import it.geosolutions.imageio.utilities.*;
import it.geosolutions.imageioimpl.plugins.tiff.*;
import com.sun.media.imageioimpl.common.*;
public static void main(String[] args) {
try {
File f = new File("image.tif");
BufferedImage tif = ImageIO.read(f);
ImageIcon ic = new ImageIcon(tif);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JLabel label = new JLabel(ic);
frame.add(label);
frame.setVisible(true);
} catch (IOException e) {
e.printStackTrace();
}
}
The libraries I'm using are:
jai-core-1.1.3.jar
jai-imageio-1.1.jar
imageio-ext-tiff.1.1.3.jar
imageio-ext-utilities.1.1.3.jar
From here: http://java.net/projects/imageio-ext (Downloads link on right side)
However, the displayed image is:
which is decidedly not the original image. Nor are any errors being thrown that I know of. Furthermore, the original image is fine, and doesn't change.
However, the original code is small. I don't actually use the imageio-ext imports, but the program will fail without them. I also haven't used imageio-ext before either.
Please help! I need to be able to use .tif images in Java without installing software.
If you already use all JAI/ImageIO libraries, you might want to try the following (which works fine for me):
import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageDecoder;
// This function is minimal, you should add exceptions and error handling
public RenderedImage read(String filename)
FileSeekableStream fss = new FileSeekableStream(filename);
ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", fss, null);
RenderedImage image = decoder.decodeAsRenderedImage()
fss.close();
return image;
}
If you need a BufferedImage instead of a RenderedImage, the only solution I found is to use this function:
public static BufferedImage Rendered2Buffered(RenderedImage image) {
BufferedImage bi = new BufferedImage(image.getWidth(), image.getHeight(), image.getSampleModel().getDataType());
bi.setData(image.getData());
return bi;
}
Be careful though, the image.getSampleModel().getDataType() usually returns a BufferedImage.TYPE_CUSTOM, which makes it impossible for the BufferedImage to be created! In my case I had to "guess" the type according to the sample size returned by image.getSampleModel().getSampleSize(0) (because I know the image format I'm working with).
If you know a better way to transform a RenderedImage to a BufferedImage, please enlighten me :)
You're correct in thinking that you need the JAI libraries to decode and use TIFF files, but even though you've imported them, you aren't actually using them!
Here is a short tutorial showing how you to create a TIFFDecodeParam object (from the JAI library), and then use that to decode (and display) a TIFF image.
You might also find the JAI API Library useful too.
I ended up going with the most-recent version of Apache-Commons Imaging (formerly Sanselan). Imaging offers out of the box support for TIFF files (I had as little bit of trouble at first, but that was solved by switching from the older Sanselan to the newer Commons Imaging).
There was a little bit of functionality I had to reverse-engineer myself (loading a single sub-TIFF at a specified width while maintaining aspect ratio):
/**
* Load a scaled sub-TIFF image. Loads nth sub-image and scales to given width; preserves aspect ratio.
*
* #param fileName String filename
* #param index Index of sub-TIFF; will throw ArrayIndexOutOfBoundsException if sub-image doesn't exist
* #param w Desired width of image; height will scale
* #return Image (BufferedImage)
* #throws IOException
* #throws ImageReadException
*/
public static Image loadScaledSubTIFF(String fileName, int index, int w) throws IOException, ImageReadException {
File imageFile = new File(fileName);
ByteSourceFile bsf = new ByteSourceFile(imageFile);
FormatCompliance formatCompliance = FormatCompliance.getDefault();
TiffReader tiffReader = new TiffReader(true);
TiffContents contents = tiffReader.readDirectories(bsf, true, formatCompliance);
TiffDirectory td = contents.directories.get(index);
Image bi = td.getTiffImage(tiffReader.getByteOrder(), null);
Object width = td.getFieldValue(new TagInfo("", 256, TiffFieldTypeConstants.FIELD_TYPE_SHORT) {/**/});
Object height = td.getFieldValue(new TagInfo("", 257, TiffFieldTypeConstants.FIELD_TYPE_SHORT) {/**/});
int newWidth = w;
int newHeight = (int) ((newWidth * ((Number)height).doubleValue()) / (((Number)width).doubleValue()));
bi = bi.getScaledInstance(w, newHeight, java.awt.Image.SCALE_FAST);
height = null;
width = null;
td = null;
contents = null;
tiffReader = null;
formatCompliance = null;
bsf = null;
return bi;
}
I don't know what to do with TIFF images, but I can't read or write any of them using straight Java standard ImageIO library. Any thoughts?
Thanks.
If you don't like or can't use JAI for any reason I have written a TIFF ImageReader plugin for ImageIO, available on GitHub. It is pure Java and does not need any native installs, and comes with a very friendly open source license (BSD).
It supports any baseline TIFF option, along with a lot of standard extensions. From version 3.1 the TIFF plugin also has write support.
With the proper JARs in your class path, usage can be as simple as:
BufferedImage image = ImageIO.read(inputTIFF);
// ...modify image (compose, resize, sharpen, etc)...
ImageIO.write(image, "TIFF", outputTIFF);
According to JEP 262: TIFF Image I/O the TIFF plugin that used to be part of JAI will be available as part of the Java SE, starting from Java 9.
That means, using Java 9 or later, the following code will just work, without any extra imports or dependencies:
BufferedImage image = ImageIO.read(inputTIFF);
// ...modify image (compose, resize, sharpen, etc)...
ImageIO.write(image, "TIFF", outputTIFF);
I haven't yet been able to verify the support for non-baseline TIFF flavors in this plugin, but I assume at least baseline TIFFs should be fully supported.
I tried JAI, and it didn't work for me.
Where are you stuck? Does the following work for you?
import java.io.File;
import java.io.FileOutputStream;
import java.awt.image.RenderedImage;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import javax.media.jai.NullOpImage;
import javax.media.jai.OpImage;
import com.sun.media.jai.codec.SeekableStream;
import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.TIFFDecodeParam;
import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.ImageCodec;
public class Main {
public static void main(String args[]) {
File file = new File("input.tif");
try {
SeekableStream s = new FileSeekableStream(file);
TIFFDecodeParam param = null;
ImageDecoder dec = ImageCodec.createImageDecoder("tiff", s, param);
RenderedImage op = new NullOpImage(dec.decodeAsRenderedImage(0),
null,
OpImage.OP_IO_BOUND,
null);
FileOutputStream fos = new FileOutputStream("output.jpg");
JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(fos);
jpeg.encode(op.getData());
fos.close();
}
catch (java.io.IOException ioe) {
System.out.println(ioe);
}
}
}
Java supports TIFF format only from Java 9 release. If you are trying to use ImageIO for TIFF into older Java version it will give you exception.
If you want to use TIFF in earlier version as well, you Twelve Monkey plugin along with Java just by adding dependency of Twelve Monkey.
Maven Dependency for Twelve Monkey:
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.5</version>
</dependency>*
I'm also giving example to merge the multiple images into Single TIFF with pages using Twelve Monkey,
BufferedImage b1 = null;
BufferedImage b2 = null;
TIFFImageReaderSpi SPI = new TIFFImageReaderSpi();
ImageReader imageReader1 = SPI.createReaderInstance();
ImageInputStream iis1 = ImageIO.createImageInputStream(new File("1.tif"));
imageReader1.setInput(iis1);
b1 = imageReader1.read(0);
ImageReader imageReader2 = SPI.createReaderInstance();
ImageInputStream iis2 = ImageIO.createImageInputStream(new File("2.tif"));
imageReader2.setInput(iis2);
b2 = imageReader2.read(0);
ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next();
writer.setOutput(ImageIO.createImageOutputStream(new File("3.tif")));
ImageWriteParam writeParam = writer.getDefaultWriteParam();
//writeParam.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
//writeParam.setCompressionType("Deflate");
writer.prepareWriteSequence(null);
IIOImage i1 = new IIOImage(b1, null, null);
IIOImage i2 = new IIOImage(b2, null, null);
writer.writeToSequence(i1, writeParam);
writer.writeToSequence(i2, writeParam);
writer.endWriteSequence();
writer.dispose();
The above code will work with Java8 and written to open two TIFF image and merge into single.
Also, you may use compression as needed. Just use comment lines to add compression.
Add Maven dependency :
<dependency>
<groupId>org.geotoolkit</groupId>
<artifactId>geotk-coverageio</artifactId>
<version>3.17</version>
</dependency>
Code example :
import org.geotoolkit.image.io.plugin.RawTiffImageReader;
IIORegistry registry = IIORegistry.getDefaultInstance();
registry.registerServiceProvider(new RawTiffImageReader.Spi());
String[] a = ImageIO.getReaderFileSuffixes();
for (int i=0; i<a.length; i++) {
System.out.println(a[i]);
}
BufferedImage image = ImageIO.read(new File("C:\\mypic.tiff"));
ImageIO.write(image, "jpg",new File("C:\\out.jpg"));
ImageIO.write(image, "gif",new File("C:\\out.gif"));
ImageIO.write(image, "png",new File("C:\\out.png"));
ImageIO.write(image, "tif",new File("C:\\out.tiff"));