如何使用Golang设置DPI?

4
Golang的图像包在某种程度上非常方便,但是缺乏设置图像DPI的支持。我检查了生成文件的文件头“FF D8 FF DB”,看起来像是JPEG原始格式。据我所知,原始格式不像JFIF一样带有DPI。所以我的问题是,如何设置生成图像的DPI?或者如何将原始格式转换为JFIF,从中我知道可以编辑文件的特定位以设置DPI?以前我在应用程序中嵌入了AdvancedBatchConverter可执行文件,并使用以下代码解决了问题,但每次看到代码时都感到厌恶:exec.Command(fmt.Sprintf("%s/AdvancedBatchConverter/abc.exe", cwd), outputFile, "/jfif", fmt.Sprintf("/convert=%s", jfifFileName))
2个回答

1
我相信您正在寻找 exif 值 XResolution 和 YResolution。
我的理解是,本机 jpeg 编码器没有任何用于 exif 数据的选项。 https://github.com/dsoprea/go-exif 可以让您修改 exif 数据。
此外,我认为如果您首先将 jpeg 写入 bytes.Buffer 或类似的缓冲区,然后再附加 exif,您可以在内存中完成整个操作,而无需先刷新到磁盘。
希望这可以帮助您。

感谢您的回答。在我有空的时候,我会尝试您的方法,但这个想法听起来非常有前途。顺便说一下,这个库并不能像它的名字所显示的那样做到所有的功能。就在几天前,当我检查时,它只能解析exif信息。当我有更多的更新后,我会添加更多的评论。 - Simon
抱歉回复晚了。直到这个星期我才有时间进行验证。就记录而言,go-exif不是一个可行的包来添加exif信息。https://www.media.mit.edu/pia/Research/deepview/exif.html是一篇很好的文章,概述了应该设置哪些字节以将新的exif写入文件。 - Simon

1

github.com/dsoprea/go-exif/v2可以读取和写入exif数据。与其他包github.com/dsoprea/go-jpeg-image-structure一起使用,以下是将DPI(XResolution,YResolution)写入图像的代码示例。

import( 
    exif2 "github.com/dsoprea/go-exif/v2"
    exifcommon "github.com/dsoprea/go-exif/v2/common"
    jpegstructure "github.com/dsoprea/go-jpeg-image-structure"
)
func SetExifData(filepath string) error {
jmp := jpegstructure.NewJpegMediaParser()

intfc, err := jmp.ParseFile(filepath)
log.PanicIf(err)

sl := intfc.(*jpegstructure.SegmentList)

// Make sure we don't start out with EXIF data.
wasDropped, err := sl.DropExif()
log.PanicIf(err)

if wasDropped != true {
    fmt.Printf("Expected the EXIF segment to be dropped, but it wasn't.")
}

im := exif2.NewIfdMapping()

err = exif2.LoadStandardIfds(im)
log.PanicIf(err)

ti := exif2.NewTagIndex()
rootIb := exif2.NewIfdBuilder(im, ti, exifcommon.IfdPathStandard, exifcommon.EncodeDefaultByteOrder)

err = rootIb.AddStandardWithName("XResolution", []exifcommon.Rational{{Numerator: uint32(96), Denominator: uint32(1)}})
log.PanicIf(err)

err = rootIb.AddStandardWithName("YResolution", []exifcommon.Rational{{Numerator: uint32(96), Denominator: uint32(1)}})
log.PanicIf(err)

err = sl.SetExif(rootIb)
log.PanicIf(err)

b := new(bytes.Buffer)

err = sl.Write(b)
log.PanicIf(err)

if err := ioutil.WriteFile(filepath, b.Bytes(), 0644); err != nil {
    fmt.Printf("write file err: %v", err)
}
return nil
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接