Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: im == null - java

hi i'm working on a project in which i need to make changes to BASE64 string of an image(jpg)...so at first when i didn't made any changes, the ImageReader was properly working and my image was displayed properly..but when i made changes to my BASE64 string the above exception came..i searched a lot and came to know that im==null comes when ByteStream is not jpeg,png,gif..etc..so what if i have a new type of ByteStream...what should i use?? or what ever my BASE64 string is i need to convert that to an image..so how can i do that??
here is my code snippet:this is to convert BASE64 string to an image
public static BufferedImage decodeToImage(String imageString) throws IOException {
BufferedImage image = null;
byte[] imageByte;
try {
BASE64Decoder decoder = new BASE64Decoder();
imageByte = decoder.decodeBuffer(imageString);
ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
image = ImageIO.read(bis);
bis.close();
}
catch (Exception e) {
e.printStackTrace();
}
ImageIO.write(image, "jpg", new File("d:/CopyOfTestImage.jpg"));
return image;
}

Have a look at the Javadocs for ImageIO.read:
Returns a BufferedImage as the result of decoding a supplied InputStream with an ImageReader chosen automatically from among those currently registered. The InputStream is wrapped in an ImageInputStream. If no registered ImageReader claims to be able to read the resulting stream, null is returned. [emphasis mine]
The read method can return null, yet you are not checking for this. In fact the method is probably returning null, which is why ImageIO.write throws an exception when you pass null into it.
First things first, you need to check for error conditions and handle them appropriately (including the null return, but also including any exceptions that are thrown, which you currently catch and ignore).
Now if you're getting null back from ImageIO.read, it means the bytes you passed into the read method did not appear to be a valid image in any known format. You need to look in more detail at the modifications you're making to the base64 string, and ensure that what you're doing is valid, and results in a valid image. Alternatively, if you're getting some other exception thrown, then you need to handle that appropriately.
(As a general rule, don't throw away/skip over errors, because then when things go wrong you have no idea why!)

change this line:
ImageIO.write(image, "jpg", new File("d:/CopyOfTestImage.jpg"));
to something like this
image = ImageIO.read(getClass().getResource("/resources/CopyOfTestImage.jpg"));

Related

Use mockito and junit to test images

I have a method that gets as parameter a MultipartFile object. Inside the method I use ImageIO.read(some_value) and ImageIO.write(some_value). I want to test this method with a mock image (I don't want to have images stored under the resource folder).
I've tried this:
MockMultipartFile file = new MockMultipartFile("file", "boat.jpg", "image/jpeg", "content image".getBytes()); but without success.
public void f(MultipartFile file) throws IOException {
final BufferedImage read = ImageIO.read(new ByteArrayInputStream(file.getBytes()));
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
ImageIO.write(read, "jpg", baos);
}
}
When I run the test the read variable has null value. I think that problem come from "content image".getBytes().
Is there a posibility to use mock images instead of real ones ?
"content image".getBytes() returns a byte[] representation of the String "content image". How is ImageIO supposed to construct a BufferedImage from that?
You have two options here.
Pass a byte[] of real data to MockMultipartFile
Since you mentioned you don't want to use mock image resources, this does not seem like a good fit.
Mock ImageIO's static methods using Powermock
The mocked method will return a real BufferedImage your method can use, without having to read an image from a file.
This gives you the added benefit of being able to mock the call to write() as well, if you wish.
Sample code:
PowerMockito.mockStatic(ImageIO.class);
when(ImageIO.read(any())).thenAnswer(invocation -> {
Object argument = invocation.getArguments()[0];
// here you can check what arguments you were passed
BufferedImage result = new BufferedImage(600, 400, BufferedImage.TYPE_INT_RGB); // create a BufferedImage object
// here you can fill in some data so the image isn't blank
return result;
});
Now, when your method under test calls imageIO.read(), it will receive the BufferedImage you construct in the lambda, without actually reading any files.

BitmapFactory.decodeStream returns null when reading from internal storage

I attempt to read images from the internal storage,
when I decode FileInputStream, BufferedInputStream or a File
using BitmapFactory I get null as a result:
//mImages is an ArrayList of image file names, "a.jpg","b.jpg", etc.
//This is inside my custom adapter for returing ImageViews from mImages:
public View getView(int position, View ..., ViewGroup...){
Context base_context = MyApplication.getAppContext();
String currentImageFilename = mImages.get(position); //say this is "cat.jpg"
//after this line f = "/data/user/0/mobile.foo.bar/files/cat.jpg"
File f = base_context.getFileStreamPath(currentImageFilename);
Boolean ex = f.exists(); //returns true, inserted only for debugging as no
//exception was thrown when decoding the bitmap and the result is null
BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(f));
Bitmap img = BitmapFactory.decodeStream(buffer); // img is null after this line
imageView.setImageBitmap(img);
}
I tried all other answers I could find, but no luck so far.
If you're running this code on Android 7 and you use BitmapFactory.decodeStream you need to reset InputStream every time you want yo use it again.
For example I used it twice, first to get some metrics and then to decode into Bitmap. And it worked fine on all versions prior to Android 7.
Now I need to reset it, otherwise it returns null:
BitmapFactory.decodeStream(iStream, null, options);
...
try {
iStream.reset();
} catch (IOException e) {
return null;
}
...
BitmapFactory.decodeStream(iStream, null, options);
Resetting inputStream won't cause any bugs on older versions so it's safe to use.
If it helped in your case - all credits to this guy: https://stackoverflow.com/a/41753686/5502121

