Convert byte array (byte[]) to Image in Java - java

I have a byte[] that I want to convert to an Image and display the image in a label.
The byte[] is of a jpeg 2000 format.
I have tried the code below but it returns null:
InputStream in = new ByteArrayInputStream(bytearray);
BufferedImage image = ImageIO.read(in);
The image value comes back as null.
I want to be able to display the image in a label like below:
jLabel.setIcon(new ImageIcon(image));
Thanks

To convert an array of bytes, i.e. byte[] into an Image, use getImage(). Probably the easiest way to do this is to instantiate an ImageIcon using the ImageIcon(byte[]) constructor, and then call getImage(). This is illustrated in the method below, particularly the last line:
public Image createImage(){
//ccurve.png
byte[] b = {-119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82,
0, 0, 0, 15, 0, 0, 0, 15, 8, 6, 0, 0, 0, 59, -42, -107,
74, 0, 0, 0, 64, 73, 68, 65, 84, 120, -38, 99, 96, -64, 14, -2,
99, -63, 68, 1, 100, -59, -1, -79, -120, 17, -44, -8, 31, -121, 28, 81,
26, -1, -29, 113, 13, 78, -51, 100, -125, -1, -108, 24, 64, 86, -24, -30,
11, 101, -6, -37, 76, -106, -97, 25, 104, 17, 96, -76, 77, 97, 20, -89,
109, -110, 114, 21, 0, -82, -127, 56, -56, 56, 76, -17, -42, 0, 0, 0,
0, 73, 69, 78, 68, -82, 66, 96, -126};
return new ImageIcon(b).getImage();
}
I think this can by used for png, gif, bmp, and jpg images. Also the byte array does not have to be hard-coded, as in this example.
If you want an ImageIcon instead of an Image, don't call getImage():
public ImageIcon createImageIcon(){
//ccurve.png
byte[] b = {-119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82,
0, 0, 0, 15, 0, 0, 0, 15, 8, 6, 0, 0, 0, 59, -42, -107,
74, 0, 0, 0, 64, 73, 68, 65, 84, 120, -38, 99, 96, -64, 14, -2,
99, -63, 68, 1, 100, -59, -1, -79, -120, 17, -44, -8, 31, -121, 28, 81,
26, -1, -29, 113, 13, 78, -51, 100, -125, -1, -108, 24, 64, 86, -24, -30,
11, 101, -6, -37, 76, -106, -97, 25, 104, 17, 96, -76, 77, 97, 20, -89,
109, -110, 114, 21, 0, -82, -127, 56, -56, 56, 76, -17, -42, 0, 0, 0,
0, 73, 69, 78, 68, -82, 66, 96, -126};
return new ImageIcon(b);
}
Then you can call jlabel.setIcon(createIconImage());.

ServletOutputStream out = response.getOutputStream();
out.write(user.getBytes());
The above is how its worked for me in the past where user has a profile picture simply stored in a byte array. The servlet realizes this and outputs the image.

Related

How can I convert image to arrays using Java code?

