as the title say i need to find some java jpeg encoder (it's good both source code or external library) that given an array that represent a raw pixel image or a BufferedImage can encode it without writing anything on file and return the encoded image possibly trough an array of some kind, with at least possibility to choose image quality and possibly with good efficiency.
NB: the array/image type input required (byte, int, argb, rgb, bgr, yuv...) doesn't matter for me, i can make approppriate conversions
As already mentioned in the comments: You can use the ImageIO class, and use it to write to a ByteArrayOutputStream. The code could really be as simple as this:
private static byte[] getJpgData(BufferedImage image)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", baos);
return baos.toByteArray();
}
This will NOT write the image to a disc or so. It will only write the image into a memory block, which you can then process or manipulate further.
If you just need a stream of bytes, then use Java's built in methods.
http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#write(java.awt.image.RenderedImage,%20java.lang.String,%20java.io.OutputStream)
ImageIO.write(myImage, "format", myOutputStream);
Related
I'm using com.sun.media.imageioimpl.plugins.tiff.TIFFPackBitsCompressor to try and encode an array of tiff bytes I have using PackBits. I'm unfamiliar with this class and haven't been finding many examples on how to use it. But, when following the javadoc, I've been getting an NPE every time I try to encode my data. So far as I can see, none of my values are null. I've tried these tests with multiple values at this point, but below is my most recent iteration:
TIFFPackBitsCompressor pack = new TIFFPackBitsCompressor();
//bImageFromConvert is a 16-bit BufferedImage with all desired data.
short[] bufferHolder = ((DataBufferUShort) bImageFromConvert.getRaster().getDataBuffer()).getData();
//Since bImageFromConvert is 16-bits, the short array isn't the right length.
//The below conversion handles tihs issue
byte[] byteBuffer = convertShortToByte(bufferHolder);
//I'm not entirely sure what this int[] in the parameters should be.
//For now, it is a test int[] array containing all 1s
int[] testint = new int[byteBuffer.length];
Arrays.fill(testint, 1);
//0 offset. dimWidth = 1760, dimHeight = 2140. Not sure what that last param is supposed to be in layman's terms.
//npe thrown at this line.
int testOut = pack.encode(byteBuffer, 0, dimWidth, dimHeight, testint, 1);
Does anyone have any insight as to what's happening? Also, if available, does anyone know a better way to encode my TIFF files using PackBits in a java program?
Let me know if there's anything to make my question clearer.
Thank you!
As said in the comment, you are not supposed to use the TIFFPackBitsCompressor directly, instead it's used internally by the JAI ImageIO TIFF plugin (the TIFFImageWriter) when you specify "PackBits" as compression type in the ImageWriteParam. You may also pass a compressor instance in the param, if you cast it to TIFFImageWriteParam first, but this is more useful for custom compressions not known by the plugin.
Also note that the compressor will only write PackBits compressed pixel data, it will not create a full TIFF file.
The normal way of writing a PackBits compressed TIFF file is:
BufferedImage image = ...; // Your input image
ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next(); // Assuming a TIFF plugin is installed
try (ImageOutputStream out = ImageIO.createImageOutputStream(...)) { // Your output file or stream
writer.setOutput(out);
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionType("PackBits");
writer.write(null, new IIOImage(image, null, null), param);
}
writer.dispose();
The above code should work fine using both JAI ImageIO and the TwelveMonkeys ImageIO TIFF plugins.
PS: PackBits is a very simple compression algorithm based on run-length encoding of byte data. As 16 bit data may vary wildly between the high and low byte of a single sample, PackBits is generally not a good choice for compression of such data.
As stated in my comments, using completely random values I got the following results:
Compression | File size
-----------------|-----------------
None | 7 533 680 bytes
PackBits | 7 593 551 bytes
LZW w/predictor | 10 318 091 bytes
ZLib w/predictor | 10 318 444 bytes
This is not very surprising, as completely random data isn't generally compressible (without data loss). For a linear gradient, which may be more similar to "photographic" image data I got completely different results:
Compression | File size
-----------------|-----------------
None | 7 533 680 bytes
PackBits | 7 588 779 bytes
LZW w/predictor | 200 716 bytes
ZLib w/predictor | 144 136 bytes
As you see, here the LZW and Deflate/Zlib algorithms (with predictor step) performs MUCH better. For "real" data, there's likely more noise, so your results is likely somewhere in between these extremes.
Hi I have a model testing question for a object recognition project i am working on. I want to be able to take .jpeg files I have in my eclipse project folder and reduce them to very sparse byte arrays in Java. For example if I had a picture of a ball I would like to be able to convert it to the following byte 2-D array:
00000000000000000
00000001110000000
00001100001110000
00010000000001000
00010000000001000
00001000000010000
00000011111000000
00000000000000000
If someone could be so kind as to explain how I can do this most efficiently I would greatly appreciate it. I am fairly new to programming and do not understand much more than oop so if you could describe the process in simple programming terms without any jargon I would really appreciate it.
First to get byte array of image you need to convert image to BufferedImage. See ths link to convert image to BuffredImage. http://www.dzone.com/snippets/converting-images
After you get BufferedImage convert t into bytearray using bufferedImageToByteArray function.
BufferedImage buf_image; // this is BufferedImage reference you got after converting it from Image
byte[] imageByteArray = bufferedImageToByteArray(buf_image,"jpg");
public static byte[] bufferedImageToByteArray(BufferedImage image, String format) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, format, baos);
return baos.toByteArray();
}
Good friends of the forum.
I've been searching a lot, and I could not find how to serialize an image and pass it to a String in android.
as might be not so, If someone knows and wants to inform me I would appreciate very much!.
Although the java.awt.Image class is not (does not implement) java.io.Serializable, javax.swing.ImageIcon is. Because of this, you can serialize it as follows:
ImageIcon myImage; // declare somewhere
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(myImage);
byte[] theBytes = baos.toByteArray();
StringBuffer buf = new StringBuffer();
for (byte b : theBytes) {
buf.append((char) b); // cast to char, then append
}
String theString = b.toString();
I'll let you figure out how to reverse it, but here's a hint: instead of OutputStream classes, use InputStream classes.
You could read the bytes of the image to a byte[] and then encode the byte[] using Base64, Here is how.
Base64 will be the most efficient way to reliably transfer binary data (such as an image) in a string.
However, since you are requesting something smaller, you may consider base64 encoding your image, then compressing the resultant string, then base64 encoding that...
It saves you a few bytes, but not many. And in some cases it may even make the result larger.
If you have control of both the server and the client, you should consider creating another interface that would allow you to send bytes.
So - I've got a third party library that needs a File as input. I've got a byte array.
I don't want to write the bytes to disk .. I'd like to keep this in memory. Any idea on how I can create a File from the provided byte array (without writing to disk)?
Sorry, not possible. A File is inherently an on-disk entity, unless you have a RAM disk - but that's not something you can create in Java.
That's exactly the reason why APIs should not be based on File objects (or be overloaded to accept an InputStream).
There's one possibility, but it's a real long-shot.
If the API uses new FileReader(file) or new FileInputStream(file) then you're hosed, but...
If it converts the file to a URL or URI (using toURL() or toURI()) then, since File is not final, you can pass in a subclass of File in which you control the construction of the URL/URI and, more importantly, the handler.
But the chances are VERY slim!
So I see there is an accepted answer (and this is old), but I found a way to do this. I was using the IDOL On Demand API and needed to convert a byte array to a File.
Here is an example of taking a byte array of an image and turning into a File:
//imageByte is the byte array that is already defined
BufferedImage image = null;
ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
image = ImageIO.read(bis);
bis.close();
// write the image to a file
File outputfile = new File("image.png");
ImageIO.write(image, "png", outputfile);
And so outputfile is a File that can be used later in your program.
Is this:
ByteBuffer buf = ByteBuffer.allocate(1000);
...the only way to initialize a ByteBuffer?
What if I have no idea how many bytes I need to allocate..?
Edit: More details:
I'm converting one image file format to a TIFF file. The problem is the starting file format can be any size, but I need to write the data in the TIFF to little endian. So I'm reading the stuff I'm eventually going to print to the TIFF file into the ByteBuffer first so I can put everything in Little Endian, then I'm going to write it to the outfile. I guess since I know how long IFDs are, headers are, and I can probably figure out how many bytes in each image plane, I can just use multiple ByteBuffers during this whole process.
The types of places that you would use a ByteBuffer are generally the types of places that you would otherwise use a byte array (which also has a fixed size). With synchronous I/O you often use byte arrays, with asynchronous I/O, ByteBuffers are used instead.
If you need to read an unknown amount of data using a ByteBuffer, consider using a loop with your buffer and append the data to a ByteArrayOutputStream as you read it. When you are finished, call toByteArray() to get the final byte array.
Any time when you aren't absolutely sure of the size (or maximum size) of a given input, reading in a loop (possibly using a ByteArrayOutputStream, but otherwise just processing the data as a stream, as it is read) is the only way to handle it. Without some sort of loop, any remaining data will of course be lost.
For example:
final byte[] buf = new byte[4096];
int numRead;
// Use try-with-resources to auto-close streams.
try(
final FileInputStream fis = new FileInputStream(...);
final ByteArrayOutputStream baos = new ByteArrayOutputStream()
) {
while ((numRead = fis.read(buf)) > 0) {
baos.write(buf, 0, numRead);
}
final byte[] allBytes = baos.toByteArray();
// Do something with the data.
}
catch( final Exception e ) {
// Do something on failure...
}
If you instead wanted to write Java ints, or other things that aren't raw bytes, you can wrap your ByteArrayOutputStream in a DataOutputStream:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
while (thereAreMoreIntsFromSomewhere()) {
int someInt = getIntFromSomewhere();
dos.writeInt(someInt);
}
byte[] allBytes = baos.toByteArray();
Depends.
Library
Converting file formats tends to be a solved problem for most problem domains. For example:
Batik can transcode between various image formats (including TIFF).
Apache POI can convert between office spreadsheet formats.
Flexmark can generate HTML from Markdown.
The list is long. The first question should be, "What library can accomplish this task?" If performance is a consideration, your time is likely better spent optimising an existing package to meet your needs than writing yet another tool. (As a bonus, other people get to benefit from the centralised work.)
Known Quantities
Reading a file? Allocate file.size() bytes.
Copying a string? Allocate string.length() bytes.
Copying a TCP packet? Allocate 1500 bytes, for example.
Unknown Quantities
When the number of bytes is truly unknown, you can do a few things:
Make a guess.
Analyze example data sets to buffer; use the average length.
Example
Java's StringBuffer, unless otherwise instructed, uses an initial buffer size to hold 16 characters. Once the 16 characters are filled, a new, longer array is allocated, and then the original 16 characters copied. If the StringBuffer had an initial size of 1024 characters, then the reallocation would not happen as early or as often.
Optimization
Either way, this is probably a premature optimization. Typically you would allocate a set number of bytes when you want to reduce the number of internal memory reallocations that get executed.
It is unlikely that this will be the application's bottleneck.
The idea is that it's only a buffer - not the whole of the data. It's a temporary resting spot for data as you read a chunk, process it (possibly writing it somewhere else). So, allocate yourself a big enough "chunk" and it normally won't be a problem.
What problem are you anticipating?