{"id":16440172,"url":"https://github.com/soypat/exif","last_synced_at":"2025-06-24T15:08:22.049Z","repository":{"id":152479934,"uuid":"621611395","full_name":"soypat/exif","owner":"soypat","description":"Dead simple exchangeable image file format tools for Go optimized for large image files using lazy loading.","archived":false,"fork":false,"pushed_at":"2023-04-26T01:13:24.000Z","size":165,"stargazers_count":22,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-04T14:04:46.999Z","etag":null,"topics":["exif","exiftool","go","golang","hyperspectral","image","jpeg","large-files","metadata","metadata-extraction","tiff"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/soypat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-03-31T02:42:06.000Z","updated_at":"2025-02-20T07:41:14.000Z","dependencies_parsed_at":null,"dependency_job_id":"8d40d0a3-ec24-4258-aa70-3eb39447caa8","html_url":"https://github.com/soypat/exif","commit_stats":{"total_commits":26,"total_committers":1,"mean_commits":26.0,"dds":0.0,"last_synced_commit":"1d67cace89bf46b24846aa41830599a31061e57c"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/soypat/exif","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soypat%2Fexif","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soypat%2Fexif/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soypat%2Fexif/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soypat%2Fexif/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/soypat","download_url":"https://codeload.github.com/soypat/exif/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soypat%2Fexif/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261700841,"owners_count":23196504,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["exif","exiftool","go","golang","hyperspectral","image","jpeg","large-files","metadata","metadata-extraction","tiff"],"created_at":"2024-10-11T09:11:20.893Z","updated_at":"2025-06-24T15:08:22.024Z","avatar_url":"https://github.com/soypat.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# exif\nExchangeable image file format tools for Go. \n\nThis library is at least 200 times faster for extracting EXIF data from a small \nimage when compared to [go-exif](https://github.com/dsoprea/go-exif) and can be up to\nthousands of times faster for images in the size of megabytes. See benchmarks below.\n\n- The root directory contains common EXIF functions and data types.\n- The `tiff` directory contains a TIFF image parser that uses lazy loading.\n    - TODO: Implement the `image.Image` interface using a cache for low memory requirement lazy loading\n- The `rational` directory contains signed and unsigned 64bit rational number types\n\n\nBenchmarks- comparisons with the popular go-exif library.\n- Small image: 15kB TIFF\n- Large image: 19.6MB TIFF\n\n```\ngoos: linux\ngoarch: amd64\npkg: github.com/soypat/exif\ncpu: 12th Gen Intel(R) Core(TM) i5-12400F\nBenchmarkThisPackage_SmallImage-12    \t  136064\t      8411 ns/op\t    2457 B/op\t      57 allocs/op\nBenchmarkDsoprea_SmallImage-12        \t     798\t   1650455 ns/op\t  659437 B/op\t   11252 allocs/op\nBenchmarkThisPackage_LargeImage-12    \t  127800\t      8593 ns/op\t    1977 B/op\t      50 allocs/op\nBenchmarkDsoprea_LargeImage-12        \t      52\t  23897506 ns/op\t123760580 B/op\t   11588 allocs/op\nPASS\ncoverage: 41.6% of statements\n```\n\u003cdetails\u003e\u003csummary\u003eBenchmark code\u003c/summary\u003e\n\nI have removed the following benchmark from this package since dsoprea's Go \npackage has two high severity security issues and github's dependabot was\nbothering me some. You are free to run it on your computer and compare with the\nbenchmarks under [`benchmarks_test.go`](./benchmarks_test.go) \n\n```go\npackage exif_test\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\tdsoprea \"github.com/dsoprea/go-exif/v3\"\n\texifcommon \"github.com/dsoprea/go-exif/v3/common\"\n)\n\nconst (\n\tsmallImageName = \"testdata/sample1.tiff\"\n)\n\nfunc BenchmarkDsoprea_SmallImage(b *testing.B) {\n\tfor i := 0; i \u003c b.N; i++ {\n\t\trawExif, err := dsoprea.SearchFileAndExtractExif(smallImageName)\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t\tmapping, _ := exifcommon.NewIfdMappingWithStandard()\n\t\tti := dsoprea.NewTagIndex()\n\t\t_, index, err := dsoprea.Collect(mapping, ti, rawExif)\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t\terr = index.RootIfd.EnumerateTagsRecursively(func(i *dsoprea.Ifd, ite *dsoprea.IfdTagEntry) error {\n\t\t\treturn nil\n\t\t})\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t}\n}\n```\n\n\u003c/details\u003e\n\n## Example\nExample of usage of this library. We read a single tag value for the `XResolution` tag\nand then print out all the Exif tags in the file under the Image File Directories. In this\ncase we only have IFD0.\n\n```go\n\tfp, err := os.Open(\"testdata/sample1.tiff\")\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer fp.Close()\n\tvar decoder exif.LazyDecoder\n\terr = decoder.Decode(fp)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Read a single tag from the decoded tags.\n\txResTag, err := decoder.GetTag(fp, 0, exifid.XResolution)\n\tif err != nil {\n\t\tpanic(\"compression tag not found\")\n\t}\n\t// One can also use the Rational, Float and Int methods to obtain \n\t// statically typed tag values. The Value method returns interface{} type.\n\tfmt.Printf(\"the x resolution is %v\", xResTag.Value())\n\n\t// Generate all tags of a certain constrained size using a callback.\n\tifds, err := decoder.MakeIFDs(fp, func(ifd, size int, id exif.ID) bool {\n\t\treturn size \u003c 1024 // Tags less than a kilobyte in size.\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfor _, ifd := range ifds {\n\t\tfmt.Printf(\"%s:\\n\", ifd.Group.String())\n\t\tfor _, tag := range ifd.Tags {\n\t\t\tfmt.Println(\"\\t\" + strings.Trim(tag.String(), \"\\x00\"))\n\t\t}\n\t}\n```\n\nOutputs:\n```\nthe x resolution is 2000000/10000\nIFD0:\n\tImageWidth (uint32): 1728\n\tImageHeight (uint32): 2376\n\tBitsPerSample (uint16): 1\n\tCompression (uint16): 4\n\tPhotometricInterpretation (uint16): 0\n\tFillOrder (uint16): 2\n\tDocumentName (string): Standard Input\n\tImageDescription (string): converted PBM file\n\tStripOffsets (unknown): 8\n\tOrientation (uint16): 1\n\tSamplesPerPixel (uint16): 1\n\tRowsPerStrip (uint32): 2376\n\tStripByteCounts (unknown): 18112\n\tXResolution (rational): 2000000/10000\n\tYResolution (rational): 2000000/10000\n\tPlanarConfiguration (uint16): 1\n\tResolutionUnit (uint16): 2\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoypat%2Fexif","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoypat%2Fexif","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoypat%2Fexif/lists"}