How to display a jpeg2000 image on a Jframe? - java

I have a jpeg2000 image, img.jp2 on a file, and on a DataInputStream object imgobj in my project, and want to show that image on a JFrame.
The old version jai_imageio-1.1.jar recommended here and the jj2000 library are both included.
I have tried:
j2kImageReader.setInput(new FileImageInputStream(new File(fileName)));
ImageReadParam imageReadParam =
j2kImageReader.getDefaultReadParam();
imageReadParam.setSourceRegion(new Rectangle(0, 0, 300, 300));
IIOImage image = j2kImageReader.readAll(0, imageReadParam);
// This type of images is difficult to handle,
// I just don't know what to do with IIOImage,
// ImageIcon doesn't accept that type in its constructor.
And this:
Image img = ImageIO.read(new File(fileName));
ImageIcon imgIcon = new ImageIcon(img);
JLabel label = new JLabel(imgIcon);
panel1.add(label);
panel1.repaint();
//Error: Can't read input file!. The panel is still empty
The option included in JMRTD is using two decoders, and no one of them accepts .jp2:
NistDecoder dec=new NistDecoder();
WsqDecoder wdec=new WsqDecoder();
//using the last one, I tried: bitmp= wdec.decode(myDataInputStream);
//but with Error, Invalid pointer : 0!.
So the question is: what is the proper use of jj2000 or jai_imageio to read a jpeg2000 image from a file or a DataInputStream, and if it is possible, to show it on a simple panel on a JFrame?
Thank you for help.
EDIT
AS requested in comments, this is what I did:
//1
FaceImageInfo imgfn = fsinf.getFaceImageInfos().get(0);
BufferedImage bf=ImageIO.read(imgfn.getImageInputStream());
ImageIcon iconImg = new ImageIcon();
iconImg= new ImageIcon(bf);// if this fails try write it to a stream and read it back see //2
JLabel(iconImg, JLabel.CENTER);
//2
ByteArrayOutputStream baos=null;
try{
baos=new ByteArrayOutputStream();
ImageIO.write(bf, "jpg", baos);
}
finally{
try{
baos.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
try {
ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
bf2=ImageIO.read(bais) ;
iconImg= new ImageIcon(bf2);
JLabel(iconImg, JLabel.CENTER);
} catch (Exception e) {
e.printStackTrace();
}

Assuming the code otherwise reads the image like you want it, you can easily get a BufferedImage from the ImageReader like this:
try (ImageInputStream input = ImageIO.createImageInputStream(new File(fileName))) {
j2kImageReader.setInput(input));
// Not sure why/if you want to read only the upper left, but I'll leave it as is
ImageReadParam imageReadParam = j2kImageReader.getDefaultReadParam();
imageReadParam.setSourceRegion(new Rectangle(0, 0, 300, 300));
// Use read instead of readAll
BufferedImage image = j2kImageReader.read(0, imageReadParam);
// You can now create an icon and add to a component
Icon icon = new ImageIcon(image);
JLabel label = new JLabel(icon);
// Etc...
}

Related

Convert an ImageIcon to a Base64 String and back to an ImageIcon without saving to disk?

I'm trying to store an imageIcon bas a Base64 String.
This is what I have so far:
public ImageIcon getImageIcon() {
if(imageIcon == null || imageIcon.isEmpty()){
return null;
} else {
try {
byte[] btDataFile = Base64.decodeBase64(imageIcon);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(btDataFile));
return new ImageIcon(image);
} catch (IOException ex) {
System.out.println(ex.getLocalizedMessage());
return null;
}
}
}
public void setImageIcon(ImageIcon imageIconIn) {
imageIcon = Base64.encodeBase64String(imageToByteArray(imageIconIn));
}
public static byte[] imageToByteArray(ImageIcon imageIn) {
try {
BufferedImage image = new BufferedImage(imageIn.getIconWidth(), imageIn.getIconHeight(),BufferedImage.TYPE_INT_RGB);
ByteArrayOutputStream b = new ByteArrayOutputStream();
// FIX
Graphics g;
g = image.createGraphics();
imageIn.paintIcon(null, g, 0,0);
// END FIX
ImageIO.write(image, "jpg", b );
g.dispose();
return b.toByteArray();
} catch (IOException ex) {
System.out.println(ex.getLocalizedMessage());
return null;
}
}
I get a black rectangle instead of the image.
I'm using Java 1.8 on Ubuntu 16.04.
What am I doing wrong?
Thanks for your help.
******************************** . FIXED . ******************************
I found a working solution and updated the above code.
******************************** EDIT *********************************
Added g.dispose() after painting icon.
This code creates a brand new BufferedImage, with width & height same as the given image.
BufferedImage image = new BufferedImage(
imageIn.getIconWidth(),
imageIn.getIconHeight(),
BufferedImage.TYPE_INT_RGB);
Note that the image is empty. No content has been written to it. The bytes will all be zero, and RGB 0x000000 is black.
Then, you are writing the bytes of this black image to your ByteArrayOutputStream.
ByteArrayOutputStream b = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", b );
return b.toByteArray();
Of course, when you convert that byte buffer back to an image, it will be black.
You will want to draw/copy imageIn into your new image before you write out the bytes.
But if you don't mind using whatever the current image's format is, you could just write out that image instead of converting it to TYPE_INT_RGB...
Image image = imageIn.getImage();
// write image to ByteArrayOutputStream