I'm trying to set up an MLKit detection project on Android using Tensorflow library, I have got false values on the output using Tensorflow lite ( different values than Frozen model inference ).
I doubt that the problem is with the input ( image ), So I want to compare the two same images that I have.
To do this task, I have used PIL image and numpy libraries on python to get bytes arrays, and I have converted the drawable image to bitmap and from bitmap to bytes arrays.
I don't know if the function np.asarray should give the same value as those two functions below:
Java code:
private float[][][][] bitmapToInputArray() {
// [START mlkit_bitmap_input]
Bitmap bitmap= getYourInputImage();
int batchNum = 0;
float[][][][] input = new float[1][112][112][3];
for (int x = 0; x < 112; x++) {
for (int y = 0; y < 112; y++) {
int pixel = bitmap.getPixel(x, y);
// Normalize channel values to [-1.0, 1.0]. This requirement varies by
// model. For example, some models might require values to be normalized
// to the range [0.0, 1.0] instead.
input[batchNum][x][y][0] = (Color.red(pixel))/ 255.0f;
input[batchNum][x][y][1] = (Color.green(pixel)) / 255.0f;
input[batchNum][x][y][2] = (Color.blue(pixel))/ 255.0f;
Log.i("Input","input"+input[batchNum][x][y][0]);
Log.i("input","input"+input[batchNum][x][y][1]);
}
}
// [END mlkit_bitmap_input]
return input;
}
public byte[] convertBitmapToByteArray(Bitmap bitmap) {
ByteArrayOutputStream stream = null;
try {
stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
Log.e(ThemedSpinnerAdapter.Helper.class.getSimpleName(), "ByteArrayOutputStream was not closed");
}
}
}
}
private Bitmap getYourInputImage() {
// This method is just for show
BitmapDrawable drawable = (BitmapDrawable) image2.getDrawable();
Bitmap bitmap = drawable.getBitmap();
Bitmap bitmapp=Bitmap.createScaledBitmap(bitmap,112,112,true);
Bitmap bitmap2= bitmapp.copy(Bitmap.Config.ARGB_8888, true);
return bitmap2;
}
byte[] bytes=convertBitmapToByteArray(bitmap1);
Log.i("byte",""+ Arrays.toString(bytes));
float[][][][] inp = new float[1][112][112][3];
inp=bitmapToInputArray();
Log.i("byte2",""+Arrays.toString(inp[0]));
Python script:
img = Image.open("irisdata-300VW_Dataset_2015_12_14-017-000880.jpg")
img.load()
img = img.resize((112, 112), PIL.Image.ANTIALIAS)
print(str(image_to_byte_array(img)))
# Normalize to [0, 1]
data = np.asarray( img, dtype="float32")
print(data)
Output of java code:
2019-08-20 19:01:13.589 1513-1513/com.example.irisdetection I/byte: [-1, -40, -1, -32, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, -1, -37, 0, 67, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -37, 0, 67, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -64, 0, 17, 8, 0, 112, 0, 112, 3, 1, 34, 0, 2, 17, 1, 3, 17, 1, -1, -60, 0, 29, 0, 0, 2, 2, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 6, 9, 4, 5, 10, 3, 2, 1, -1, -60, 0, 69, 16, 0, 1, 3, 3, 1, 5, 5, 4, 7, 5, 6, 5, 5, 0, 0, 0, 3, 1, 2, 4, 5, 6, 17, 33, 0, 7, 18, 19, 49, 8, 34, 65, 81, 97, 20, 35, 113, -127, 9, 21, 50, 51, -111, -95, -79, 36, 66, -63, -47, -16, 22, 23, 67, 82, 83, -31, 37, 52, 98, 114, -15, 99, 115, -126, -125, -94, -1, -60, 0, 28, 1, 0, 2, 2, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 4, 5, 2, 3, 8, 0, 1, -1, -60, 0, 55, 17, 0, 0, 4, 3, 6, 3, 8, 1, 3, 4, 3, 1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 17, 33, 0, 6, 49, 65, 81, 97, 18, 19, 113, 7, 20, 35, -127, -111, -95, -79, -16, -47, 34, -63, -31, 21, 36, 67, -15, 8, 22, 50, 51, -1, -38, 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, 0, -28, -105, 115, 116, 26, 45, 98, -97, 117, 74, -71, -31, -57, -88, 40, -73, 93, 88, -83, 83, 89, 39, 41, -20, -43, 40, -7, 28, 115, 12, -100, -52, -116, -88, 78, 53, -45, 84, -49, -53, 102, 114, 124, 34, -52, -20, -3, -72, 91, -115, 6, -58, -120, -76, -5, -102, -126, 71, 36, -107, 43, -97, -11, 61, 93, -17, 78, 96, 63, 115, -35, -52, 8, -3, -30, -89, -40, -26, 117, -40, 29, -70, 107, 106, 21, 112, 86, -36, 7, 73, 36, 120, -9, 30, -19, -18, -48, -56, 86, -79, -88, -31, -106, -105, 36, -53, -53, 103, 30, -92, 121, 24, -120, 76, 47, -7, -15, -99, 54, 103, 44, -88, -107, 42, -57, 98, 107, 90, 83, -98, 105, 20, -21, 43, 126, 53, -117, 106, 58, -71, -116, 84, -114, 58, -11, 22, 53, 77, -84, 119, 47, -34, -14, -52, 72, 102, 127, -68, -57, -61, 77, -78, 126, -35, 18, -79, 112, 9, 38, 41, 40, 50, 3, 104, 63, -7, -64, 66, 97, -100, -66, -115, -115, 59, 43, -119, 21, 43, -50, -111, 79, 62, 82, -55, -72, 64, 70, -76, -92, -6, 5, 119, -54, -42, 15, -40, -126, -36, -81, 86, 109, 8, 55, 69, -62, 114, 31, -39, -30, 125, 65, 65, 9, 120, -47, -111, -24, -48, 36, -55, 56, -58, 49, -12, 103, 52, -14, 77, -24, -68, 12, -41, 24, -38, -49, 45, -6, 122, -80, -104, -106, -88, 32, -76, 92, 72, -67, 51, -13, 95, 92, -2, 105, -90, 112, -85, -1, 0, 101, -21, 110, -105, 72, -35, 117, -93, 21, -22, -48, 56, 84, 56, 50, 9, -62, -33, -74, 105, 35, -25, -99, 126, 42, 71, -89, -126, -86, -2, 91, 77, 119, -59, -67, 56, 86, 101, 29, -50, -116, -41, 28, -83, 78, 1, 2, 59, 85, 78, 103, -82, -120, -120, -119, -16, 84, -8, -81, -82, -43, -119, 2, 73, -74, -32, 34, 124, -95, -91, 103, -120, -56, 48, -108, -3, 55, 10, -128, 72, 44, 54, -11, 68, -43, -117, 63, 85, 41, 75, -67, -81, -115, 104, 11, -128, 98, 30, 84, -99, -90, 117, -103, -47, 13, 32, -111, 99, 59, 8, -30, 120, -85, 59, -38, -8, 42, 116, -50, -67, 51, -25, -116, 109, -17, 6, -128, 85, 123, 72, 34, 46, 60, 28, -72, -8, 39, 69, -49, -97, -13, -38, -77, -28, -17, 107, 125, -75, -103, -113, -97, 108, 110, -34, -19, -88, 0, 69, -53, 80, 84, -87, 74, -114, 69, 34, -82, -124, 81, -94, 97, 124, -4, -70, 109, 40, -94, 118, -112, -19, 67, 109, 76, -114, -54, -2, -25, 36, -118, -104, -30, 35, -122, -39, -111, -90, 10, 79, 39, 61, 73, -53, 69, -41, 25, 93, 116, -12, -38, -87, 70, -4, -59, 84, -83, 100, 30, 67, 47, -65, 103, 51, 120, 107, -94, 36, 68, -124, -63, -31, -56, 39, 44, -58, -127, -112, -53, 110, -125, -106, 118, 97, 30, -117, 46, 58, 100, -68, 46, 110, 123, -51, -41, -89, 84, -4, -4, -68, 126, 91, 123, -44, -30, 3, -39, -107, 80, 92, 92, 89, -18, -89, -34, 105, -29, -4, 83, -11, -38, 47, -70, -19, -17, 10, -4, -89, 8, -43, 90, 49, 40, -14, -36, 1, -72, -111, -56, -113, 86, 101, 90, -103, 31, 125, 62, -13, -29, -32, -102, -90, -60, -55, -43, 90, 28, 126, 23, 56, 106, -118, -115, -30, 114, 47, -106, 5
2019-08-20 19:01:13.590 1513-1513/com.example.irisdetection I/byte2: [[[F#8bc81c1, [[F#4123d66, [[F#d5d68a7, [[F#ed2a154, [[F#7ce78fd, [[F#c74c9f2, [[F#66de843, [[F#627ec0, [[F#50ea7f9, [[F#201933e, [[F#57cc59f, [[F#250c6ec, [[F#f88cab5, [[F#7ffa54a, [[F#d721cbb, [[F#1f965d8,
Output of python code:
How can I get the same output of the python code with Java code using bitmap as an input?

Input to large for RSA Cipher

I have generated the following Public Key in Android.
fun createCipher(): Cipher
{
val posKey = posPublicKey
posKey.publicKey.modulus
var spec = RSAPublicKeySpec(BigInteger(posPublicKey.publicKey.modulus), BigInteger(posPublicKey.publicKey.exponent))
var fact = KeyFactory.getInstance(KeyProperties.KEY_ALGORITHM_RSA)
publicKey = fact.generatePublic(spec)
var cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding")
cipher.init(Cipher.ENCRYPT_MODE, publicKey)
return cipher
}
The RSA key size that I have selected is 4096 bytes
The exponent is 3 bytes and the modulus is 512 bytes
The Modulus Byte Array is as follows:
[-32, -28, -121, 32, 109, -82, 43, 115, 43, -117, 20, 35, 122, 33, -2, 23, 23, -22, 75, 0, 91, 10, -89, 48, 33, -89, 57, 1, 57, -13, 9, -127, 90, 121, -96, -94, 106, -16, -105, -112, -74, 30, -12, 74, -74, 104, -26, 15, 99, -22, -55, -75, 14, -45, 56, 20, 85, 90, 83, -50, 68, -114, 5, -10, -109, 79, 44, 81, 68, -98, -45, -51, -97, 71, 90, -13, -78, 118, -21, -47, 66, 104, -83, 56, -72, -27, 45, 16, 70, 32, -76, -125, -11, 108, 126, -61, -126, 16, 6, -49, -106, -114, 18, 49, 121, -39, -109, 115, 111, -128, 83, 8, -110, -10, -4, 51, -67, 49, 66, 103, -76, -88, -110, 122, 56, 29, -101, 22, 3, 117, -104, -54, -64, -71, 23, 58, 87, 37, 96, 25, -114, 38, 1, -126, 33, -91, -4, 89, -28, 10, 95, -104, -24, -38, 17, 47, -122, 24, -89, 123, 100, 12, -10, -57, -44, 45, 25, 39, -80, -101, -6, -99, -95, -5, 70, 32, 37, -57, -52, -47, -66, 85, 10, -48, 75, 4, -114, 104, -7, -112, -128, 4, 114, 77, -40, 96, 66, 83, -54, 10, 111, 102, -39, -63, 2, -75, 38, 36, 24, 13, -51, 96, 89, -60, -40, 99, 65, 123, 52, -114, 122, 75, 32, -121, 80, -76, -11, -1, -31, -118, -51, -21, 13, 109, 111, -102, 120, -56, 62, -19, -79, 86, -41, -81, 67, -80, -63, 37, 35, 47, 109, -32, 47, -128, 95, -48, -53, -1, -125, -19, -9, -10, 15, -116, -50, 53, -86, -102, -24, 107, 122, -43, -125, 51, 14, 101, 67, 57, 116, 97, -40, -98, -82, -118, -83, 120, -107, -14, 19, -49, -27, 10, 25, 40, 43, -27, 31, 59, -57, 58, 33, -98, 1, -45, -118, 76, -21, -13, -123, 67, 42, -37, -96, -32, 33, 124, 1, 44, -99, 74, 18, 32, 10, -107, -121, 86, -115, -70, -107, 109, 17, -92, 109, -47, 60, -49, -91, 7, -125, 47, 78, 86, 81, -2, -35, 17, 124, 94, -26, -80, -84, 120, 110, 38, -55, -90, -11, 107, 73, 71, 44, 69, -58, 56, -59, 2, 94, 27, 88, 29, -57, 95, -99, 5, 102, -66, 118, -82, 126, 20, -104, -95, 47, -2, 77, -33, 89, -66, -92, 121, -5, 78, 68, -1, -82, -95, -121, 117, -29, 70, 11, -72, 54, -99, -13, -87, 9, 77, -113, 51, -124, -56, -8, 126, -114, -31, 90, -125, -11, 41, -85, 74, 3, 90, -95, 85, 121, 61, 14, 116, 51, -40, -57, -124, -69, -51, -76, -119, -80, 95, 95, 17, -34, 80, -36, 66, -51, 14, -69, -113, 35, -109, -115, -16, -3, -118, 114, -20, -81, 57, -65, 40, -8, -67, -85, 110, 50, -128, 44, -78, 93, -44, -93, 89, -76, 13, 98, -38, -55, -120, 11, 127, 84, -2, 101, 57, -121, -111, 91, -102, -118, 85, -124, -90, 91, -84, 28, 120, -28, -105, 88, -73, 6, 89, 33, 8, 9, 30, 9, -6, 17, 25]
The Exponent Byte Array is as Follows:
[1, 0, 1]
The test Key is as follows:
val stringKey = "8D-F7-5B-15-0F-2A-E5-3E-FD-44-5A-63-50-AC-62-D6-06-2D-59-5C-F1-C3-9A-DB-45-25-0D-7A-72-AE-DF-87"
val stringIV = "FA-94-FD-74-2E-AC-2C-90-79-98-AF-A3-D7-12-5D-A2"
var aeskey = AesKeyBuilder()
val key = (stringKey.replace("-", "")).toByteArray(Charsets.US_ASCII)
val iv = (stringIV.replace("-", "")).toByteArray(Charsets.US_ASCII)
aeskey.key = key
aeskey.iv = iv
val encryptedKey = cipher.doFinal(aesKey.Key)
The item that I am trying to encrypt is 64 bytes. Using this public key.
However, I get the following error:
Process: com.touchsides.rewards.debug, PID: 19470
com.android.org.bouncycastle.crypto.DataLengthException: input too large for RSA cipher.
at com.android.org.bouncycastle.crypto.engines.RSACoreEngine.convertInput(RSACoreEngine.java:115)
at com.android.org.bouncycastle.crypto.engines.RSABlindedEngine.processBlock(RSABlindedEngine.java:95)
at com.android.org.bouncycastle.crypto.encodings.OAEPEncoding.encodeBlock(OAEPEncoding.java:199)
at com.android.org.bouncycastle.crypto.encodings.OAEPEncoding.processBlock(OAEPEncoding.java:131)
I believe the modulus size is large enough to allow for the encryption of this byte array.
You get the com.android.org.bouncycastle.crypto.DataLengthException error because RSA key was created with negative Modulus. So it can't be used to encrypt even one byte.
BigInteger default constructor uses the most significant bit of provided byte array payload as sign bit for the number. So you have to explicitly specify that you want a positive number using another constructor where the first argument is a sign indicator:
BigInteger(1, posPublicKey.publicKey.modulus), BigInteger(1, posPublicKey.publicKey.exponent)
There's also a C# approach to add a zero-byte in front of the byte array (so the sign bit will be always zero):
BigInteger(byteArrayOf(0) + posPublicKey.publicKey.modulus), BigInteger(byteArrayOf(0) + posPublicKey.publicKey.exponent)
And finally, if you already have your BigInteger created the wrong way, it's possible to convert it:
var modulus = BigInteger(posPublicKey.publicKey.modulus)
if (modulus.compareTo(BigInteger.ZERO) < 0)
modulus = modulus.add(BigInteger.ONE.shiftLeft(4096))
Please also look at this answer and answers of this question.

lzw decompression algorithm in java for given compressed text

I have following compressed text given as a byte Array:
byte[] compressed = [97, 2, 10, 28, 72, -80, -96, -63, -125, 8, 19, 42, 92, -56, -80, -95, -61, -121, 16, 35, 74, -100, 72, -79, -94, -59, -117, 24, 51, 106, -36, -56, -79, -93, -57, -113, 32, 67, -118, 28, 73, -78, -92, -55, -109, 40, 83, -86, 92, -55, -78, -91, -53, -105, 48, 99, -54, -100, 73, -77, -90, -51, -101, 56, 115, -22, -36, -55, -77, -89, -49, -97, 64, -125, 10, 29, 74, -76, -88, -47, -93, 72, -109, 42, 93, -54, -76, -87, -45, -89, 80, -93, 74, -99, 74, -75, -86, -43, -85, 88, -77, 106, -35, -54, -75, -85, -41, -81, 96, -61, -118, 29, 75, -74, -84, -39, -77, 104, -45, -86, 93, -53, -74, -83, -37, -73, 112, -29, -54, -99, 75, -73, -82, -35, -69, 120, -13, -22, -35, -53, -73, -81, -33, -65, -128, 3, 11, 30, 76, -72, -80, -31, -61, -120, 19, 43, 94, -52, -72, -79, -29, -57, -112, 35, 75, -98, 76, -71, -78, -27, -53, -104, 51, 107, -34, -52, -71, -77, -25, -49, -96, 67, -117, 30, 77, -70, -76, -23, -45, -88, 83, -85, 94, -51, -70, -75, -21, -41, -80, 99, -53, -98, 77, -69, -74, -19, -37, -72, 115, -21, -34, -51, -69, -73, -17, -33, -64, -125, 11, 31, 78, -68, -72, -15, -29, -56, -109, 43, 95, -50, -68, -71, -13, -25, -48, -93, 75, -97, 78, -67, -70, -11, -21, -40, -77, 107, -33, -50, -67, -69, -9, -17, -32, -61, -117, 31, 79, -66, -68, -7, -13, -24, -45, -85, 95, -49, -66, -67, -5, -9, -16, -29, -53, -97, 79, -65, -66, -3, -5, -8, -13, -21, -33, -49, -65, -65, -1, -1, 0, -61, 4, 20, 56, -112, 96, 65, -125, 7, 17, 38, 84, -72, -112, 97, 67, -121, 15, 33, 70, -108, 56, -111, 98, 69, -117, 23, 49, 102, -44, -72, -111, 99, 71, -113, 31, 65, -122, 20, 57, -110, 100, 73, -109, 39, 81, -90, 84, -71, -110, 101, 75, -105, 47, 97, -58, -108, 57, -109, 102, 77, -101, 55, 113, -26, -44, -71, -109, 103, 79, -97, 63, -127, 6, 21, 58, -108, 104, 81, -93, 71, -111, 38, 85, -70, -108, 105, 83, -89, 79, -95, 70, -107, 58, -107, 106, 85, -85, 87, -79, 102, -43, -70, -107, 107, 87, -81, 95, -63, -122, 21, 59, -106, 108, 89, -77, 103, -47, -90, 85, -69, -106, 109, 91, -73, 111, 91, 2];
and a given codeword length of 9 bits.
The resulting string should be aaaaaaaaaaaaaaaaaaaaaaaaa... with a total length of 39270 of all *a*s.
I want to write a decompress function which decompresses the compressed byte array and returns the resulting string of *a*s.
I tried the normal LZW implementations but this didn't work very well. The given codeword length of 9 bit and the negative values in the byte array gives me some headache.
My understanding is I have to convert the whole byte array to one binary string and read each value every 9 bits (codeword length)?
Has anyone a hint or a suggestion how this can be done? Thanks, I really appreciate your support.
Edit:
Here is some code, I tried so far, which works with
byte[] compressed = [68, 0, 97, 0, 115, 0, 32, 0, 105, 0, 115, 0, 116, 0, 32, 0, 101, 0, 105, 0, 110, 0, 32, 0, 107, 0, 117, 0, 114, 0, 122, 0, 101, 0, 114, 0, 32, 0, 84, 0, 101, 0, 120, 0, 116, 0]
and a given codeword length of 16 bits.
The resulting string is Das ist ein kurzer Text.
public static List<String> convertByteArrayToBinaryStringList(byte[]compressedData,int codeWordLength){
StringBuilder sb=new StringBuilder();
List<String> binaryCompressedValues=new ArrayList<String>();
for(int i=0;i<compressedData.length;i++){
sb.append(byteToBinaryString(compressedData[i]));
}
char[]binaryCharArray=sb.toString().toCharArray();
int j=0;
while(j<binaryCharArray.length){
StringBuilder binStringBuilder=new StringBuilder();
for(int i=j;i<j+codeWordLength;i++){
if(j+codeWordLength>binaryCharArray.length){
System.out.println("End reached!");
binStringBuilder.append("0");
}else{
binStringBuilder.append(binaryCharArray[i]);
}
}
j+=codeWordLength;
binaryCompressedValues.add(binStringBuilder.toString());
}
return binaryCompressedValues;
}
public String incrementDictSize(String currentDictSize) {
String incrementedString = Integer.toBinaryString(Integer.valueOf(currentDictSize, 2) + 1);
int lengthDistance = currentDictSize.length() - incrementedString.length();
String padding = "";
if (lengthDistance > 0) {
for (int i = 0; i < lengthDistance; i++) {
padding += "0";
}
}
return padding + incrementedString;
}
public byte[]uncompress(byte[]compressedData){
int codeWordLength=16;
List<String> binaryCompressedValues=new ArrayList<String>();
binaryCompressedValues=convertByteArrayToBinaryStringList(compressedData,codeWordLength);
//int dictSize = 256;
String dictSize="1111111100000000";
Map<String, String> dictionary=new HashMap<String, String>();
String s="00000000";
String padString="00000000";
for(int i=0;i< 256;i++){
s=String.format("%8s",Integer.toBinaryString(i)).replace(' ','0');
dictionary.put(s+padString,""+(char)i);
System.out.println("dictionary.get("+i+") "+s+padString+" "+dictionary.get(s+padString));
}
//String w = "" + (char)(byte)compressedData[0];
String w="";
StringBuffer result=new StringBuffer(w);
for(String k:binaryCompressedValues){
String entry;
if(dictionary.containsKey(k)){
entry=dictionary.get(k);
dictionary.put(incrementDictSize(currentDictSize),w+entry.charAt(0));
result.append(entry);
w=entry;
}else{
entry=w+w.charAt(0);
result.append(entry);
dictionary.put(incrementDictSize(currentDictSize),w+w.charAt(0));
w=entry;
}
}
return result.toString().getBytes();
}
Example code for reading n-bit-codes LSB first.
Beware dirty details like alignment on code size change.
/** An <code>NBitsInputStream</code> reads its <code>InputStream</code>
* as codes of n bits, least significant bits first.
*/// extend with set/increaseCodeLength() as needed
class NBitsInputStream extends java.io.FilterInputStream {
int buffer, validBits;
int codeLength, codeMask;
protected NBitsInputStream(InputStream in, int n) {
super(in);
codeLength = n;
codeMask = (1 << n) - 1;
}
/** Reads a code of n bits, least significant bits first.
* #return the code, or -1 if -1 is read. */
#Override
public int read() throws IOException {
while (validBits < codeLength) {
int high = super.read();
if (high < 0) // EOF
return high;
buffer |= high << validBits;
validBits += 8;
}
int code = buffer & codeMask;
validBits -= codeLength;
buffer >>= codeLength;
return code;
}
}
(Tried
for (int code ; 0 <= (code = codes.read()) ; ) {
String entry = (String) dictionary.get(code);
w += (null != entry ? entry : w).charAt(0);
dictionary.put(++currentDictSize, w);
result.append(w = entry);
}
without unexpected observations.)
Note that your dictionary will contain not just the longest strings, but each of their prefixes, for up to about 2130641537 characters using 16 bit codes (in addition to a result of almost that length).

not getting the original data after decompression with Inflater. inflate

Here's my test code, the problem is resultLength != original.length, and result array is same as original array, shouldn't it be after compression and decompression?
public static void main(String[] args) {
// generateTyreAlarmEvent()
byte[] original = {10, 17, 97, 98, 99, 100, 101, 102, 103, 104, 105, 103, 107, 108, 109, 110, 111, 112, 113, 16, 2, 24, -50, -1, -113, -59, 5, 34, 20, 8, -35, 1, 16, 40, 24, -34, 1, 32, 60, 40, -33, 1, 48, 80, 56, -32, 1, 64, 100, 42, 16, 8, 2, 16, 1, 24, 3, 32, 0, 40, 1, 48, 1, 56, 1, 64, 0};
byte[] buffer = new byte[original.length];
Deflater compresser = new Deflater();
compresser.setInput(original);
compresser.finish();
int compressedLen = compresser.deflate(buffer);
compresser.end();
Inflater decompressor = new Inflater();
decompressor.setInput(buffer, 0, compressedLen);
byte[] result = new byte[original.length];
int resultLength = 0;
try {
resultLength = decompressor.inflate(result);
} catch (DataFormatException e) {
}
decompressor.end();
// the problem is resultLength(63) != original.length(67), and result array is same as original array
}
The original byte array is (len is 67) :
{10, 17, 97, 98, 99, 100, 101, 102, 103, 104, 105, 103, 107, 108, 109, 110, 111, 112, 113, 16, 2, 24, -50, -1, -113, -59, 5, 34, 20, 8, -35, 1, 16, 40, 24, -34, 1, 32, 60, 40, -33, 1, 48, 80, 56, -32, 1, 64, 100, 42, 16, 8, 2, 16, 1, 24, 3, 32, 0, 40, 1, 48, 1, 56, 1, 64, 0}
and the result is (len is 63) :
{10, 17, 97, 98, 99, 100, 101, 102, 103, 104, 105, 103, 107, 108, 109, 110, 111, 112, 113, 16, 2, 24, -50, -1, -113, -59, 5, 34, 20, 8, -35, 1, 16, 40, 24, -34, 1, 32, 60, 40, -33, 1, 48, 80, 56, -32, 1, 64, 100, 42, 16, 8, 2, 16, 1, 24, 3, 32, 0, 40, 1, 48, 1}
Thanks!
You did not make the output buffer big enough. Just to test, I replaced byte[] buffer = new byte[original.length]; with byte[] buffer = new byte[1000];, and it worked fine.
If the data is not compressible, as this is, then the output will be larger than the input.

DataFormatException: incorrect header check in java.util.zip.InflaterInputStream

I use javafx WebView in my project and it began crash at one website.
Through debug i understood, that when page receives part of js-code server uses header "Content-Encoding:deflate", ignoring my request headers.
Main problem in inflate method of InflaterInputStream.
java.util.zip.ZipException: incorrect header check
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
I reproduced this error in simple method:
public byte[] makeTestRequest(String url) throws Exception {
InputStreamResponseListener listener = new InputStreamResponseListener();
Request request = httpClient
.newRequest(url);
request.send(listener);
Response response = listener.get(5, TimeUnit.SECONDS);
byte[] uncompressedData = new byte[65536];
if (response.getStatus() == 200) {
try(InputStream responseContent = listener.getInputStream()){
InputStream stream = new InflaterInputStream(responseContent);
int len, offset = 0;
while ((len = stream.read(uncompressedData , offset, uncompressedData.length-offset))>0) {
offset += len;
}
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return uncompressedData;
}
Error occurs in this method.
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/zip/Inflater.java#247
Inflator's buffer in this moment contains data:
[-52, 93, 105, 115, 19, -57, -70, -2, 43, 42, 127, -54, -87, -63, -55, 116, -49, -98, 111, 22, 96, 98, -57, -40, -114, 23, -74, -101, -5, -63, 24, -127, 29, -37, -40, 120, 97, 75, -91, -54, 24, 8, -71, 5, 9, 107, 78, 40, 3, 33, 108, 39, 124, 57, 39, 62, 24, -127, -15, 34, -2, -62, -24, 31, -35, 126, -33, 30, 75, -45, -45, 61, 51, 26, 105, 20, 83, -87, 20, -42, 72, -74, -34, -18, -89, -33, 125, -23, -17, 59, -26, -58, -58, -89, 74, -117, 71, 74, -13, 11, -109, -77, 103, 59, -66, 116, 40, -47, 109, 87, -73, -68, 125, 29, -89, -25, 103, 103, 106, -49, 117, -10, 122, 108, 124, 113, 118, 126, -95, -10, -56, -78, 108, -41, -13, 8, -75, -10, 117, 44, -52, -51, -50, 47, 46, 116, 124, -7, 63, -33, 119, 76, -98, -22, -8, -110, 24, -122, 109, -17, 99, 127, 122, -66, 116, 118, -79, 7, 30, -20, -21, -104, -102, 60, -53, 126, -24, 88, 40, -99, -103, 97, 15, 59, -40, -17, -80, 95, 25, -104, 63, 85, -102, 103, 79, 53, -83, 83, -45, 14, -112, -2, 18, 123, 126, 118, 108, -90, -60, 30, -7, 47, -85, 87, -85, 43, -2, 127, -3, -118, -65, -11, 121, -63, 95, -83, 94, -59, -97, 55, 11, -2, 29, -1, -91, -65, -38, -15, -61, -66, -32, -69, -22, 127, 26, -120, -112, -1, -80, -6, 79, -42, 126, -97, -102, 54, -11, -62, -76, -102, -87, -76, -114, 107, -102, 123, -48, -103, 10, -3, -31, -25, 126, -39, -33, 97, -1, 109, 84, -81, 48, 90, 31, 51, 90, -33, -79, 127, 95, 86, 111, 85, 127, -87, -34, -16, -53, -43, 101, 124, -2, -112, 125, -7, -102, -65, -59, 62, 117, -69, -10, -11, 102, 10, -7, -29, -22, 111, -87, 47, -33, 51, 28, 51, 59, -7, 93, 90, 118, -14, -1, -12, 55, -128, -8, -6, 87, 59, -60, -10, -78, -94, 60, 114, -48, -42, 15, -57, -94, -4, 79, 32, -124, -3, -5, -100, -67, 126, -29, -81, 85, -105, 25, 73, -1, -57, 8, -72, -30, 111, -78, 47, 47, 23, -4, 109, -10, 112, -123, -47, 20, -94, -62, -16, 44, 43, 76, -123, -95, -96, 98, -66, 116, -122, 29, 89, 120, -41, 54, -115, 40, 81, 68, -45, 102, -12, -119, -109, 33, -94, -18, -78, 111, -127, -81, 44, -121, 72, -5, -61, -81, 84, -81, -80, -89, 12, 60, -10, -22, 25, -37, -93, -113, -80, 51, -80, 35, -2, -70, -65, 86, -93, -57, 72, 1, -108, 36, 125, 79, 125, 85, -90, 103, -89, -82, 74, 90, -58, 56, -79, -10, -89, 44, -29, 87, -1, 13, 35, -70, 2, -80, 50, -46, -73, 16, -8, -73, 8, 55, -20, -7, -57, 78, 98, -121, 118, -106, -70, 70, -104, 6, -102, 74, -125, -50, -74, 82, 100, -71, 87, -64, -77, 64, -125, -1, 1, -72, -104, -67, 126, 84, 103]
I'm surprised, but my that page successfully displayed in Chrome and Safari, but don't work in javafx WebView.
Is it a bug in inflate method or i'm doing something wrong?
It didn't solve the problem with javafx WebView, but using Inflator constructor with nowrap option helped with incorrect header check" error:
Inflator inf = new Inflator(true);
InputStream stream = new InflaterInputStream(responseContent, inf);

Categories