I have a jpg image and I want to convert it to a tiff file, but when I create the output file from byteArrayOutputStream, the output file has 0 byte length.
public static void main(String[] args) throws Exception {
String root = "E:\\Temp\\imaging\\test\\";
File image = new File(root + "0riginalTif-convertedToJpg.JPG");
byte[] bytes = compressJpgToTiff(image);
File destination = new File(root + "OriginalJpg-compressedToTiff.tiff");
FileOutputStream fileOutputStream = new FileOutputStream(destination);
fileOutputStream.write(bytes);
}
public static byte[] compressJpgToTiff(File imageFile) throws Exception {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(255);
ImageOutputStream imageOutputStream = null;
try {
File input = new File(imageFile.getAbsolutePath());
Iterator<ImageWriter> imageWriterIterator = ImageIO.getImageWritersByFormatName("TIF");
ImageWriter writer = imageWriterIterator.next();
imageOutputStream = ImageIO.createImageOutputStream(byteArrayOutputStream);
writer.setOutput(imageOutputStream);
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionType("JPEG");
param.setCompressionQuality(0.1f);
BufferedImage bufferedImage = ImageIO.read(input);
writer.write(null, new IIOImage(bufferedImage, null, null), param);
writer.dispose();
return byteArrayOutputStream.toByteArray();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (imageOutputStream != null)
imageOutputStream.close();
byteArrayOutputStream.close();
}
}
I want to reduce the size of output tiff as much as possible. Is there a better approach? Is it even possible to reduce the size of a tiff image?
return byteArrayOutputStream.toByteArray(); but you didn't wirite data to byteArrayOutputStream. Look, you just added data to writer.
About compression of tiff file, you have already done it with - param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
Your byteArrayOutputStream object is getting closed in finally block before you converting byteArrayOutputStream to byteArray using byteArrayOutputStream.toByteArray() thats why you getting content length to be 0. So modify your code once as below :
public static byte[] compressJpgToTiff(File imageFile) throws Exception {
//Add rest of your method code here
writer.dispose();
byte[] bytesToReturn = byteArrayOutputStream.toByteArray();
return bytesToReturn;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (imageOutputStream != null)
imageOutputStream.close();
byteArrayOutputStream.close();
}
}
Related
I want to reduce the file size while saving the image.
Please, take this code for reference.
And how to reduce the file size.
public void saveImage(MultipartFile image_one, MultipartFile image_two, MultipartFile image_three) throws Exception{
System.out.println("Inside Save image Repo");
String folder = "C:/Users/HP/Photos";
byte[] bytes_one;
try {
bytes_one = image_one.getBytes();
Path path1 = Paths.get(folder + image_one.getOriginalFilename());
System.out.println("Path of 1st imagae : "+path1);
Files.write(path1, bytes_one);
System.out.println("Image-1 size : "+bytes_one.length);
} catch (Exception e) {
System.out.println("Inside Catch Block -> Image not found ");
e.printStackTrace();
}
}
You could use the Java javax.imageio library and use a function to compress your image bytes.
This should do the work:
public byte[] compressImage(MultipartFile image) throws IOException
{
InputStream inputStream = image.getInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
float imageQuality = 0.3f;
// Create the buffered image
BufferedImage bufferedImage = ImageIO.read(inputStream);
// Get image writers
Iterator<ImageWriter> imageWriters = ImageIO.getImageWritersByFormatName("jpg"); // Input your Format Name here
if (!imageWriters.hasNext())
throw new IllegalStateException("Writers Not Found!!");
ImageWriter imageWriter = imageWriters.next();
ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(outputStream);
imageWriter.setOutput(imageOutputStream);
ImageWriteParam imageWriteParam = imageWriter.getDefaultWriteParam();
// Set the compress quality metrics
imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
imageWriteParam.setCompressionQuality(imageQuality);
// Compress and insert the image into the byte array.
imageWriter.write(null, new IIOImage(bufferedImage, null, null), imageWriteParam);
byte[] imageBytes = outputStream.toByteArray();
// close all streams
inputStream.close();
outputStream.close();
imageOutputStream.close();
imageWriter.dispose();
return imageBytes;
}
It returns the compressed image bytes so that the value returned can be transformed into a number of things. In your case, in a file...
byte[] compressedImageBytes = compressImage(imageOne);
Files.write(path1, bytesOne);
I am trying to read .rpt file and generate pdf using ReportClientDocument,ByteArrayInputStream and ByteArrayOutputStream. After generating the pdf file I am unable to open it. It is showing "It may be damaged or use a file format that Preview doesn’t recognise." My Source code is provided below
public static void generatePDFReport()
{
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
LocalDateTime now = LocalDateTime.now();
System.out.println(dtf.format(now));
try {
ReportClientDocument rcd = new ReportClientDocument();
String rptPath="/Users/florapc/Desktop/Report/AcStatement.rpt";
String outputPath=String.format("/Users/florapc/Desktop/Report/%s.pdf",dtf.format(now));
File inputFile = new File(rptPath);
File outputFile = new File(outputPath);
rcd.open(rptPath, 0);
System.out.println(rptPath);
List<IParameterField> fld = rcd.getDataDefController().getDataDefinition().getParameterFields();
List<String> reportContent = new ArrayList<String>();
System.out.println(fld.size());
for (int i = 0; i < fld.size(); i++) {
System.out.println(fld.get(i).getDescription());
reportContent.add(fld.get(i).getDescription().replaceAll("[^a-zA-Z0-9]", " "));
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(reportContent);
byte[] bytes = bos.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
byte[] byteArray = new byte[byteArrayInputStream.available()];
int x = byteArrayInputStream.read(byteArray, 0, byteArrayInputStream.available());
System.out.println(x);
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();;
byteArrayOutputStream.write(byteArray, 0, x);
byteArrayOutputStream.writeTo(fileOutputStream);
System.out.println(fileOutputStream);
System.out.println("File exported succesfully");
byteArrayInputStream.close();
byteArrayOutputStream.close();
fileOutputStream.close();
rcd.close();
} catch (Exception e) {
e.printStackTrace();
}
}
I can read .rpt file and print it in console. Please help me finding the best way to generate pdf properly.
I'm not familiar with ReportClientDocument. As far as I understand it's not a PDF document itself but a report that can be saved as PDF. ObjectOutputStream won't achieve this as it's Java specific format and has nothing to do with PDF.
It looks as if a PrintOutputController is needed for PDF export. Thus your code would look more like so:
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
InputStream is = rcd.getPrintOutputController().export(ReportExportFormat.PDF);
copy(is, fileOutputStream);
fileOutputStream.close();
...
void copy(InputStream source, OutputStream target) throws IOException {
byte[] buf = new byte[8192];
int length;
while ((length = source.read(buf)) > 0) {
target.write(buf, 0, length);
}
}
Note that no byte array streams are needed. They are a detour, slowing down your program and drive up memory consumption.
I am using a piece of code posted on stackover flow to write custom metadata to PNG image and read it. The write function seems to work fine but when i try to read data that i had written it throws NullPointerException. Can someone tell me what is wrong?
Here is code for writing metadata
try{
image=ImageIO.read(new FileInputStream("input.png"));
writeCustomData(image, "software", "FRDDC");
ImageIO.write(image, "png", new File("output.png"));
}
catch(Exception e){
e.printStackTrace();
}
Method to write metadata
public static byte[] writeCustomData(BufferedImage buffImg, String key, String value) throws Exception {
ImageWriter writer = ImageIO.getImageWritersByFormatName("png").next();
ImageWriteParam writeParam = writer.getDefaultWriteParam();
ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
//adding metadata
javax.imageio.metadata.IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
IIOMetadataNode textEntry = new IIOMetadataNode("tEXtEntry");
textEntry.setAttribute("keyword", key);
textEntry.setAttribute("value", value);
IIOMetadataNode text = new IIOMetadataNode("tEXt");
text.appendChild(textEntry);
IIOMetadataNode root = new IIOMetadataNode("javax_imageio_png_1.0");
root.appendChild(text);
metadata.mergeTree("javax_imageio_png_1.0", root);
//writing the data
ByteArrayOutputStream baos = new ByteArrayOutputStream();
javax.imageio.stream.ImageOutputStream stream = ImageIO.createImageOutputStream(baos);
writer.setOutput(stream);
writer.write(metadata, new IIOImage(buffImg, null, metadata), writeParam);
try {
ImageIO.write(buffImg, "png", new File("new.png"));
} catch (Exception e) {
e.printStackTrace();
}
stream.close();
return baos.toByteArray();
}
Reading metadata
try{
image=ImageIO.read(new FileInputStream("output.png"));
ByteArrayOutputStream baos=new ByteArrayOutputStream();
ImageIO.write(image, "png", baos );
byte[] b=baos.toByteArray();
String out=readCustomData(b, "software");
}
catch(Exception e){
e.printStackTrace();
}
Method to read metadata
public static String readCustomData(byte[] imageData, String key) throws IOException{
ImageReader imageReader = ImageIO.getImageReadersByFormatName("png").next();
imageReader.setInput(ImageIO.createImageInputStream(new ByteArrayInputStream(imageData)), true);
// read metadata of first image
javax.imageio.metadata.IIOMetadata metadata = imageReader.getImageMetadata(0);
//this cast helps getting the contents
//Node n=metadata.getAsTree("javax_imageio_png_1.0");
//NodeList childNodes=n.getChildNodes();
PNGMetadata pngmeta = (PNGMetadata) metadata;
if(pngmeta.getStandardTextNode()==null){
System.out.println("not found");
}
NodeList childNodes = pngmeta.getStandardTextNode().getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
String keyword = node.getAttributes().getNamedItem("keyword").getNodeValue();
String value = node.getAttributes().getNamedItem("value").getNodeValue();
if(key.equals(keyword)){
return value;
}
}
return null;
}
Error Message
not found
java.lang.NullPointerException
at PNGMeta.readCustomData(PNGMeta.java:104)
at PNGMeta.main(PNGMeta.java:40)
BUILD SUCCESSFUL (total time: 2 seconds)
Here's the most efficient way of modifying and then reading the metadata that I know of. In contrast to the code posted by the OP, this version does not fully replace the metadata in the image, but merges the new content with any existing content.
As it uses the "standard" metadata format, it should also work for any format supported by ImageIO, that allows arbitrary text comments (I only tested for PNG, though). The actual data written, should match that of the native PNG metadata format in this case.
It reads all image pixel data and metadata using a single method, to avoid excess stream open/close and seeking and memory usage. It writes all image pixel data and metadata at once for the same reason. For lossless, single image formats like PNG, this roundtrip should not lose any quality or metadata.
When reading metadata back, only the metadata is read, pixel data is ignored.
public class IIOMetadataUpdater {
public static void main(final String[] args) throws IOException {
File in = new File(args[0]);
File out = new File(in.getParent(), createOutputName(in));
System.out.println("Output path: " + out.getAbsolutePath());
try (ImageInputStream input = ImageIO.createImageInputStream(in);
ImageOutputStream output = ImageIO.createImageOutputStream(out)) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
ImageReader reader = readers.next(); // TODO: Validate that there are readers
reader.setInput(input);
IIOImage image = reader.readAll(0, null);
addTextEntry(image.getMetadata(), "foo", "bar");
ImageWriter writer = ImageIO.getImageWriter(reader); // TODO: Validate that there are writers
writer.setOutput(output);
writer.write(image);
}
try (ImageInputStream input = ImageIO.createImageInputStream(out)) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
ImageReader reader = readers.next(); // TODO: Validate that there are readers
reader.setInput(input);
String value = getTextEntry(reader.getImageMetadata(0), "foo");
System.out.println("value: " + value);
}
}
private static String createOutputName(final File file) {
String name = file.getName();
int dotIndex = name.lastIndexOf('.');
String baseName = name.substring(0, dotIndex);
String extension = name.substring(dotIndex);
return baseName + "_copy" + extension;
}
private static void addTextEntry(final IIOMetadata metadata, final String key, final String value) throws IIOInvalidTreeException {
IIOMetadataNode textEntry = new IIOMetadataNode("TextEntry");
textEntry.setAttribute("keyword", key);
textEntry.setAttribute("value", value);
IIOMetadataNode text = new IIOMetadataNode("Text");
text.appendChild(textEntry);
IIOMetadataNode root = new IIOMetadataNode(IIOMetadataFormatImpl.standardMetadataFormatName);
root.appendChild(text);
metadata.mergeTree(IIOMetadataFormatImpl.standardMetadataFormatName, root);
}
private static String getTextEntry(final IIOMetadata metadata, final String key) {
IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
NodeList entries = root.getElementsByTagName("TextEntry");
for (int i = 0; i < entries.getLength(); i++) {
IIOMetadataNode node = (IIOMetadataNode) entries.item(i);
if (node.getAttribute("keyword").equals(key)) {
return node.getAttribute("value");
}
}
return null;
}
}
Expected output of the above code is:
Output path: /path/to/yourfile_copy.png
value: bar
Your output contains "not found", which is created by
if(pngmeta.getStandardTextNode()==null){
System.out.println("not found");
}
Therefore
NodeList childNodes = pngmeta.getStandardTextNode().getChildNodes();
must fail with a NullPointerException. pngmeta.getStandardTextNode() results in null, so you actully call
null.getChildNodes();
I tried to convert Mat to byte array in java . On conversion of Mat to Byte[] and Byte[] to Mat, I am not able to retain the original value of Mat. The Mat .get accepts byte[] as parameter which is not working. Can anyone help me with the same?
Use Case: To grab each frame of video and send it via kafka to consumer containing byte[] message then consumer would recieve the byte array and convert to Mat and save it as image.
I came accross similar posts in java but no solution was found. here
See my code:
` System.loadLibrary("opencv_java249");
MatOfByte webcam_image = new MatOfByte();
VideoCapture capture = new VideoCapture(
"/home/jishnu/CodeT/TrainingDataSet/Video.mp4");
System.out.println("Frame Grabber started");
byte[] frameArray;
int i=0;
if (capture.isOpened()) {
while (true) {
capture.read(webcam_image);
frameArray = new byte[(int) (webcam_image.total() * webcam_image
.channels())];
if (!webcam_image.empty()) {
// System.out.print(".");
webcam_image.get(0,0,frameArray);
producer.send(new KeyedMessage<String, byte[]>("imageTopic",frameArray));
//Below statements are only for debugging
System.out.println(frameArray.length);
MatOfByte inputframe=new MatOfByte(frameArray);
boolean b= Highgui.imwrite("/home/jishnu/CodeT/Today7.jpeg", inputframe);
if(b){System.out.println("save image success");}
else System.out.println("save image failed");
inputframe.fromArray(frameArray);
b= Highgui.imwrite("/home/jishnu/CodeT/Today6.bmp",inputframe);
if(b){System.out.println("save image success");System.exit(0);}
else System.out.println("save image failed");
} else {
System.out.println(" --(!) No captured frame -- Break!");
`
It's working me.I use apachi-common for write and read from file.
public static void save(Mat mat, String name)
{
File file = new File(path, name);
int length = (int) (mat.total() * mat.elemSize());
byte buffer[] = new byte[length];
mat.get(0, 0, buffer);
try
{
FileUtils.writeByteArrayToFile(file, buffer);
} catch (IOException e)
{
e.printStackTrace();
}
}
public static Mat load(String name)
{
File file = new File(path, name);
byte[] buffer = new byte[0];
try
{
buffer = FileUtils.readFileToByteArray(file);
} catch (IOException e)
{
e.printStackTrace();
}
Mat mat = new Mat(row, col, type);
mat.put(0, 0, buffer);
return mat;
}
OpenCV version : 4.5.1
Refarance: https://www.tutorialspoint.com/how-to-convert-opencv-mat-object-to-bufferedimage-object-using-java
public static void main(String[] args) throws IOException {
String filePath = ".jpg";
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
Mat mat=Imgcodecs.imread(filePath);
MatOfByte matOfByte = new MatOfByte();
Imgcodecs.imencode(".jpg", mat, matOfByte);
byte[] byteArray = matOfByte.toArray();
Path path = Paths.get("D:\\yyy2.jpg");
Files.write(path, byteArray);
//InputStream inputStream = new ByteArrayInputStream(byteArray);
}
If anyone gets the same error.
I used Mat.put(frameArray) to create Mat from byte instead of MatOfByte inputframe=new MatOfByte(frameArray);
Now everything is working fine, I dont know why is MatofByte constructor not working.
Fixed in later versions of JavaCV.
I have created a graphical image with the following sample code.
BufferedImage bi = new BufferedImage(50,50,BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g2d = bi.createGraphics();
// Draw graphics.
g2d.dispose();
// BufferedImage now has my image I want.
At this point I have BufferedImage which I want to convert into an IMG Data URI. Is this possible? For example..
<IMG SRC="data:image/png;base64,[BufferedImage data here]"/>
Not tested, but something like this ought to do it:
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(bi, "PNG", out);
byte[] bytes = out.toByteArray();
String base64bytes = Base64.encode(bytes);
String src = "data:image/png;base64," + base64bytes;
There are lots of different base64 codec implementations for Java. I've had good results with MigBase64.
You could use this solution which doesn't use any external libraries. Short and clean! It uses a Java 6 library (DatatypeConverter). Worked for me!
ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageIO.write(image, "png", output);
DatatypeConverter.printBase64Binary(output.toByteArray());
I use Webdriver, get captcha, like this below:
// formatName -> png
// pathname -> C:/Users/n/Desktop/tmp/test.png
public static String getScreenshot(WebDriver driver, String formatName, String pathname) {
try {
WebElement element = driver.findElement(By.xpath("//*[#id=\"imageCodeDisplayId\"]"));
File screenshot = element.getScreenshotAs(OutputType.FILE);
// base64 data
String base64Str = ImageUtil.getScreenshot(screenshot.toString());
return base64Str;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String getScreenshot(String imgFile) {
InputStream in;
byte[] data = null;
try {
in = new FileInputStream(imgFile);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
String base64Str = new String(Base64.getEncoder().encode(data));
if (StringUtils.isAnyBlank(base64Str)) {
return null;
}
if (!base64Str.startsWith("data:image/")) {
base64Str = "data:image/jpeg;base64," + base64Str;
}
return base64Str;
}