Output image becomes black after conversion from FileInputStream to Image

I am trying to merge two TIFF images which are in form of FileInputStream into a single Tiff image. Although the image is getting merged the output file is coming up as Black. While comparing the original image and the converted image I could see that the bit depth of the converted image changes to 1. Could anybody provide a solution to this?
The code that I am using is:
public class MergerTiffUsingBuffer {
public static void main(String[] args) {
File imageFile1 = new File("D:/Software/pdfbox-1.3.1.jar/tiff/FLAG_T24.TIF");
File imageFile2 = new File("D:/Software/pdfbox-1.3.1.jar/tiff/CCITT_3.TIF");
try {
FileInputStream fis1 = new FileInputStream(imageFile1);
FileInputStream fis2 = new FileInputStream(imageFile2);
List<BufferedImage> bufferedImages=new ArrayList<>();
List<FileInputStream> inputStreams=new ArrayList<>();
inputStreams.add(fis1);
inputStreams.add(fis2);
Iterator<?> readers = ImageIO.getImageReadersByFormatName("tiff");
ImageReader reader = (ImageReader) readers.next();
for(FileInputStream inputStream:inputStreams){
ImageInputStream iis = ImageIO.createImageInputStream(inputStream);
reader.setInput(iis);
ImageReadParam param = reader.getDefaultReadParam();
Image image = reader.read(0, param);
BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
OutputStream out = new FileOutputStream("D:/Software/pdfbox-1.3.1.jar/tiff/MergedTiff.TIF");
BufferedImage binarized = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(),BufferedImage.TYPE_BYTE_BINARY);
ImageIO.write(binarized, "tiff", out);
bufferedImages.add(bufferedImage);
}
System.out.println(bufferedImages.size());
} catch (IOException e2) {
e2.printStackTrace();
}
}
}
You seem to be a little confused about how to copy image data. Simply creating a new, blank image, by passing the dimensions of another image, will not copy it... So a fully black image is what I would expect after running your code.
Replace your for loop with something like this:
for (FileInputStream inputStream : inputStreams) {
ImageInputStream iis = ImageIO.createImageInputStream(inputStream);
reader.setInput(iis);
BufferedImage image = reader.read(0, null); // a) BufferedImage is returned! b) null param is fine!
BufferedImage binarized = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
// The following 7 lines is the important part you were missing:
Graphics2D g = binarized.createGraphics();
try {
g.drawImage(image, 0, 0, null);
}
finally {
g.dispose();
}
OutputStream out = new FileOutputStream("D:/Software/pdfbox-1.3.1.jar/tiff/MergedTiff.TIF");
ImageIO.write(binarized, "tiff", out); // You probably want to check return value (true/false)!
bufferedImages.add(image);
}

Opencv java - Load image to GUI

I'm developing an application using Java Opencv-2.4.4 and swing GUI. Problem is that I'm unable to find any solution, that shows efficient way how to print processed image (saved in Mat object) to java swing GUI. For this moment I'm using this clumsy solution:
javax.swing.JLabel outputImage;
outputImage.setIcon(new javax.swing.ImageIcon("/home/username/Output.png"));
private void sliderStateChanged(javax.swing.event.ChangeEvent evt) {
.
.
Mat canny; // Here is saved what I want to plot
String filename = "/home/username/Output.png";
Highgui.imwrite(filename, canny); // write to disk
outputImage.setIcon(new ImageIcon(ImageIO.read(new File(filename)))); //update Icon
.
.
}
When user changes some values, inputs etc ., in GUI I have to overwrite Output.png on disk and update jLabel with new image from disk.
Is there any more elegant / efficient solution to this ? Is it posible to plot or convert Mat object directly to Canvas or Image or anything that is printable as image in swing ?
Yes there is more elegant way to do it. You can concert Mat to BufferedImage type and then just Load it with swing. The code to convert it to Buffered image is:
Mat image_tmp = your image
MatOfByte matOfByte = new MatOfByte();
Highgui.imencode(".jpg", image_tmp, matOfByte);
byte[] byteArray = matOfByte.toArray();
BufferedImage bufImage = null;
try {
InputStream in = new ByteArrayInputStream(byteArray);
bufImage = ImageIO.read(in);
} catch (Exception e) {
e.printStackTrace();
}
And then you just can paint it in your GUI object:
g.drawImage(bufImage , 0, 0, null);
where g is of type Graphics
Hope this helps.
jpeg encoding is interesting, but there are a couple problems:
it is not a lossless format, you will lose image data when compressing
it takes quite a while (around 6 to 10 times longer than the suggested one below)
public Image toBufferedImage(Mat m){
int type = BufferedImage.TYPE_BYTE_GRAY;
if ( m.channels() > 1 ) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
int bufferSize = m.channels()*m.cols()*m.rows();
byte [] b = new byte[bufferSize];
m.get(0,0,b); // get all the pixels
BufferedImage image = new BufferedImage(m.cols(),m.rows(), type);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(b, 0, targetPixels, 0, b.length);
return image;
}
This is a readymade solution for Imshow() equivalent in Java OpenCV Its simple to use. API will look like:
Imshow im = new Imshow("Title");
im.showImage(matimage);
Visit here https://github.com/master-atul/ImShow-Java-OpenCV
This is a better solution as you don't store the image into disk and read again. Hence it reduces the overhead of reading from a disk and thus is faster.
Using #andriy's anwser. I came up with this solution. I used JFrame instead of Graphics. Hope this helps.
public void imshow(Mat src){
BufferedImage bufImage = null;
try {
MatOfByte matOfByte = new MatOfByte();
Highgui.imencode(".jpg", src, matOfByte);
byte[] byteArray = matOfByte.toArray();
InputStream in = new ByteArrayInputStream(byteArray);
bufImage = ImageIO.read(in);
JFrame frame = new JFrame("Image");
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(new JLabel(new ImageIcon(bufImage)));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} catch (Exception e) {
e.printStackTrace();
}
}

