I'm accessing an external api and I'm expecting to get an image as response (byte[]). My method that connects to this endpoint looks like this:
private byte[] retrieveImage(String uri) {
byte[] imageBytes = null;
try {
URL url = new URL(uri);
BufferedImage bufferedImage = ImageIO.read(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
imageBytes = baos.toByteArray();
} catch (Exception ex) {
throw new ImageNotReadException(ex.getLocalizedMessage());
}
return imageBytes;
}
It turned out that if I pass the wrong parameters to the target endpoint I get this error message:
So basically I would like to throw the same error above but I also would like to throw an ImageNotReadException (java.lang.IllegalArgumentException: image == null! ) in case the program fails to read the image (byte[]). So basically, my method private byte[] retrieveImage(String uri) would have to throw my read image exception and the endpoint response exception.
Any tips?
Appreciate the help!
As i have commented see below options
private Response retrieveImage(String uri) {
byte[] imageBytes = null;
Response r=new Response();
try {
URL url = new URL(uri);
BufferedImage bufferedImage = ImageIO.read(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
imageBytes = baos.toByteArray();
r.setImage(imageBytes);
r.setStatus(1);
} catch (Exception ex) {
r.setStatus(0);
}
return r;
}
Response :
class Response{
String status;
byte[] image;
//getters setters
}
Or :
private Response retrieveImage(String uri)throws CustomException {
byte[] imageBytes = null;
try {
URL url = new URL(uri);
BufferedImage bufferedImage = ImageIO.read(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
imageBytes = baos.toByteArray();
} catch (Exception ex) {
throw new CustomException(ex.getLocalizedMessage());
}
return imageBytes;
}
Related
Someone is providing a S3 Presigned URL so that I can upload my images to that link. All my images are on the website. Is there a way in JAVA to copy the image URL to the new URL provided ?
I am trying to do this. Seems like an overkill
try {
// Get Image from URL
URL urlGet = new URL("http://something.com/something.png");
BufferedImage image = ImageIO.read(urlGet);
//for png
ImageIO.write(image, "png",new File("/something.png"));
// for jpg
//ImageIO.write(image, "jpg",new File("/something.jpg"));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(image, "png", outputStream);
outputStream.flush();
byte[] imageInBytes = outputStream.toByteArray();
outputStream.close();
URL url = new URL(putUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod(HttpMethod.PUT);
connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, PNG_MIME_TYPE);
OutputStream stream = connection.getOutputStream();
try {
stream.write(imageInBytes);
} finally {
stream.close();
connection.disconnect();
}
switch (connection.getResponseCode()) {
case HttpURLConnection.HTTP_OK:
return "";
default:
break;
}
} catch (Exception e) {
log.error("Exception occured", e);
throw e;
}
There would be no point converting to BufferedImage and back for the copy when you can preserve the byte stream of the original files. The first part can be replaced with simple call to extract the bytes off your website:
byte[] imageInBytes = read(urlGet);
Where read() is:
private static byte[] read(URL url) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(16*1024);
try (var in = url.openStream()) {
in.transferTo(out);
}
return out.toByteArray();
}
If you use JDK11 onwards you could try the HttpClient class for the GET and POSTs, for example this does same as above if passing it urlGet.toURI():
private static byte[] read(URI uri) throws IOException, InterruptedException
{
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(uri).build();
var resp = client.send(request, BodyHandlers.ofByteArray());
return resp.body();
}
Generally, I am using below code to take a screenshot and attach in allure report :
#Attachment(value = "Page Screenshot", type = "image/png")
public static byte[] saveScreenshotPNG(WebDriver driver) {
return ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
}
But now my need is I have already some screenshot on my desktop and want to attach it with an allure report. is that possible?
You can take the existing image and convert it to byte[]. getScreenshotAs() decodes the screenshot string so you might need to do it as well
Java
#Attachment(value = "Page Screenshot", type = "image/png")
public static byte[] saveScreenshotPNG(String path) {
File file = new File(path);
BufferedImage bufferedImage = ImageIO.read(file);
byte[] image = null;
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
ImageIO.write(bufferedImage, "png", bos);
image = bos.toByteArray();
} catch (Exception e) { }
// if decoding is not necessary just return image
return image != null ? Base64.getMimeDecoder().decode(image) : null;
}
Python
with open(path, 'rb') as image:
file = image.read()
byte_array = bytearray(file)
allure.attach(byte_array, name="Screenshot", attachment_type=AttachmentType.PNG)
So, I am downloading the profile picture from the Google SIgn-in api and I save it to a hidden file. The problem is that when I try to retrieve it, it throws me: D/skia: --- Failed to create image decoder with message 'unimplemented'. However when I retrieve an image from FireBaseStorage and save that one to the hidden file I can retrieve it whithout any problems.
I tried BitmapFactory.decodeByteArray(), but then I had a message telling me skia wasn't able to decode the file and it returned null.
The method I use to retrieve the profile picture and call the method that will save the file
private void getUsersPic() {
Bitmap profilePic;
try {
InputStream in = new URL(AppData.getUser().getPicture()).openConnection().getInputStream();
profilePic = BitmapFactory.decodeStream(in);
int size = profilePic.getRowBytes()*profilePic.getHeight();
ByteBuffer b = ByteBuffer.allocate(size);
byte[] bytes = new byte[size];
profilePic.copyPixelsToBuffer(b);
b.position(0);
b.get(bytes, 0, bytes.length);
SaveBitmapToFile.saveBitmap(bytes , AppData.getUser().getName()+AppData.getUser().getLastName());
} catch(Exception e) {
System.out.println("Get profile pic: "+e.toString());
}
}
Save the file
public static void saveBitmap(byte[] bitmap, String key) {
String path = AppData.getAppContext().getFilesDir()+"/.image"+"/";
File fileDir = new File(path);
if(!fileDir.isDirectory())
fileDir.mkdirs();
try {
File bitmapDir = new File(fileDir+"/"+key);
bitmapDir.createNewFile();
FileOutputStream stream = new FileOutputStream(bitmapDir);
stream.write(bitmap);
stream.close();
} catch (IOException e) {
System.out.println("Problem creating file "+e.toString()+ " Directory: "+fileDir);
}
}
Retrieve and return a bitmap
public static Bitmap getBitmap(String key) {
File file = new File(AppData.getAppContext().getFilesDir()+"/.image/"+key);
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
return BitmapFactory.decodeStream(buf);//BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
} catch(Exception e) {
System.out.println("Exception getting bitmap: "+e.toString());
return null;
}
}
The last method should return a Bitmap and it is doing it. It is just not working when the image comes from the Google Sign-in api.
As pskink said in the comment of the post, I had to use compress() instead of copyPixelToBuffer(). Here is my updated method:
private void getUsersPic() {
Bitmap profilePic;
try {
InputStream in = new URL(AppData.getUser().getPicture()).openConnection().getInputStream();
profilePic = BitmapFactory.decodeStream(in);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
profilePic.compress(Bitmap.CompressFormat.PNG, 100, stream);
SaveBitmapToFile.saveBitmap(stream.toByteArray() , AppData.getUser().getName()+AppData.getUser().getLastName());
} catch(Exception e) {
System.out.println("Get profile pic: "+e.toString());
}
}
I'm sending a photo via MQTT, and trying to save a copy of that.
This is what the receiver does:
connectMQTTAsReceiver("Controller", "tcp://m2m.eclipse.org:1883", "robot");
byte[] photoByte=receiveMQTT.getBytes();
File photo=new File("image2.jpg");
photo.createNewFile();
FileOutputStream outputStream=new FileOutputStream(photo);
outputStream.write(photoByte);
outputStream.close();
With this, the photo is saved but it's completely white.
Then I tried doing this:
connectMQTTAsReceiver("Controller", "tcp://m2m.eclipse.org:1883", "robot");
byte[] photoByte=Base64.getDecoder().decode(receiveMQTT().getBytes(StandardCharsets.UTF_8));
InputStream in = new ByteArrayInputStream(photoByte);
System.out.println("Received");
BufferedImage bufferedImage;
try {
bufferedImage = ImageIO.read(in);
File outputfile = new File("image3.jpg");
ImageIO.write(bufferedImage, "jpg", outputfile);
} catch (IOException e) {
e.printStackTrace();
}
and it gives me this error:
java.lang.IllegalArgumentException: Illegal base64 character -1e
I have trouble to sending data from Android Client to NodeJS Server.
I use Socket.IO-client java library in my client.
But, there is not much information for me.
How can i sending binary data from android client to nodejs server?
You can use Base64 to encode the image:
public void sendImage(String path)
{
JSONObject sendData = new JSONObject();
try{
sendData.put("image", encodeImage(path));
socket.emit("message",sendData);
}catch(JSONException e){
}
}
private String encodeImage(String path)
{
File imagefile = new File(path);
FileInputStream fis = null;
try{
fis = new FileInputStream(imagefile);
}catch(FileNotFoundException e){
e.printStackTrace();
}
Bitmap bm = BitmapFactory.decodeStream(fis);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG,100,baos);
byte[] b = baos.toByteArray();
String encImage = Base64.encodeToString(b, Base64.DEFAULT);
//Base64.de
return encImage;
}
So basically you are sending a string to node.js
If you want to receive the image just decode in Base64:
private Bitmap decodeImage(String data)
{
byte[] b = Base64.decode(data,Base64.DEFAULT);
Bitmap bmp = BitmapFactory.decodeByteArray(b,0,b.length);
return bmp;
}