一、JPEG 图像的 SOF0 标记(Start of Frame 0)提供了图像的基本信息,以下是标记后面跟的字节的具体含义:
名称 字节数 值 说明
--------------------------------------------------------------------------
段标识 1 FF
段类型 1 C0
段长度 2 其值=8+组件数量×3
(以下为段内容)
样本精度 1 8 每个样本位数(大多数软件不支持12和16)
图片高度 2
图片宽度 2
组件数量 1 3 1=灰度图,3=YCbCr/YIQ 彩色图,4=CMYK 彩色图
(以下每个组件占用3字节)
组件 ID 1 1=Y, 2=Cb, 3=Cr, 4=I, 5=Q
采样系数 1 0-3位:垂直采样系数
4-7位:水平采样系数
量化表号 1
二、先来看一张由gray8数据转成yuv420p数据,然后经过硬件jpeg编码成jpeg的图像数据。看起来是灰色图,实际数据是彩图,
// Gray8 to YUV420P (I420)
void convert_gray8_to_yuv420p(const unsigned char *gray, unsigned char *yuv420p, int width, int height) {
int frame_size = width * height;
int chroma_size = (width / 2) * (height / 2);
memcpy(yuv420p, gray, frame_size);
unsigned char *u_plane = yuv420p + frame_size;
unsigned char *v_plane = u_plane + chroma_size;
memset(u_plane, 128, chroma_size);
memset(v_plane, 128, chroma_size);
}
图像高度:0x0100=256 图像宽度:0x0500=1280,分量数量(Number of Components)是3:指定了图像中颜色分量的数量。每个分量描述了一个颜色通道,通常是 Y、Cb、Cr 或者灰度图像中的 Y 通道。这个字段后面跟着每个分量的详细信息。
三、再看一张gray8灰度jpeg图的数据格式
图像高度:0x0100=256 图像宽度:0x0500=1280,分量数量(Number of Components)是0x01,说明是灰度图。
四、Android app java 使用程序去识别是灰度图还是彩图。
private static final byte SOF0_MARKER = (byte) 0xC0;
public static boolean isGrayscaleJPEG(byte[] jpegData)
{
int sof0Index = findSOF0Marker(jpegData);
if (sof0Index == -1) {
return false;
}
int colorComponentCount = jpegData[sof0Index + 9] & 0xff;
Log.d(TAG,"colorComponentCount=" + colorComponentCount);
return colorComponentCount == 1;
}
private static int findSOF0Marker(byte[] jpegData)
{
for (int i = 0; i < jpegData.length - 1; i++) {
if (jpegData[i] == (byte) 0xFF && jpegData[i + 1] == SOF0_MARKER) {
return i;
}
}
return -1;
}
boolean isgray= isGrayscaleJPEG(image);
if (isgray ) {
Log.i(TAG,"Image type: Gray8");
} else {
Log.i(TAG,"Image type: RGB");
}
五、看一下运行时候的log。