How to Read JPEG image into BufferedImage object using Java

This is not a duplicated question here, because I've been searching for the solution for a long time in Google and StackOverflow, and still cannot find a solution.
I have these two images:
These are two images from the same website with same prefix and same format. The only difference is the size: the first is larger, while the second is smaller.
I downloaded both of the images to local folder and used Java to read them into BufferedImage objects. However, when I outputted the BufferedImages to local files, I found that the first image was almost red, while the second was normal(same as original). What's wrong with my code?
byte[] rawData = getRawBytesFromFile(imageFilePath); // some code to read raw bytes from image file
ImageInputStream iis = ImageIO.createImageInputStream(new ByteArrayInputStream(rawData));
BufferedImage img = ImageIO.read(iis);
FileOutputStream fos = new FileOutputStream(outputImagePath, false);
ImageIO.write(img, "JPEG", fos);
fos.flush();
fos.close();
PS: I used GIMP to open the first image and detected that the Color Mode is 'sRGB', no alpha or other stuff.
This is apparently a know bug, I saw several suggestions (this is one) that suggest using Toolkit#createImage instead, which apparently ignores the color model.
I tested this and it seems to work fine.
public class TestImageIO01 {
public static void main(String[] args) {
try {
Image in = Toolkit.getDefaultToolkit().createImage("C:\\hold\\test\\13652375852388.jpg");
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(in)), "Yeah", JOptionPane.INFORMATION_MESSAGE);
BufferedImage out = new BufferedImage(in.getWidth(null), in.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = out.createGraphics();
g2d.drawImage(in, 0, 0, null);
g2d.dispose();
ImageIO.write(out, "jpg", new File("C:\\hold\\test\\Test01.jpg"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
nb- I used the JOptionPane to verify the incoming image. When using ImageIO it comes in with the red tinge, with Toolkit it looks fine.
Updated
And an explantation
I checked your code in netbeans and faced with your problem, then I changed the code as below that has no problem:
public class Test {
public static void main(String args[]) throws IOException {
byte[] rawData = getRawBytesFromFile(imageFilePath); // some code to read raw bytes from image file
// ImageInputStream iis = ImageIO.createImageInputStream(new ByteArrayInputStream(rawData));
// BufferedImage img = ImageIO.read(iis);
FileOutputStream fos = new FileOutputStream(outputImagePath, false);
fos.write(rawData);
// ImageIO.write(img, "JPEG", fos);
fos.flush();
fos.close();
}
private static byte[] getRawBytesFromFile(String path) throws FileNotFoundException, IOException {
byte[] image;
File file = new File(path);
image = new byte[(int)file.length()];
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(image);
return image;
}
}
Please check it and inform me of the result ;)
Good Luck
I suspect this solution might work just fine in the original poster's case.
String fileName = imageFilePath;
File inFile = new File(fileName);
BufferedImage img = ImageIO.read(inFile);
...
Best,

Saving an icon on a jLabel as an Image on the hard disk

I have a an Image Icon generated in my code which i place it as an icon on a label as per the following code:
ImageIcon icon = new ImageIcon(barcode.drawBarcode());
jLabel36.setIcon(icon);
Now my problem is that how can i change the ImageIcon type to Image and save it on the hard disk. when i try to type cast ImageIcon to Image i get the following error :
java.lang.ClassCastException: javax.swing.ImageIcon cannot be cast to java.awt.Image
Can anyone suggest me how can i achieve this task both type casting and saving the image.
Just use getImage():
// get image from imageicon
Image image = icon.getImage();
// cast it to bufferedimage
BufferedImage buffered = (BufferedImage) image;
try {
// save to file
File outputfile = new File("saved.png");
ImageIO.write(buffered, "png", outputfile);
} catch (IOException e) {
e.printStackTrace();
}

Categories

Resources