无法使用 FreeImage 将元数据添加到 JPEG 图像

Can't add a metadata to a JPEG image using FreeImage

我尝试将元数据添加到现有的 JPEG 文件并将图像保存在另一个文件中。我正在使用 Delphi 11 和 FreeImage(Delphi 包装器)。生成的图像与现有图像相同,没有添加元数据标签。完全没有错误。

这是重现问题的简单独立程序:

procedure AddTagArtistTest;
var
    fif      : FREE_IMAGE_FORMAT;
    dib      : PFIBITMAP;
    Tag      : PFITAG;
    TagValue : AnsiString;
    TagKey   : AnsiString;
    TagID    : WORD;
    Filename : String;
    Success  : Boolean;
begin
    Filename := 'F:\Images\ExistingImage.jpg'; // Already has metadata but no TAG_ARTIST
    dib      := nil;
    Success  := FALSE;
    try
        fif := FreeImage_GetFileTypeU(PChar(FileName), 0);
        if fif = FIF_UNKNOWN then
            fif := FreeImage_GetFIFFromFilenameU(PChar(FileName));
        if fif = FIF_UNKNOWN then
            Exit;
        if not FreeImage_FIFSupportsReading(fif) then
            Exit;
        dib    := FreeImage_LoadU(fif, PChar(Filename), 0);
        if dib = nil then
            Exit;
        Tag      := FreeImage_CreateTag();
        TagValue := 'FRANCOIS PIETTE';
        TagKey   := 'Artist';
        TagID    := 3B; // TAG_ARTIST;
        if not FreeImage_SetTagID(Tag, TagID) then
            Exit;
        if not FreeImage_SetTagKey(Tag, PAnsiChar(TagKey)) then
            Exit;
        if not FreeImage_SetTagType(Tag, FIDT_ASCII) then
            Exit;
        if not FreeImage_SetTagLength(Tag, Length(TagValue) + 1) then
            Exit;
        if not FreeImage_SetTagCount(Tag,  Length(TagValue) + 1) then
            Exit;
        if not FreeImage_SetTagValue(Tag, PAnsiChar(TagValue)) then
            Exit;
        if not FreeImage_SetMetadata(FIMD_EXIF_MAIN,
                                     dib,
                                     PAnsiChar(TagKey),
                                     Tag) then
            Exit;
        if not FreeImage_SaveU(FIF_JPEG,
                               dib,
                               PChar(ChangeFileExt(FileName, '_2.jpg')),
                               0) then
            Exit;
        Success := TRUE;
    finally
        if dib <> nil then
            FreeImage_Unload(dib);
        if Success then
            WriteLn('Success')
        else
            WriteLn('Failed');
    end;
end;

知道我做错了什么吗?

根据 the documentation, page 76, Table 13 不支持将 EXIF_MAIN 写入 JPEG - 只支持读取:

FIF_JPEG FIF_TIFF FIF_PNG FIF_GIF FIF_RAW FIF_JXR FIF_WEBP
0 = FIMD_COMMENTS R/W - R/W R/W - - -
1 = FIMD_EXIF_MAIN R R/W - - R R/W R
2 = FIMD_EXIF_EXIF R R - - R R/W R
3 = FIMD_EXIF_GPS R - - - R R/W R
4 = FIMD_EXIF_MAKERNOTE R - - - R R R
5 = FIMD_EXIF_INTEROP R - - - R R R
6 = FIMD_IPTC R/W R/W - - - R/W -
7 = FIMD_XMP R/W R/W R/W - - R/W R/W
8 = FIMD_GEOTIFF - R/W - - - - -
9 = FIMD_ANIMATION - - - R/W - - -
10 = FIMD_CUSTOM - - - - - - -
11 = FIMD_EXIF_RAW R/W - - - - - R/W

这意味着:如果您将其另存为 FIF_TIFF,您将获得一张包含新设置的元数据的图片。只需将您的代码更改为:

        if not FreeImage_SaveU(FIF_TIFF,
                               dib,
                               PChar(ChangeFileExt(FileName, '_2.tif')),
                               0) then

别忘了再次释放标签:

FreeImage_DeleteTag( Tag );

已使用 FreeImage 3.18.0 和 D7 成功测试。一个反例是使用 IPTC 或 XMP 而不是 EXIF,因为它们具有对 JPEG 图片的写入支持。