解析图片字节流获取图片信息:站在了巨人的肩膀上
实战——读取并分析BMP图像的十六进制数据_泼夫的博客-CSDN博客_图片十六进制解析
可以获取
- 图片类型
- 图片大小
- 图片宽度像素
- 图片高度像素
- ....
public static FastImageInfo imageDimension(byte[] bytes) throws IOException {
try (InputStream is = new ByteArrayInputStream(bytes)) {
return processStream(is);
}
}
private static FastImageInfo processStream(InputStream is) throws IOException {
int c1 = is.read();
int c2 = is.read();
int c3 = is.read();
String mimeType = null;
int width = -1, height = -1;
if (c1 == 'G' && c2 == 'I' && c3 == 'F') { // GIF
is.skip(3);
width = readInt(is, 2, false);
height = readInt(is, 2, false);
mimeType = "image/gif";
} else if (c1 == 0xFF && c2 == 0xD8) { // JPG
while (c3 == 255) {
int marker = is.read();
int len = readInt(is, 2, true);
if (marker == 192 || marker == 193 || marker == 194) {
is.skip(1);
height = readInt(is, 2, true);
width = readInt(is, 2, true);
mimeType = "image/jpeg";
break;
}
is.skip(len - 2);
c3 = is.read();
}
} else if (c1 == 137 && c2 == 80 && c3 == 78) { // PNG
is.skip(15);
width = readInt(is, 2, true);
is.skip(2);
height = readInt(is, 2, true);
mimeType = "image/png";
} else if (c1 == 66 && c2 == 77) { // BMP
is.skip(15);
width = readInt(is, 4, false);
height = Math.abs(readInt(is, 4, false));
mimeType = "image/bmp";
} else if (c1 == 'R' && c2 == 'I' && c3 == 'F') { // WEBP https://www.apiref.com/java11-zh/java.base/java/io/InputStream.html#readNBytes(int)
// byte[] bytes = is.readNBytes(27);
byte[] bytes = new byte[27];
int result = is.read(bytes, 0,27);
if (result != -1) {
width = ((int) bytes[24] & 0xff) << 8 | ((int) bytes[23] & 0xff);
height = ((int) bytes[26] & 0xff) << 8 | ((int) bytes[25] & 0xff);
mimeType = "image/webp";
}
} else {
int c4 = is.read();
if ((c1 == 'M' && c2 == 'M' && c3 == 0 && c4 == 42)
|| (c1 == 'I' && c2 == 'I' && c3 == 42 && c4 == 0)) { //TIFF
boolean bigEndian = c1 == 'M';
int ifd = 0;
int entries;
ifd = readInt(is, 4, bigEndian);
is.skip(ifd - 8);
entries = readInt(is, 2, bigEndian);
for (int i = 1; i <= entries; i++) {
int tag = readInt(is, 2, bigEndian);
int fieldType = readInt(is, 2, bigEndian);
int valOffset;
if ((fieldType == 3 || fieldType == 8)) {
valOffset = readInt(is, 2, bigEndian);
is.skip(2);
} else {
valOffset = readInt(is, 4, bigEndian);
}
if (tag == 256) {
width = valOffset;
} else if (tag == 257) {
height = valOffset;
}
if (width != -1 && height != -1) {
mimeType = "image/tiff";
break;
}
}
}
}
if (mimeType == null) {
throw new IOException("Unsupported image type");
}
FastImageInfo imageInfo = new FastImageInfo();
imageInfo.setWidth(width);
imageInfo.setHeight(height);
imageInfo.setMimeType(mimeType);
return imageInfo;
}
private static int readInt(InputStream is, int noOfBytes, boolean bigEndian) throws IOException {
int ret = 0;
int sv = bigEndian ? ((noOfBytes - 1) * 8) : 0;
int cnt = bigEndian ? -8 : 8;
for (int i = 0; i < noOfBytes; i++) {
ret |= is.read() << sv;
sv += cnt;
}
return ret;
}