JavaCV Create Mat from Resource (InputStream) - java

I use JavaCV (not OpenCV). My goal is to obtain a Mat object from an image that is stored as a Resource. Then I'm going to pass this Mat into opencv_imgproc.matchTemplate method. I've managed to write this bad code:
InputStream in = getClass().getResourceAsStream("Lenna32.png");
BufferedImage image = ImageIO.read(in);
Frame f = new Java2DFrameConverter().getFrame(image);
Mat mat = new OpenCVFrameConverter.ToMat().convert(f);
This works in some cases. The problems are:
For png images that has transparency channel (that is 32BPP), it shifts channels, so that R=00 G=33 B=66 A=FF turns to R=33 G=66 B=FF
On my target environment, I can't use ImageIO
There are too many object conversions InputStream -> BufferedImage -> Frame -> Mat. I feel like there should be a simple and effective way to do this.
What is the best way to create Mat from a Resource?

I resolved this by reading bytes from InputStream and passing them into imdecode function:
InputStream is = context.getResourceAsStream("Lenna32.png");
int nRead;
byte[] data = new byte[16 * 1024];
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
byte[] bytes = buffer.toByteArray();
Mat mat = imdecode(new Mat(bytes), CV_LOAD_IMAGE_UNCHANGED);

Related

Any Alternative to ImageIO.write to convert bufferedimage to GIF bytes (Faster than ImageIO)?

my problem is when using imageio.write i am seeing that is using hdd, also read about jDeli (but too expensive), Apache Commons, JAI that are much faster....
I wanna use the encoded bytes returned by routine... at a custom Remote Desktop Utility...
public static byte[] imageToJPEGByteArray(Image aImage, int width, int height, int qualityPercent) throws IOException {
byte[] imageBytes = new byte[0];
float quality = 75 / 100f;
BufferedImage destImage;
destImage = SwingFXUtils.fromFXImage(aImage, null);
// Output JPEG byte array
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if(qualityPercent != -1) {
// Start to create JPEG with quality option
ImageWriter writer = null;
Iterator iter = ImageIO.getImageWritersByFormatName("gif");
if (iter.hasNext()) {
writer = (ImageWriter) iter.next();
}
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
writer.setOutput(ios);
ImageWriteParam iwparam = new JPEGImageWriteParam(Locale.getDefault());
iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwparam.setCompressionQuality(quality);
writer.write(null, new IIOImage(destImage, null, null), iwparam);
ios.flush();
writer.dispose();
ios.close();
// Done creating JPEG with quality option
} else {
// This one line below created a JPEG file without quality option
ImageIO.write(destImage, "gif", baos);
}
baos.flush();
imageBytes = baos.toByteArray();
baos.close();
// Done
return imageBytes;
}
If you are saying that you've observed that this code appears to cause disk activity when saving to ByteArrayOutputStream perhaps you should try setting the ImageIO "use cache" flag to false:
ImageIO.setUseCache(false);
Javadoc for setUseCache says:
Sets a flag indicating whether a disk-based cache file should be used when creating ImageInputStream and ImageOutputStreams.

Reduce size of byte array image screenshot selenium

