JPEG保存到ios照片库后,DCT系数发生了变化

时间:2012-12-10 10:33:06

标签: ios jpeg libjpeg dct

将JPEG图像保存到iOS照片库时会发生奇怪的变化。我不知道我做错了什么。 我正在使用libjpeg-turbo来访问JPEG图像,然后我修改了图像的DCT系数。修改后的图像(仅在DCT中,没有别的)保存在照片库中。但是在打开保存的图像后,DCT系数与我在上一步中更改的系数不同。

详细说明,让我解释一下我如何为每个DCT添加+1。我正在使用libjpeg库的“example.c”中的标准过程:

struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
FILE * infile;

if ((infile = fopen(filename, "rb")) == NULL) {
    fprintf(stderr, "can't open %s\n", filename);
    return 0;
}

cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;

if (setjmp(jerr.setjmp_buffer)) {
    jpeg_destroy_decompress(&cinfo);
    fclose(infile);
    return 0;
}

jpeg_create_decompress(&cinfo);

jpeg_stdio_src(&cinfo, infile);

(void) jpeg_read_header(&cinfo, TRUE);

jvirt_barray_ptr* coeffs_array;
coeffs_array = jpeg_read_coefficients(&cinfo);

BOOL done = FALSE;
for (int ci = 0; ci < 3; ci++)
{
    JBLOCKARRAY buffer_one;
    JCOEFPTR blockptr_one;
    jpeg_component_info* compptr_one;
    compptr_one = cinfo.comp_info + ci;

    for (int by = 0; by < compptr_one->height_in_blocks; by++)
    {
        buffer_one = (cinfo.mem->access_virt_barray)((j_common_ptr)&cinfo, coeffs_array[ci], by, (JDIMENSION)1, FALSE);

        for (int bx = 0; bx < compptr_one->width_in_blocks; bx++)
        {
            blockptr_one = buffer_one[0][bx];

            for (int bi = 0; bi < 64; bi++)
            {
                blockptr_one[bi]++;
            }                  
        }   
    } 
}

write_jpeg(output, &cinfo, coeffs_array); // saving modified JPEG to the output file

jpeg_destroy_decompress(&cinfo);
fclose(infile);

在此之后,我在文件中保存了一个新的JPEG图像,让我们说“new.jpg”。现在我想将这个“new.jpg”保存到照片库,所以我加载图像:

imageToSave = [UIImage imageWithContentsOfFile:outputFile];

我还检查了DCT系数是否保持变化。在我拥有相同的图像后,我修改了DCT,然后我将保存它:

UIImageWriteToSavedPhotosAlbum(imageToSave, nil, nil, nil);

图片“new.jpg”现已保存在照片库中。

到目前为止,一切都很好,DCT系数的工作方式与libjpeg库的效果相同。当我再次加载保存的图像并查看DCT系数时,会发生变化。我发现DCT已经改变了,我不知道为什么。当您想要保存JPEG图像时,是否有iOS使用的优化算法?为什么DCT会发生变化。

我正在使用以下程序读取保存的图像:

NSData *jpegData = UIImageJPEGRepresentation([info objectForKey:UIImagePickerControllerOriginalImage], 1);
[jpegData writeToFile:file atomically:YES]; // saved image is saved in file and I can use the procedure from above to check DCTs

此外,这是原始DCT的示例,通过向所有人添加+1来修改DCT,并在将其保存到一个8x8块的照片库后加载DCT:

Original DCTs:
-759 -24 -8 1 -1 0 0 1 
56 -27 -10 1 0 1 0 0 
8 0 0 0 0 -1 0 0 
0 0 0 -1 0 -1 0 -1 
0 0 0 1 0 0 0 0 
0 0 0 1 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 -1 0 0 0 0 

Modified DCTs by libjpeg:
-758 -23 -7 2 0 1 1 2 
57 -26 -9 2 1 2 1 1 
9 1 1 1 1 0 1 1 
1 1 1 0 1 0 1 0 
1 1 1 2 1 1 1 1 
1 1 1 2 1 1 1 1 
1 1 1 1 1 1 1 1 
1 1 1 0 1 1 1 1 

DCTs after saving JPEG to photo library:
-758 -22 -7 2 0 0 0 0 
58 -26 -8 3 0 0 0 0 
8 2 0 0 -1 1 0 0 
2 3 0 0 0 0 0 0 
2 1 -1 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 -1 

任何帮助将不胜感激。我真的没有想法为什么在保存图像到照片库之后DCT会改变。

2 个答案:

答案 0 :(得分:2)

当您使用UIImage及其方法时,iOS将始终重新压缩您的JPEG,从而改变DCT。相反,使用AssetsLibrary将用户的图片存储和检索为NSData。此行为未记录,但可以正常工作。

我还建议将.jpeg存储在临时文件夹中,然后将其提供给libjpeg-turbo。

答案 1 :(得分:-1)

您应该彻底简化代码,以查看发生不良行为的位置。您正在执行至少五个不同的步骤,这些步骤可能会出错。

现在,据说它不能在iOS上运行,但知道JPEG编解码器,请注意用于保存 file.jpg 质量。我不确定您的特定库的默认设置是什么,但是如果不是100%,它将最终影响您的DCT系数。

尝试使用无损编解码器(例如PNG或BMP)保存修改后的图像。

相关问题