I have a webserver that creates a QRcode. During the process, I get a BarcodeQRCode object from which I can get the image (.getImage()).
I am not sure how I can send back to the client this image. I don't want to save it in a file but just send back data in response to JSON request.
For information, I have a similar case from which I get a PDF file that works great:
private ByteArrayRepresentation getPdf(String templatePath, JSONObject json) throws IOException, DocumentException, WriterException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(..., baos);
// setup PDF content...
return new ByteArrayRepresentation(baos.toByteArray(), MediaType.APPLICATION_PDF);
}
Is there a way to do something similar more or less like:
private ByteArrayRepresentation getImage(JSONObject json) throws IOException, DocumentException, WriterException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Image qrCode = getQRCode(json); /// return the BarcodeQRCode.getImage()
ImageIO.write(qrCode, "png", baos);
return new ByteArrayRepresentation(baos.toByteArray(), MediaType.IMAGE_PNG);
}
But this is not working. I get: argument mismatch; Image cannot be converted to RenderedImage.
EDIT
No compilation error after modification as proposed below. However, the returned image seems to be empty (or at least not normal). I put the error-free code if anyone has an idea what is wrong:
#Post("json")
public ByteArrayRepresentation accept(JsonRepresentation entity) throws IOException, DocumentException, WriterException {
JSONObject json = entity.getJsonObject();
return createQR(json);
}
private ByteArrayRepresentation createQR(JSONObject json) throws IOException, DocumentException, WriterException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Image codeQR = getQRCode(json);
BufferedImage buffImg = new BufferedImage(codeQR.getWidth(null), codeQR.getHeight(null), BufferedImage.TYPE_4BYTE_ABGR);
buffImg.getGraphics().drawImage(codeQR, 0, 0, null);
return new ByteArrayRepresentation(baos.toByteArray(), MediaType.IMAGE_PNG);
}
private Image getQRCode(JSONObject json) throws IOException, DocumentException, WriterException {
JSONObject url = json.getJSONObject("jsonUrl");
String urls = (String) url.get("url");
BarcodeQRCode barcode = new BarcodeQRCode(urls, 200, 200, null);
Image codeImage = barcode.createAwtImage(Color.BLACK, Color.WHITE);
return codeImage;
}
First, convert the Image to RenderedImage:
BufferedImage buffImg = new BufferedImage(qrCode.getWidth(null), qrCode.getHeight(null), BufferedImage.TYPE_4BYTE_ABGR);
buffImg.getGraphics().drawImage(qrCode, 0, 0, null);
If you use com.itextpdf.text.Image you can use this code
BarcodeQRCode qrcode = new BarcodeQRCode("testo testo testo", 1, 1, null);
Image image = qrcode.createAwtImage(Color.BLACK, Color.WHITE);
BufferedImage buffImg = new BufferedImage(image.getWidth(null), image.getWidth(null), BufferedImage.TYPE_4BYTE_ABGR);
buffImg.getGraphics().drawImage(image, 0, 0, null);
buffImg.getGraphics().dispose();
File file = new File("tmp.png");
ImageIO.write(buffImg, "png", file);
I hope you have been helpful
Enrico
Related
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)
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;
}
I have a server and I want to compress images in it. When I write the image, it goes from 23MB to 650kb and it's okay. But when I'm reading it to send it to my client app, the size is back to 23MB.
public static BufferedImage getProfilePicture(String username) throws IOException {
File input = new File(profilePicturePath + File.separatorChar + username + ".png");
BufferedImage image = ImageIO.read(input);
rewriteImage(image);
return image;
}
public static String getProfilePictureBase64(String username) throws IOException {
BufferedImage img = getProfilePicture(username);
final ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(img, "png", os);
return Base64.getEncoder().encodeToString(os.toByteArray());
}
So my question is : How can I keep the compressed size to send image to my client ?
How to display Base64 string in image on Java com.sun.net.httpserver.HttpServer ?
I run this code:
static class base implements HttpHandler{
#Override
public void handle(HttpExchange he) throws IOException {
byte[] name = Base64.getEncoder().encode(base64String.getBytes());
byte[] decodedString = Base64.getDecoder().decode(new String(name).getBytes("UTF-8"));
String base64String = "BASE64 IMAGE";
Headers headers = he.getResponseHeaders();
headers.add("Content-Type", "image/png");
File file = new File ("1.png");
//System.out.println(file);
FileInputStream fileInputStream = new FileInputStream(file);
InputStream bufferedInputStream = new ByteArrayInputStream(decodedString);
bufferedInputStream.read(decodedString, 0, decodedString.length);
he.sendResponseHeaders(200, decodedString.length);
final OutputStream os = he.getResponseBody();
os.write(decodedString);
os.close();
}
}
But displays a white cube
I am creating a PDF and writing the stream in response. Before writing in the stream, I want to add a background image as watermark in all the pages so that PDF document flushed through response is the final one with watermark.
Hi this is my code sample. Any help would be much appriciated
private static String generatePDF(HttpServletRequest request, HttpServletResponse response, String fileName) throws Exception
{
Document document = null;
PdfWriter writer = null;
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(fileName);
Document document = new Document(PageSize.A4);
writer = PdfWriter.getInstance(document, fos);
document.open();
/**
* Adding tables and cells and other stuff required
**/
return pdfFileName;
} catch (Exception e) {
FileUtil.deleteFile(fileName);
throw e
} finally {
if (document != null) {
document.close();
}
fos.flush();
}
}
I now would like to add a background image using the below code and write the output PDF to the same stream
PdfReader sourcePDFReader = null;
try
{
sourcePDFReader = new PdfReader(sourcePdfFileName);
int noOfPages = sourcePDFReader.getNumberOfPages();
PdfStamper stamp = new PdfStamper(sourcePDFReader, new FileOutputStream(destPdfFileName));
int i = 0;
Image templateImage = Image.getInstance(templateImageFile);
templateImage.setAbsolutePosition(0, 0);
PdfContentByte tempalteBytes;
while (i < noOfPages) {
i++;
tempalteBytes = stamp.getUnderContent(i);
tempalteBytes.addImage(templateImage);
}
stamp.close();
return destPdfFileName;
} catch (Exception ex) {
LOGGER.log(Level.INFO, "Error when applying tempalte image as watermark");
} finally {
if (sourcePDFReader != null) {
sourcePDFReader.close();
}
}
I solved this using Bruno's first (recommended) approach.
1) Create a page event helper with an onEndPage event:
class PDFBackground extends PdfPageEventHelper {
#Override
void onEndPage(PdfWriter writer, Document document) {
Image background = Image.getInstance("myimage.png");
// This scales the image to the page,
// use the image's width & height if you don't want to scale.
float width = document.getPageSize().getWidth();
float height = document.getPageSize().getHeight();
writer.getDirectContentUnder()
.addImage(background, width, 0, 0, height, 0, 0);
}
}
2) When creating your writer, register your page event helper:
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
writer.setPageEvent(new PDFBackground());
I have solved this with Bruno's second option. Here is the code.
public static String addBackgroundImageToPDF(ByteArrayOutputStream bos, String destPdfFileName, String templateImageFile)
{
PdfReader sourcePDFReader = null;
try
{
sourcePDFReader = new PdfReader(bos.toByteArray());
int noOfPages = sourcePDFReader.getNumberOfPages();
PdfStamper stamp = new PdfStamper(sourcePDFReader, new FileOutputStream(destPdfFileName));
int i = 0;
Image templateImage = Image.getInstance(templateImageFile);
templateImage.setAbsolutePosition(0, 0);
PdfContentByte tempalteBytes;
while (i < noOfPages)
{
i++;
tempalteBytes = stamp.getUnderContent(i);
tempalteBytes.addImage(templateImage);
}
stamp.close();
return destPdfFileName;
}
catch (Exception ex)
{
LOGGER.log(Level.INFO, "Error when applying template image as watermark");
}
finally
{
if (sourcePDFReader != null)
{
sourcePDFReader.close();
}
}
}
You can choose between two options:
Use the background image in a page event (to the 'under' content in the onEndPage() method)/
Create the first PDF in memory, then add the background image in a second pass using the code you posted.
I prefer option 1.