Same Image, but different base64

I used the following function to create a base64 encoded string of my Gravatar image (https://www.gravatar.com/avatar/cd5415f97afbe0177ba35ae31fbfd0db):
final BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(inputStreamToByteArray(is));
encoded = encoded.replaceAll("\r?\n", "");
return encoded;
I ran the method a couple of days ago and got the following base64 encoded string:
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
Just today I executed the method again, using the same image. But instead of retrieving the same encoded string, I received:
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
As you may notice, the first couple of characters are the same, but if you look at the end of the strings, you notice directly that they are completely different. Why is that? The image is still my Gravatar image (e.g., using http://codebeautify.org/base64-to-image-converter shows the same image for both strings).
Thanks for any hint, explanation! Is there anything wrong with my implementation? Is some of the implementation time or location dependent? How can I get the same base64 string for the same image?
PS: inputStreamToByteArray is implemented as follows:
public static byte[] inputStreamToByteArray(final InputStream is) {
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
final byte[] data = new byte[16384];
try {
int nRead;
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
} catch (final IOException e) {
return null;
} finally {
try {
buffer.close();
} catch (final IOException e) {
// ignore
}
}
return buffer.toByteArray();
}
Converting both images back to .jpg, and using http://regex.info/exif.cgi, the following header comments appear:
One:
CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), quality = 90
Other:
CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 90
(can't remember which order I converted the images in, but there is a version change either way)
As you can see, they have upgraded the JPEG compressor (or spec?) to a newer version, resulting in a different JPEG encoding, or at least difference in the comments.
So to answer your question, there does not seem to be an issue with your base64 converter, but just that the two images actually are different

How to convert byte array to buffered image

I have a server-side java code that gets a byte array from the client. In order to do some image processing, I need to convert the byte array into a BufferedImage. I have a code that's supposed to do that here:
public void processImage(byte[] data) {
ByteArrayInputStream stream = new ByteArrayInputStream(data);
BufferedImage bufferedImage;
bufferedImage = ImageIO.read(stream);
// bufferedImage is null
//...
}
But this doesn't work; bufferedImage is null. According to the ImageIO documentation:
If no registered ImageReader claims to be able to read the resulting stream, null is returned.
How do I tell the ImageReader what image type it is. For instance, if I know the image to be JPEG (which it is, in my case), what am I supposed to do?
EDIT: Thanks for the suggestion that the file is most likely not in JPEG format. This is the client-side code I have that sends the data as String over to the server:
import org.json.JSONObject;
// Client-side code that sends image to server as String
public void sendImage() {
FileInputStream inputStream = new FileInputStream(new File("myImage.jpg"));
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] b = new byte[1024];
while ((bytesRead = inputStream.read(b)) != -1) {
byteStream.write(b,0,bytesRead);
}
byte[] byteArray = byteStream.toByteArray();
JSONObject jsonObject = new JSONObject();
jsonObject.put("data",new String(byteArray));
// ... more code here that sends jsonObject in HTTP post body
}
And this is the server-side code that calls the processImage() function:
// Server-side code that calls processImage() function
public void handleRequest(String jsonData) {
JSONObject jsonObject = new JSONObject(jsonData);
processImage(jsonObject.getString("data").getBytes());
}
The most likely explanation is that the byte array doesn't contain a JPEG image. (For instance, if you've just attempted to download it, you may have an HTML document giving an error diagnostic.) If that's the case, you'll need to find what is causing this and fix it.
However, if you "know" that the byte array contains an image with a given format, you could do something like this:
Use ImageIO.getImageReadersByFormatName or ImageIO.getImageReadersByMIMEType to get an Iterator<ImageReader>.
Pull the first ImageReader from the Iterator.
Create an MemoryCacheImageInputStream wrapping a ByteArrayInputStream for the types.
Use ImageReader.setInput to connect the reader to the ImageInputStream.
Use ImageReader.read to get the BufferedImage.

PNG read and write with Java increases file size

Got a problem when reading and writing a png file. I read it with ImageIO to a byte array and then write this byte array again using ImageIO. But the file size increases significantly. How can this happen?
public BufferedImage toBufferedImage(InputStream inputstream) {
try {
return ImageIO.read(inputstream);
} catch (Exception e) {
throw new IllegalStateException("Can't convert to buffered image", e);
}
}
public byte[] toByteArray(BufferedImage bufferedImage, String filetype) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
ImageIO.write(bufferedImage, filetype, output);
return output.toByteArray();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
Follow up: is there any library to support compressed PNGs that is written in Java and does not need any native code?
This is most likely due to the compression algorithm being different between Java and whatever created the original PNG.
The documentation says it's decoding the input file, so it's not being held in memory as a PNG:
Returns a BufferedImage as the result of decoding a supplied File with an ImageReader chosen automatically from among those currently registered. The File is wrapped in an ImageInputStream. If no registered ImageReader claims to be able to read the resulting stream, null is returned.
When it writes it back, it has to re-encode the PNG file, and Java's PNG encoding doesn't seem to be as efficient as whatever created your original file.
The PNG writer supplied with the JDK does not support compression. You can quickly check this with:
w = ImageIO.getImageWritersByFormatName("png").next();
p = w.getDefaultWriteParam();
print("Can compress? "+p.canWriteCompressed());
// Can compress? false
It's possible that imageio-ext or jai-imageio include a png writer with compression support: http://java.net/projects/imageio/

Categories