I'm taking screenshot in my runs after every run but want to reduce the size so that it doesn't occupy too much space: every screenshot is 1mb on average, having 200 test with screenshot attached will give 200mb only for screenshots.
Attaching it to allure report
#Attachment
public byte[] attachScreenshot() {
try {
return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
} catch (Exception ignore) {return null;}
}
Any ideas on how to shrink the screenshot size?
Finally! Found the solution. My report size went from 70mb to 15mb by compressing to jpg:
private static byte[] pngBytesToJpgBytes(byte[] pngBytes) throws IOException {
//create InputStream for ImageIO using png byte[]
ByteArrayInputStream bais = new ByteArrayInputStream(pngBytes);
//read png bytes as an image
BufferedImage bufferedImage = ImageIO.read(bais);
BufferedImage newBufferedImage = new BufferedImage(bufferedImage.getWidth(),
bufferedImage.getHeight(),
BufferedImage.TYPE_INT_RGB);
newBufferedImage.createGraphics().drawImage(bufferedImage, 0, 0, Color.WHITE, null);
//create OutputStream to write prepaired jpg bytes
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//write image as jpg bytes
ImageIO.write(newBufferedImage, "JPG", baos);
//convert OutputStream to a byte[]
return baos.toByteArray();
}
```

bytes to Image Conversion in java

I am trying to convert Image to Byte Array and save it in database. Image to Byte Conversion and bytes to Image Conversion using ImageIO Method works completely fine before saving it into database. But when i retrieve bytes from Database ImageIO returns null.
FileInputStream fis = new FileInputStream(picturePath);
BufferedImage image = ImageIO.read(new File(picturePath));
BufferedImage img = Scalr.resize(image, Scalr.Mode.FIT_EXACT, 124, 133, Scalr.OP_ANTIALIAS);
ByteArrayOutputStream ByteStream = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", ByteStream);
ByteStream.flush();
byte[] imageBytes = ByteStream.toByteArray();
ByteStream.close();
PersonImage = imageBytes;
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(PersonImage);
BufferedImage ImageForBox = ImageIO.read((InputStream)byteArrayInputStream);
PersonImageBox.setIcon(new ImageIcon((Image)ImageForBox));
Above code is what I do before saving picture bytes in DB. I resize the Image then convert it into bytes and then convert other way around and show it in JLabel, it works fine. But when I retrieve bytes from database and use the same code i.e.
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(PersonImage); // PersonImage are bytes from dB.
BufferedImage ImageForBox = ImageIO.read((InputStream)byteArrayInputStream);
PersonImageBox.setIcon(new ImageIcon((Image)ImageForBox));
In this case ImageIO returns null. Please help.

Java: BufferedImage to byte array and back

I see that a number of people have had a similar problem, however I'm yet to try find exactly what I'm looking for.
So, I have a method which reads an input image and converts it to a byte array:
File imgPath = new File(ImageName);
BufferedImage bufferedImage = ImageIO.read(imgPath);
WritableRaster raster = bufferedImage .getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
What I now want to do is convert it back into a BufferedImage (I have an application for which I need this functionality). Note that "test" is the byte array.
BufferedImage img = ImageIO.read(new ByteArrayInputStream(test));
File outputfile = new File("src/image.jpg");
ImageIO.write(img,"jpg",outputfile);
However, this returns the following exception:
Exception in thread "main" java.lang.IllegalArgumentException: im == null!
This is because the BufferedImage img is null. I think this has something to do with the fact that in my original conversion from BufferedImage to byte array, information is changed/lost so that the data can no longer be recognised as a jpg.
Does anyone have any suggestions on how to solve this? Would be greatly appreciated.
This is recommended to convert to a byte array
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", baos);
byte[] bytes = baos.toByteArray();
Note that calling close or flush will do nothing, you can see this for yourself by looking at their source/doc:
Closing a ByteArrayOutputStream has no effect.
The flush method of OutputStream does nothing.
Thus use something like this:
ByteArrayOutputStream baos = new ByteArrayOutputStream(THINK_ABOUT_SIZE_HINT);
boolean foundWriter = ImageIO.write(bufferedImage, "jpg", baos);
assert foundWriter; // Not sure about this... with jpg it may work but other formats ?
byte[] bytes = baos.toByteArray();
Here are a few links concerning the size hint:
Java: Memory efficient ByteArrayOutputStream
jpg bits per pixel
Of course always read the source code and docs of the version you are using, do not rely blindly on SO answers.

How to get an InputStream from a BufferedImage?

How can I get an InputStream from a BufferedImage object? I tried this but ImageIO.createImageInputStream() always returns NULL
BufferedImage bigImage = GraphicsUtilities.createThumbnail(ImageIO.read(file), 300);
ImageInputStream bigInputStream = ImageIO.createImageInputStream(bigImage);
The image thumbnail is being correctly generated since I can paint bigImage to a JPanel with success.
From http://usna86-techbits.blogspot.com/2010/01/inputstream-from-url-bufferedimage.html
It works very fine!
Here is how you can make an
InputStream for a BufferedImage:
URL url = new URL("http://www.google.com/intl/en_ALL/images/logo.gif");
BufferedImage image = ImageIO.read(url);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, "gif", os);
InputStream is = new ByteArrayInputStream(os.toByteArray());
If you are trying to save the image to a file try:
ImageIO.write(thumb, "jpeg", new File(....));
If you just want at the bytes try doing the write call but pass it a ByteArrayOutputStream which you can then get the byte array out of and do with it what you want.
By overriding the method toByteArray(), returning the buf itself (not copying), you can avoid memory related problems. This will share the same array, not creating another of the correct size. The important thing is to use the size() method in order to control the number of valid bytes into the array.
final ByteArrayOutputStream output = new ByteArrayOutputStream() {
#Override
public synchronized byte[] toByteArray() {
return this.buf;
}
};
ImageIO.write(image, "png", output);
return new ByteArrayInputStream(output.toByteArray(), 0, output.size());

Categories

Resources