I am looking for the fastest way to download an image from the GPU to a file, for later loading in the same application (so not necessarily PNG e.g.).
I noticed however that when I use a DeflaterStream directly, it is considerably slower than ImageIO with DeflaterStream ( so using ImageIO.write(deflaterstream) ).
Am I doing something wrong? Or is ImageIO just heavily optimized/better than fastest GZIP compression?
glBindTexture(GL_TEXTURE_2D, textureId);
int bpp = 4; // Assuming a 32-bit display with a byte each for red, green, blue, and alpha.
ByteBuffer buffer = BufferUtils.createByteBuffer(SAVE_WIDTH * SAVE_HEIGHT * bpp);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA8, GL_UNSIGNED_BYTE, buffer );
// File file = new File("saves/s-" + layer + ".png"); // The file to save to.
String format = "png"; // Example: "PNG" or "JPG"
// BufferedImage image = new BufferedImage(SAVE_WIDTH, SAVE_HEIGHT, BufferedImage.TYPE_INT_ARGB);
try {
FileOutputStream bOut = new FileOutputStream("saves/p-"+ layer + ".gz");
DeflaterOutputStream gzipOut = new DeflaterOutputStream (bOut, new Deflater(Deflater.BEST_SPEED));
//buffer.flip();
System.out.println("Bytes remaining " + buffer.remaining());
while (buffer.hasRemaining()) gzipOut.write(buffer.get());
gzipOut.close();
bOut.close();
} catch (IOException ex) {
Logger.getLogger(SaveStateManager.class.getName()).log(Level.SEVERE, null, ex);
}
Conmpression is always expensive but you might be able to improve with
OutputStream bOut = new BufferedOutputStream(new FileOutputStream("saves/p-" + layer + ".gz"));
DeflaterOutputStream defOut = new DeflaterOutputStream(bOut, new Deflater(Deflater.BEST_SPEED));
//buffer.flip();
byte[] bytes = new byte[1024];
while (buffer.hasRemaining()) {
int len = Math.min(buffer.remaining(), bytes.length);
buffer.get(bytes, 0, len);
defOut.write(bytes, 0, len);
}
defOut.close();
Related
I am trying to read an image file in JPG format, write a text into the image,
and save it into a file in a single strip, compressed TIFF image format.
I used Apache Commons library to do the compression and the writing of the
output image file. I have no idea why the output image is drawn like it was split in two parts and the second part drawn first. If anyone can help me resolve this or point out what am I doing wrong here. Thanks..
This is the sample input and output image from the code below...
sample image
FileOutputStream fos = null;
BufferedOutputStream os = null;
ByteArrayOutputStream baos = null;
try {
String inputPath = "D:\\Test\\input.jpg";
File inputFile = new File(inputPath);
BufferedImage inputImage = ImageIO.read(inputFile);
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage outputImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
Font font = new Font("Arial", Font.BOLD, 40 );
java.awt.Graphics2D g2 = outputImage.createGraphics();
g2.setFont( font );
g2.setColor ( Color.BLACK );
g2.drawImage ( inputImage, 0, 0, width, height, Color.WHITE, null);
g2.drawString("TEST TEXT", 20, 40);
g2.dispose();
PixelDensity resolution = PixelDensity.createFromPixelsPerInch ( 200, 200);
double resolutionX = resolution.horizontalDensityInches();
double resolutionY = resolution.verticalDensityInches();
RationalNumber rationalNumX = RationalNumber.valueOf ( resolutionX );
RationalNumber rationalNumY = RationalNumber.valueOf ( resolutionY );
TiffOutputSet outputSet = new TiffOutputSet(ByteOrder.LITTLE_ENDIAN);
TiffOutputDirectory directory = outputSet.addRootDirectory();
baos = new ByteArrayOutputStream();
ImageIO.write(outputImage, "tif", baos);
byte[] bytes = baos.toByteArray();
byte[] compressedBytes = T4AndT6Compression.compressT6(bytes, width, height);
TiffImageData.Data data = new TiffImageData.Data(0, compressedBytes.length, compressedBytes);
TiffElement.DataElement[] dataElements = new TiffElement.DataElement[]{ data };
TiffImageData tiffImageData = new TiffImageData.Strips(dataElements, height);
directory.add ( TiffTagConstants.TIFF_TAG_NEW_SUBFILE_TYPE, 1 );
directory.add ( TiffTagConstants.TIFF_TAG_PHOTOMETRIC_INTERPRETATION, (short) 1 );
directory.add ( TiffTagConstants.TIFF_TAG_COMPRESSION, (short) 4 );
directory.add ( TiffTagConstants.TIFF_TAG_BITS_PER_SAMPLE, (short) 1 );
directory.add ( TiffTagConstants.TIFF_TAG_RESOLUTION_UNIT, (short) 2 );
directory.add ( TiffTagConstants.TIFF_TAG_ROWS_PER_STRIP, height );
directory.add ( TiffTagConstants.TIFF_TAG_IMAGE_WIDTH, width );
directory.add ( TiffTagConstants.TIFF_TAG_IMAGE_LENGTH, height );
directory.add ( TiffTagConstants.TIFF_TAG_XRESOLUTION, rationalNumX );
directory.add ( TiffTagConstants.TIFF_TAG_YRESOLUTION, rationalNumY );
directory.setTiffImageData( tiffImageData );
String outputPath = "D:\\Test\\output.tif";
File outputFile = new File(outputPath);
fos = new FileOutputStream(outputFile);
os = new BufferedOutputStream(fos);
new TiffImageWriterLossy().write( os, outputSet );
} catch (IOException ex) {
Logger.getLogger(JavaApplication7.class.getName()).log(Level.SEVERE, null, ex);
} catch (ImageWriteException ex) {
Logger.getLogger(JavaApplication7.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if ( baos != null ) {
try {
baos.flush();
baos.close();
} catch ( IOException ex ) { }
}
if ( os != null ) {
try {
os.flush();
os.close();
} catch ( IOException ex ) { }
}
if ( fos != null ) {
try {
fos.flush();
fos.close();
} catch ( IOException ex ) { }
}
}
The problem with your code is that you first store the BufferedImage as a TIFF file using ImageIO, then compress the entire file along with headers as the pixel data of the image you pass to commons imaging:
baos = new ByteArrayOutputStream();
ImageIO.write(outputImage, "tif", baos);
byte[] bytes = baos.toByteArray(); // <-- This is not pixel data, but a complete TIFF file
byte[] compressedBytes = T4AndT6Compression.compressT6(bytes, width, height);
The reason this actually resembles the image you expect, is that ImageIO writes the image data uncompressed. The garbage lines and offset before your image, is the TIFF header and tags displayed as pixels...
Instead, you probably meant to do something like:
// Cast is safe here, as you know outputImage is TYPE_BYTE_BINARY
byte[] bytes = ((DataBufferByte) outputImage.getRaster().getDataBuffer()).getData();
byte[] compressedBytes = T4AndT6Compression.compressT6(bytes, width, height);
This will compress just the pixels, and your image should be fine.
You could also do everything using just ImageIO, and avoid the extra dependency on commons imaging, by doing something like this:
try (ImageOutputStream stream = ImageIO.createImageOutputStream(outputFile)) {
ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromRenderedImage(outputImage);
ImageWriter writer = ImageIO.getImageWriters(imageTypeSpecifier, "TIFF").next();
writer.setOutput(stream);
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionType("CCITT T.6");
IIOMetadata metadata = writer.getDefaultImageMetadata(imageTypeSpecifier, param);
// TODO: Set 200 DPI, default is likely 72, and perhaps subfile type if needed,
// other tags will be set correctly for you
writer.write(null, new IIOImage(outputImage, null, metadata), param);
}
We are getting image as a byte array and encode it into base64 string then writing this string into word doc but unable to change it's size.
PFB code:
worddocfile // stringbuilder
String encodedImage = new String(Base64.encodeBase64(fileType.getFileContent()), "UTF-8");
encodedImage = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
worddocfile.append("<img style='display:block; width:600px;height:600px;' id='base64image'")
.append(" src='data:image/jpeg;base64,")
.append(encodedImage)
.append("' /> ");
Can anyone suggest the solution because it's working on html page but not on word document.
We have already used background image tag but it's not working.
<p style="background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='); border: 1px solid black;background-repeat: no-repeat;background-size: contain;width:600px;height:597px;\>
Convert byte array into an image and place this image inside the WEB-INF folder.
Now re scale the converted image with the updated size and store it inside WEB-INF folder.
Now convert the re scaled image into byte array and write the bytes on the word doc.
PFB the code:
ByteArrayInputStream bis1 = new ByteArrayInputStream(fileType.getFileContent() );
Iterator<?> readers = ImageIO.getImageReadersByFormatName("jpg");
//ImageIO is a class containing static methods for locating ImageReaders
//and ImageWriters, and performing simple encoding and decoding.
ImageReader reader = (ImageReader) readers.next();
Object source1 = bis1;
ImageInputStream iis = ImageIO.createImageInputStream(source1);
reader.setInput(iis, true);
ImageReadParam param = reader.getDefaultReadParam();
try{
Image image1 = reader.read(0, param);
//got an image file image1 -- image1.getWidth(null)
BufferedImage bufferedImage = new BufferedImage(650,950, BufferedImage.TYPE_INT_RGB);
//bufferedImage is the RenderedImage to be written
Graphics2D g2 = bufferedImage.createGraphics();
g2.setBackground(Color.WHITE);
g2.clearRect(0, 0, 650,950);
g2.drawImage(image1, 0,0,650,950, null);//
g2.dispose();
//mgpath can be WEB-INF folder
File imageFile = new File(imgpath+"UpdatedImg.jpg");
ImageIO.write(bufferedImage, "jpg", imageFile);
FileInputStream fisn = new FileInputStream(imageFile);
//create FileInputStream which obtains input bytes from a file in a file system
//FileInputStream is meant for reading streams of raw bytes such as image data. For reading streams of characters, consider using FileReader.
ByteArrayOutputStream bosn = new ByteArrayOutputStream();
byte[] bufn = new byte[1024];
try {
for (int readNum1; (readNum1 = fisn.read(bufn)) != -1;) {
//Writes to this byte array output stream
bosn.write(bufn, 0, readNum1);
System.out.println("read " + readNum1 + " bytes,");
}
} catch (IOException ex) {
}
byte[] outArray1 = bosn.toByteArray();
String encodedImage = new String(Base64.encodeBase64(outArray1), "UTF-8");
logger.debug("encodedImage" + encodedImage);
/// workbookDetails.append("<img src='data:image/png;base64," + encodedImage + "'/>");
workbookDetails.append("<img style='display:block; width:595px;height:609px;' id='base64image'")
.append(" src='data:image/jpeg;base64,")
.append(encodedImage)
.append("' /> ")
.append(" </p>")
.append(" </td>")
.append(" </tr>")
.append(" </tbody>")
.append("</table>");
.append("</table>");
I am trying to create a preview for PDF files which are created by Ballasamic Mockups. Around 50% of the time, I am not getting a preview and getting xref missing error. What am I doing wrong?
Error log :
com.sun.pdfview.PDFParseException: Expected 'xref' at start of table
at com.sun.pdfview.PDFFile.readTrailer(PDFFile.java:974)
at com.sun.pdfview.PDFFile.parseFile(PDFFile.java:1175)
at com.sun.pdfview.PDFFile.<init>(PDFFile.java:126)
at com.sun.pdfview.PDFFile.<init>(PDFFile.java:102)
Code :
private byte[] onlyCreatePdfPreview(String path, int attachId) {
try {
File file = new File(path);
RandomAccessFile raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
PDFFile pdffile = new com.sun.pdfview.PDFFile(buf);
PDFPage page = pdffile.getPage(0);
Rectangle rect = new Rectangle(0, 0,
(int) page.getBBox().getWidth(),
(int) page.getBBox().getHeight());
java.awt.Image img = page.getImage(
rect.width, rect.height, //width & height
rect, // clip rect
null, // null for the ImageObserver
true, // fill background with white
true // block until drawing is done
);
BufferedImage buffered = toBufferedImage(img);
buffered = Scalr.resize(buffered, Scalr.Method.ULTRA_QUALITY, 400, 250);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(buffered, "png", baos);
baos.flush();
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
}
What am I doing wrong? Thank you.
Final Working code
try {
String pdfPath = zipLocation + String.valueOf(new BigInteger(130, random).toString(32));
PdfReader reader = new PdfReader(path);
PdfStamper pdfStamper = new PdfStamper(reader,new FileOutputStream(pdfPath));
pdfStamper.getWriter().setPdfVersion(PdfWriter.PDF_VERSION_1_4);
pdfStamper.close();
reader.close();
RandomAccessFile raf = new RandomAccessFile(pdfPath, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
PDFFile pdffile = new com.sun.pdfview.PDFFile(buf);
PDFPage page = pdffile.getPage(0);
Rectangle rect = new Rectangle(0, 0,
(int) page.getBBox().getWidth(),
(int) page.getBBox().getHeight());
java.awt.Image img = page.getImage(
rect.width, rect.height, //width & height
rect, // clip rect
null, // null for the ImageObserver
true, // fill background with white
true // block until drawing is done
);
BufferedImage buffered = toBufferedImage(img);
buffered = Scalr.resize(buffered, Scalr.Method.ULTRA_QUALITY, 400, 250);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(buffered, "png", baos);
baos.flush();
return baos.toByteArray();
}//catch block
(This answer collects information from comments to the question which eventually led to a solution.)
Apparently com.sun.pdfview.PDFFile expects the cross references to start with xref. But this expectation only makes sense for PDFs following a PDF Reference up to revision 3 (version 1.4) published November 2001; PDFs following a later Reference or even the ISO 32000 standard (part 1 or 2) have the choice of using a cross reference stream (starting with an object number) instead of a cross reference table (starting with xref).
Thus, one should switch to using software following newer specifications than some more than 15 years old version or one has to convert one's PDFs to follow the old specifications, at least on the surface.
One can convert manually (e.g. using Adobe Acrobat) or automatized (e.g. using iText). (These examples software products really are only examples, other products can also be used for this task.)
If using a current iText 5 version, the conversion looks like this:
PdfReader reader = new PdfReader(SOURCE);
PdfStamper stamper = new PdfStamper(reader, DEST);
stamper.getWriter().setPdfVersion(PdfWriter.PDF_VERSION_1_4);
stamper.close();
reader.close();
And one has to take care that if SOURCE is a file name or a random access file, DEST must not be a file output stream to the same file. Otherwise the original file is truncated before the PdfStamper had a chance to copy it all to its output.
Hello I was curious on how data can be downloaded in java, so I looked through few methods and decided to use BufferedInputStream.
Now when I download, I download the file by 1024 bytes burst, and everytime it downloads 1kb I concat the temp array to the main data array.tH
I use this concat method:
public static byte[] concat(byte[] data, byte[] bytes) {
byte[] result = Arrays.copyOf(data, data.length + bytes.length);
System.arraycopy(bytes, 0, result, data.length, bytes.length);
return result;
}
This is my download process:
URL target = new URL ("http://freshhdwall.com/wp-content/uploads/2014/08/Image-Art-Gallery.jpg");
URLConnection t = target.openConnection();
t.setRequestProperty("User-Agent", "NING/1.0");
t.connect();
BufferedInputStream stream = new BufferedInputStream(t.getInputStream());
final byte[] bytes = new byte[1024];
int count;
byte[] data = new byte[0];
while ( (count = stream.read(bytes, 0, bytes.length)) != -1) {
System.out.println(count);
data = concat(data, bytes);
}
Now after downloading, I convert the bytes array to BufferedImage using ByteArrayInputStream:
InputStream s = new ByteArrayInputStream(data);
BufferedImage m = ImageIO.read(s);
And then I display the result:
JFrame j = new JFrame();
j.add(new JLabel(new ImageIcon(m)));
j.pack();
j.setVisible(true);
Now the result image looks like this:
(source: gyazo.com)
As you see, the image looks broken, missing bytes when downloading.
This is the real image:
img http://freshhdwall.com/wp-content/uploads/2014/08/Image-Art-Gallery.jpg
What did I do wrong that it displays the image like that?
On each loop iteration, you potentially read less than bytes.length bytes. As such, you can't use the full length of the array. You need to use exactly that part that was actually read.
One solution is to use
while ((count = stream.read(bytes, 0, bytes.length)) != -1) {
System.out.println(count); // this should hint at this
data = concat(data, bytes, count); // use the count
}
and
public static byte[] concat(byte[] data, byte[] bytes, int count) {
byte[] result = Arrays.copyOf(data, data.length + count);
System.arraycopy(bytes, 0, result, data.length, count);
return result;
}
so as to only copy over the bytes you've actually received.
Consider using some of the solutions here. They are probably more efficient or, at least, more readable.
I have a java.awt.Image that I need to add CCITT T.6 compression and convert to a TIFF byte array. I have seen some examples of using TIFFImageWriteParam and other classes from the javax.imageio package but I can’t find a complete example going all the way from Image to byte array.
Here is what I have so far beginning with a java.awt.Image obtained from scanning. This works just fine to generate a byte array of a TIFF, but I need to find a way, using TIFFImageWriteParam or some other means, to compress the TIFF prior to processing it as a byte array:
thisImage = ... a java.awt.Image from a scanner
if(thisImage!=null){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedImage bimg = new BufferedImage(thisImage.getWidth(null),thisImage.getHeight(null), BufferedImage.TYPE_BYTE_BINARY);
bimg.createGraphics().drawImage(thisImage, 0, 0, null);
try {
ImageIO.write(bimg, "tiff", baos);
} catch (Exception e) {
e.printStackTrace();
}
thisByteArray = baos.toByteArray();
...
Any help would be appreciated.
I found a solution thanks to: this thread.
Here is what I ended up doing that solved my issue:
thisImage = thisImage = ... a java.awt.Image from a scanner
if(thisImage!=null){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
boolean foundWriter = false;
BufferedImage bimg = new BufferedImage(thisImage.getWidth(null),thisImage.getHeight(null), BufferedImage.TYPE_BYTE_BINARY);
bimg.createGraphics().drawImage(thisImage, 0, 0, null);
for(Iterator<ImageWriter> writerIter = ImageIO.getImageWritersByFormatName("tif"); writerIter.hasNext() && !foundWriter;) {
foundWriter = true;
ImageWriter writer = (ImageWriter)writerIter.next();
writer.setOutput(ios);
TIFFImageWriteParam writeParam = (TIFFImageWriteParam)writer.getDefaultWriteParam();
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
writeParam.setCompressionType("CCITT T.6");
writer.prepareWriteSequence(null);
ImageTypeSpecifier spec = ImageTypeSpecifier.createFromRenderedImage(bimg);
javax.imageio.metadata.IIOMetadata metadata = writer.getDefaultImageMetadata(spec, writeParam);
IIOImage iioImage = new IIOImage(bimg, null, metadata);
writer.writeToSequence(iioImage, writeParam);
bimg.flush();
writer.endWriteSequence();
ios.flush();
writer.dispose();
ios.close();
thisByteArray = baos.toByteArray();
baos.close();
}
}