Reputation: 380
In my code I'm reading image convert it to byte array and modifying that byte array with some logic and trying to generate image from that modified byte array, but i'm unable to generate image from that code
my code sample:
//1. Convert Image to byte code
ByteArrayOutputStream baos=new ByteArrayOutputStream();
BufferedImage img=ImageIO.read(new File(dirName,"MyImg.png"));
ImageIO.write(img, "png", baos);
baos.flush();
byte[] bytes = baos.toByteArray();
byte[] modified = baos.toByteArray();
String temp_string = new String();
for (int i = 0; i < bytes.length; i++)
{
// conversion of byte to unsign byte
int b = bytes[i] & 0xFF;
/*
* convert byte array to an 8 bit string
*/
int temp,count = 1;
byte b1 = (byte)b;
String uv = String.format("%8s", Integer.toBinaryString(b1 & 0xFF)).replace(' ', '0');
String tempStr = "";
for(int zx = 0 ; zx < uv.length() ; zx++ )
{
temp = Character.getNumericValue(uv.charAt(zx));
if(temp == 1)
{
temp += count;
count = temp;
if(temp % 2 == 0)
temp = 0;
else
temp = 1;
tempStr += temp;
}
else if(temp == 0)
{
tempStr += 0;
}
}
temp_string += tempStr;
if(i < bytes.length)
{
temp_string +=",";
}
}
String[] string_ByteArray = temp_string.split(",");
for(int a =0 ; a < string_ByteArray.length ; a++)
{
int aaa = Integer.parseInt(string_ByteArray[a],2);
modified[a] = (byte) aaa;
}
//3. Convert byte code to Image
ByteArrayInputStream bis = new ByteArrayInputStream(modified);
BufferedImage bImage2 = ImageIO.read(bis);
ImageIO.write(bImage2, "png", new File("output.png") );
in this code i'm getting error in 3rd step:
Exception in thread "main" java.lang.IllegalArgumentException: image == null!
at javax.imageio.ImageTypeSpecifier.createFromRenderedImage(Unknown Source)
at javax.imageio.ImageIO.getWriter(Unknown Source)
at javax.imageio.ImageIO.write(Unknown Source)
at mypack.Img_conversion.main(Img_conversion.java:96)
Upvotes: 1
Views: 810
Reputation: 44404
That is an impressively roundabout way of doing bit manipulation. There is no valid reason to use Strings. I suggest you either use bitwise operators, or use a BitSet.
Iterating through bits mathematically:
int b = bytes[i] & 0xFF;
for (int j = 7; j >= 0; j--) {
int bit = (b >> j) & 1;
temp = /* ... */;
if (temp != 0) {
b |= (1 << j); // set bit j
} else {
b &= ~(1 << j); // clear bit j
}
}
modified[i] = (byte) b;
Iterating through bits with a BitSet:
byte b = bytes[i];
BitSet bits = BitSet.valueOf(new byte[] { b });
for (int j = 7; j >= 0; j--) {
int bit = bits.get(j) ? 1 : 0;
temp = /* ... */;
bits.set(j, temp != 0);
}
modified[i] = bits.toByteArray()[0];
You might notice that since BitSet.valueOf takes an array of bytes, it’s wasteful to keep creating new BitSets. Instead, you could just do BitSet.valueOf(bytes)
once, and run through all the bits in that single BitSet:
BitSet bits = BitSet.valueOf(bytes);
for (int i = bits.cardinality() - 1; i >= 0; i--) {
int bit = bits.get(i) ? 1 : 0;
temp = /* ... */;
bits.set(i, temp != 0);
}
byte[] modified = bits.toByteArray();
However…
A PNG image is (usually) compressed. This means the bits do not directly correspond to pixels. Modifying those bits creates an invalid compressed data block, which is why your attempt to read it with ImageIO.read fails and returns null.
If you want bytes you can directly manipulate, get them from the raw BufferedImage, not from a PNG representation:
int[] pixels = img.getData().getPixels(
0, 0, img.getWidth(), img.getHeight(),
new int[0]);
byte[] bytes = pixels.length * 4;
ByteBuffer.wrap(bytes).asIntBuffer().put(pixels);
It would be much easier for others to help you, if you took the time to give your variables meaningful names. temp
and uv
and zx
are cryptic and meaningless. Better names would be:
j
)When you’re done modifying the bytes, you still have raw image data, not a PNG representation, so you cannot make a ByteArrayInputStream from those bytes and pass them to ImageIO.read. Attempting to pass off those bytes as a PNG representation will always fail.
Instead, overwrite your image with the pixel data:
int[] pixels = new int[bytes.length / 4];
ByteBuffer.wrap(bytes).asIntBuffer().get(pixels);
img.getRaster().setPixels(0, 0, img.getWidth(), img.getHeight(), pixels);
ImageIO.write(img, "png", new File("output.png"));
Upvotes: 1
Reputation: 806
As stated in the documentation if any of the parameter of the write
method is null it will throw IllegalArgumentException
.
You call like this:
ImageIO.write(bImage2, "png", new File("output.png") );
The only parameter which can be null is the bImage2
.
Please check it if it's really null
.
Upvotes: 0