该隐的剑 2024-04-09 12:46 采纳率: 0%
浏览 4

JPEG图片EXIF格式中DirectoryEntry的问题

JPEG图片使用EXIF格式时读取DirectoryEntry的问题
想写一个解压缩JPEG图片的功能,查了很多关于TIFF格式的介绍,也知道EXIF就是TIFF,只是有一点点差别。
现在遇到的问题是,读取TIFF的头不存在问题,遍历IFD也没有问题,读取每一个IFD中的DirectoryEntry时遇到不能理解的地方。
DE(DirectiryEntry)共12字节,01字节为tag,23字节为type,47字节为length,811字节为offsetOfValue;
保存图片的宽度的DE信息,其tag为0x0100(高端序),type为3(2字节的整型数值),length为1,这些都正常,但offsetOfValue读出来的值与实际完全无关.
保存图片的宽度的DE信息,其tag为0x0101(高端序),type为3(2字节的整型数值),length为1,这些都正常,offsetOfValue也一样完全无关。
如果offsetOfValue是根据TIFF格式的说明,那么它存储的就应当是宽度值,而非偏移量。但明显这个值与图片实际宽度(和高度)不同。
如果offsetOfValue是指向偏移量的,这个偏移量值已经大于文件尺寸了。
无论offsetOfValue是高端序还是低端序,都与实际值没半毛钱关系。
第一张图片是图片的信息,以及IFD0的完整字节,IFD1的字节没有截图,因为IFD1里没有tag为0x0100和0x0101的DE.

img


第二张图片是遍历IFD及读取DE的C++代码

img


第三张图片是Debug输出日志,日志中显示的数值完全无法尝试理解

img


想请问一下,问题出在哪?是对DE定义理解错了吗?

  • 写回答

5条回答 默认 最新

  • 码农阿豪@新空间代码工作室 Java领域优质创作者 2024-04-09 12:47
    关注
    让阿豪来帮你解答,本回答参考chatgpt3.5编写提供,如果还有疑问可以评论或留言
    问题描述:在读取JPEG图片使用EXIF格式时,读取DirectoryEntry的过程中遇到问题。 解决方案:根据题目中的描述,问题可能出在读取DE(DirectoryEntry)时offsetOfValue的值与实际值不同,无论offsetOfValue是高端序还是低端序,都与实际值没半毛钱关系。因此,我们需要检查代码中对DE定义的理解是否正确,以及是否正确地读取了offsetOfValue的值。 首先,我们需要了解一下DirectoryEntry的具体定义: DirectoryEntry是TIFF格式中的一个重要概念,用于存储TIFF文件中的各种信息,如图片的宽度、高度、光圈值等等。DirectoryEntry的结构如下:
    • Tag:一个2字节的整数,用于标识DirectoryEntry所描述的图片信息类型;
    • Type:一个2字节的整数,用于标识DirectoryEntry的值类型,如int16、int32、float等;
    • Count:一个4字节的整数,用于表示DirectoryEntry的值占用的长度,即"value"字段的长度;
    • Value Offset:一个4字节的整数,表示"value"字段在TIFF文件中的偏移量(相对于TIFF文件起始位置),该偏移量可能指向另一个IFD(即Directory Offset),也可能指向当前IFD内的值。如果值的长度小于4字节,则"Value Offset"字段可以直接存储值本身,而不需要指向另一个IFD或者内部值。 根据上述定义,我们可以初步判断问题可能出在读取offsetOfValue的值上。为了验证这一点,我们可以在代码中增加一些调试信息,检查读取到的offsetOfValue的值是否正确。例如,在以下代码段中:
    ifdFileStream.seekg(dirOffset + i * sizeof(DirectoryEntry));
    ifdFileStream.read(reinterpret_cast<char *>(&entry), sizeof(DirectoryEntry));
    // 判断Tag是否为0x0100或0x0101,如果是,则打印出Value Offset的值
    if (entry.Tag == 0x0100 || entry.Tag == 0x0101) {
        std::cout << "Tag = " << std::hex << entry.Tag << ", Value Offset = " << std::dec << entry.ValueOffset << std::endl;
    }
    

    我们在读取DirectoryEntry时,判断Tag是否为0x0100或0x0101,如果是,则打印出Value Offset的值。这样,我们可以检查Value Offset的值是否正确,并与实际值进行比较。 如果确定是offsetOfValue的值有误,我们需要检查代码中的读取方式是否正确。例如,在以下代码段中:

    if (entry.ValueOffset <= 4) {
        // Value is stored directly in ValueOffset
        value = entry.ValueOffset;
    } else {
        // Value is stored in another location, seek to that location and read it
        ifdFileStream.seekg(entry.ValueOffset);
        ifdFileStream.read(reinterpret_cast<char *>(&value), sizeof(value));
    }
    

    如果ValueOffset小于等于4,则值直接存储在ValueOffset中,否则值存储在另一个位置,我们需要通过seekg函数跳转到这个位置读取值。这里需要注意的是,如果要读取的值的类型为2字节或4字节的整型数值时,需要使用对应的类型来读取,否则可能会读取错误的值。例如,对于一个2字节的整型值(Type为3),我们需要使用int16类型来读取:

    if (entry.Type == 3) {
        if (entry.ValueOffset <= 4) {
            // Value is stored directly in ValueOffset
            value = *(reinterpret_cast<int16_t *>(&entry.ValueOffset));
        } else {
            // Value is stored in another location, seek to that location and read it
            ifdFileStream.seekg(entry.ValueOffset);
            ifdFileStream.read(reinterpret_cast<char *>(&value), sizeof(int16_t));
        }
    }
    

    当然,以上只是一种可能的解决方案,具体问题具体分析,需要根据实际情况来确定。如果以上方法不能解决问题,我们可以通过各种日志、调试工具来定位问题所在,找到具体的原因并进行相应的调整。

    评论

报告相同问题?

问题事件

  • 创建了问题 4月9日

悬赏问题

  • ¥20 PDF元数据中的XMP媒体管理属性
  • ¥15 R语言中lasso回归报错
  • ¥15 网站突然不能访问了,上午还好好的
  • ¥15 有没有dl可以帮弄”我去图书馆”秒选道具和积分
  • ¥15 semrush,SEO,内嵌网站,api
  • ¥15 Stata:为什么reghdfe后的因变量没有被发现识别啊
  • ¥15 振荡电路,ADS仿真
  • ¥15 关于#c语言#的问题,请各位专家解答!
  • ¥15 这个如何解决详细步骤
  • ¥15 在微信h5支付申请中,别人给钱就能用我的软件,这个的所属行业是啥?