任何大于 16x8 或 8x16 的图像尺寸的 JPEG 编码错误
JPEG encoding error for any image size larger than 16x8 or 8x16
目前我正在为一个大学项目开发一个 jpeg 编码器。图像具有固定大小,编码器使用固定量化和霍夫曼表进行基线处理。首先,我的代码从 SDRAM 读取 32 位 RGBx 值,转换为 YCbCr 颜色 space,将每个通道标准化为 0 并写回。然后,它开始对 8x8 块进行 DCT,并将熵编码数据写入 SDRAM。这个过程是使用 C 完成的,然后 Python 代码创建一个带有适当 JFIF 标记和熵编码数据的文件。最后,OS 使用默认的 jpeg 解码器,只需双击即可查看图像。
我的代码适用于 8x8、8x16 和 16x8 图像,但不适用于 16x16 或项目中使用的图像的实际大小。您可能会在下面看到 16x16 示例。
16x16 输入
16x16 输出
但是,在 Whosebug 上,它似乎与我的 OS' 默认解码器相比有所不同。下面是它在 macOS 预览应用程序上的样子。
我认为我的问题是由于 JFIF 中的标记或某种算法错误造成的。
如果有 jpeg 方面经验的人可以帮助我,我将非常高兴。
亲切的问候
我写了一个jpeg编解码器。它保持在 https://github.com/MalcolmMcLean/babyxrc 但是,尽管欢迎您查看甚至使用它,但这并不能真正回答您的问题。
JPEG 基于 16x16 色度块和 8x8 亮度块。因此,您的软件的初始版本在第一个 16x16 块后崩溃也就不足为奇了。这只是一个例行的编程错误。如果您无法通过阅读 JEG 规范找到它,请启动编辑器并创建平面 32x32 图像。然后查看二进制文件,看看它与您的不同之处。
这是我的没有子采样的负载扫描
static int loadscanYuv111(JPEGHEADER *hdr, unsigned char *buff, FILE *fp)
{
short lum[64];
short Cb[64];
short Cr[64];
BITSTREAM *bs;
int i;
int ii;
int iii;
int iv;
int diffdc = 0;
int dcb = 0;
int dcr = 0;
int actableY;
int actableCb;
int actableCr;
int dctableY;
int dctableCb;
int dctableCr;
int count = 0;
int target;
int luminance;
int red;
int green;
int blue;
actableY = hdr->useac[0];
actableCb = hdr->useac[1];
actableCr = hdr->useac[2];
dctableY = hdr->usedc[0];
dctableCb = hdr->usedc[1];
dctableCr = hdr->usedc[2];
bs = bitstream(fp);
for(i=0;i<hdr->height;i+=8)
for(ii=0;ii<hdr->width;ii+=8)
{
if(hdr->dri && (count % hdr->dri) == 0 && count > 0 )
{
readmarker(bs);
diffdc = 0;
dcb = 0;
dcr = 0;
}
getblock(lum, hdr->dctable[dctableY], hdr->actable[actableY], bs);
lum[0] += diffdc;
diffdc = lum[0];
for(iv=0;iv<64;iv++)
lum[iv] *= hdr->qttable[hdr->useq[0]][iv];
unzigzag(lum);
idct8x8(lum);
getblock(Cb, hdr->dctable[dctableCb], hdr->actable[actableCb], bs);
Cb[0] += dcb;
dcb = Cb[0];
for(iv=0;iv<64;iv++)
Cb[iv] *= hdr->qttable[hdr->useq[1]][iv];
unzigzag(Cb);
idct8x8(Cb);
getblock(Cr, hdr->dctable[dctableCr], hdr->actable[actableCr], bs);
Cr[0] += dcr;
dcr = Cr[0];
for(iv=0;iv<64;iv++)
Cr[iv] *= hdr->qttable[hdr->useq[2]][iv];
unzigzag(Cr);
idct8x8(Cr);
for(iii=0;iii<8;iii++)
{
if( i + iii >= hdr->height)
break;
for(iv=0;iv<8;iv++)
{
if(ii + iv >= hdr->width)
break;
target = (i + iii) * hdr->width * 3 + (ii + iv) * 3;
luminance = lum[iii*8+iv]/64 + 128;
red = (int) (luminance + 1.402 * Cr[iii*8+iv]/64);
green = (int) (luminance - 0.34414 * Cb[iii*8+iv]/64 - 0.71414 * Cr[iii*8+iv]/64);
blue = (int) (luminance + 1.772 * Cb[iii*8+iv]/64);
red = clamp(red, 0, 255);
green = clamp(green, 0, 255);
blue = clamp(blue, 0, 255);
buff[target] = red;
buff[target+1] = green;
buff[target+2] = blue;
}
}
count++;
}
killbitstream(bs);
if(loadeoi(fp) == 0)
return 0;
return -1;
}
如您所见,数据是交错的。
但是,如果你弄错了,它会创建一个尺寸正确的奇特图像,而不是比预期更小的图像。
目前我正在为一个大学项目开发一个 jpeg 编码器。图像具有固定大小,编码器使用固定量化和霍夫曼表进行基线处理。首先,我的代码从 SDRAM 读取 32 位 RGBx 值,转换为 YCbCr 颜色 space,将每个通道标准化为 0 并写回。然后,它开始对 8x8 块进行 DCT,并将熵编码数据写入 SDRAM。这个过程是使用 C 完成的,然后 Python 代码创建一个带有适当 JFIF 标记和熵编码数据的文件。最后,OS 使用默认的 jpeg 解码器,只需双击即可查看图像。
我的代码适用于 8x8、8x16 和 16x8 图像,但不适用于 16x16 或项目中使用的图像的实际大小。您可能会在下面看到 16x16 示例。
但是,在 Whosebug 上,它似乎与我的 OS' 默认解码器相比有所不同。下面是它在 macOS 预览应用程序上的样子。
我认为我的问题是由于 JFIF 中的标记或某种算法错误造成的。
如果有 jpeg 方面经验的人可以帮助我,我将非常高兴。
亲切的问候
我写了一个jpeg编解码器。它保持在 https://github.com/MalcolmMcLean/babyxrc 但是,尽管欢迎您查看甚至使用它,但这并不能真正回答您的问题。
JPEG 基于 16x16 色度块和 8x8 亮度块。因此,您的软件的初始版本在第一个 16x16 块后崩溃也就不足为奇了。这只是一个例行的编程错误。如果您无法通过阅读 JEG 规范找到它,请启动编辑器并创建平面 32x32 图像。然后查看二进制文件,看看它与您的不同之处。
这是我的没有子采样的负载扫描
static int loadscanYuv111(JPEGHEADER *hdr, unsigned char *buff, FILE *fp)
{
short lum[64];
short Cb[64];
short Cr[64];
BITSTREAM *bs;
int i;
int ii;
int iii;
int iv;
int diffdc = 0;
int dcb = 0;
int dcr = 0;
int actableY;
int actableCb;
int actableCr;
int dctableY;
int dctableCb;
int dctableCr;
int count = 0;
int target;
int luminance;
int red;
int green;
int blue;
actableY = hdr->useac[0];
actableCb = hdr->useac[1];
actableCr = hdr->useac[2];
dctableY = hdr->usedc[0];
dctableCb = hdr->usedc[1];
dctableCr = hdr->usedc[2];
bs = bitstream(fp);
for(i=0;i<hdr->height;i+=8)
for(ii=0;ii<hdr->width;ii+=8)
{
if(hdr->dri && (count % hdr->dri) == 0 && count > 0 )
{
readmarker(bs);
diffdc = 0;
dcb = 0;
dcr = 0;
}
getblock(lum, hdr->dctable[dctableY], hdr->actable[actableY], bs);
lum[0] += diffdc;
diffdc = lum[0];
for(iv=0;iv<64;iv++)
lum[iv] *= hdr->qttable[hdr->useq[0]][iv];
unzigzag(lum);
idct8x8(lum);
getblock(Cb, hdr->dctable[dctableCb], hdr->actable[actableCb], bs);
Cb[0] += dcb;
dcb = Cb[0];
for(iv=0;iv<64;iv++)
Cb[iv] *= hdr->qttable[hdr->useq[1]][iv];
unzigzag(Cb);
idct8x8(Cb);
getblock(Cr, hdr->dctable[dctableCr], hdr->actable[actableCr], bs);
Cr[0] += dcr;
dcr = Cr[0];
for(iv=0;iv<64;iv++)
Cr[iv] *= hdr->qttable[hdr->useq[2]][iv];
unzigzag(Cr);
idct8x8(Cr);
for(iii=0;iii<8;iii++)
{
if( i + iii >= hdr->height)
break;
for(iv=0;iv<8;iv++)
{
if(ii + iv >= hdr->width)
break;
target = (i + iii) * hdr->width * 3 + (ii + iv) * 3;
luminance = lum[iii*8+iv]/64 + 128;
red = (int) (luminance + 1.402 * Cr[iii*8+iv]/64);
green = (int) (luminance - 0.34414 * Cb[iii*8+iv]/64 - 0.71414 * Cr[iii*8+iv]/64);
blue = (int) (luminance + 1.772 * Cb[iii*8+iv]/64);
red = clamp(red, 0, 255);
green = clamp(green, 0, 255);
blue = clamp(blue, 0, 255);
buff[target] = red;
buff[target+1] = green;
buff[target+2] = blue;
}
}
count++;
}
killbitstream(bs);
if(loadeoi(fp) == 0)
return 0;
return -1;
}
如您所见,数据是交错的。 但是,如果你弄错了,它会创建一个尺寸正确的奇特图像,而不是比预期更小的图像。