代码之家  ›  专栏  ›  技术社区  ›  fpiette

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

  •  0
  • fpiette  · 技术社区  · 4 年前

    我尝试将元数据添加到现有的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    := $013B; // 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;
    

    你知道我做错了什么吗?

    0 回复  |  直到 4 年前
        1
  •  3
  •   AmigoJack    4 年前

    根据 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_exix_kernote R - - - R R R
    5=FIMD_exix_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_exix_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图片的写入支持。