package bimg import ( "io/ioutil" "os" "path" "testing" ) func TestSize(t *testing.T) { files := []struct { name string width int height int }{ {"test.jpg", 1680, 1050}, {"test.png", 400, 300}, {"test.webp", 550, 368}, } for _, file := range files { size, err := Size(readFile(file.name)) if err != nil { t.Fatalf("Cannot read the image: %#v", err) } if size.Width != file.width || size.Height != file.height { t.Fatalf("Unexpected image size: %dx%d", size.Width, size.Height) } } } func TestMetadata(t *testing.T) { files := []struct { name string format string orientation int alpha bool profile bool space string }{ {"test.jpg", "jpeg", 0, false, false, "srgb"}, {"test_icc_prophoto.jpg", "jpeg", 0, false, true, "srgb"}, {"test.png", "png", 0, true, false, "srgb"}, {"test.webp", "webp", 0, false, false, "srgb"}, } for _, file := range files { metadata, err := Metadata(readFile(file.name)) if err != nil { t.Fatalf("Cannot read the image: %s -> %s", file.name, err) } if metadata.Type != file.format { t.Fatalf("Unexpected image format: %s", file.format) } if metadata.Orientation != file.orientation { t.Fatalf("Unexpected image orientation: %d != %d", metadata.Orientation, file.orientation) } if metadata.Alpha != file.alpha { t.Fatalf("Unexpected image alpha: %t != %t", metadata.Alpha, file.alpha) } if metadata.Profile != file.profile { t.Fatalf("Unexpected image profile: %t != %t", metadata.Profile, file.profile) } if metadata.Space != file.space { t.Fatalf("Unexpected image profile: %t != %t", metadata.Profile, file.profile) } } } func TestImageInterpretation(t *testing.T) { files := []struct { name string interpretation Interpretation }{ {"test.jpg", InterpretationSRGB}, {"test.png", InterpretationSRGB}, {"test.webp", InterpretationSRGB}, } for _, file := range files { interpretation, err := ImageInterpretation(readFile(file.name)) if err != nil { t.Fatalf("Cannot read the image: %s -> %s", file.name, err) } if interpretation != file.interpretation { t.Fatalf("Unexpected image interpretation") } } } func TestEXIF(t *testing.T) { if VipsMajorVersion <= 8 && VipsMinorVersion < 10 { t.Skip("Skip test in libvips < 8.10") return } files := map[string]EXIF { "test.jpg": {}, "exif/Landscape_1.jpg": { Orientation: 1, XResolution: "72/1", YResolution: "72/1", ResolutionUnit: 2, YCbCrPositioning: 1, ExifVersion: "Exif Version 2.1", ColorSpace: 65535, }, "test_exif.jpg": { Make: "Jolla", Model: "Jolla", XResolution: "72/1", YResolution: "72/1", ResolutionUnit: 2, Orientation: 1, Datetime: "2014:09:21 16:00:56", ExposureTime: "1/25", FNumber: "12/5", ISOSpeedRatings: 320, ExifVersion: "Exif Version 2.3", DateTimeOriginal: "2014:09:21 16:00:56", ShutterSpeedValue: "205447286/44240665", ApertureValue: "334328577/132351334", ExposureBiasValue: "0/1", MeteringMode: 1, Flash: 0, FocalLength: "4/1", WhiteBalance: 1, ColorSpace: 65535, }, "test_exif_canon.jpg": { Make: "Canon", Model: "Canon EOS 40D", Orientation: 1, XResolution: "72/1", YResolution: "72/1", ResolutionUnit: 2, Software: "GIMP 2.4.5", Datetime: "2008:07:31 10:38:11", YCbCrPositioning: 2, Compression: 6, ExposureTime: "1/160", FNumber: "71/10", ExposureProgram: 1, ISOSpeedRatings: 100, ExifVersion: "Exif Version 2.21", DateTimeOriginal: "2008:05:30 15:56:01", DateTimeDigitized: "2008:05:30 15:56:01", ComponentsConfiguration: "Y Cb Cr -", ShutterSpeedValue: "483328/65536", ApertureValue: "368640/65536", ExposureBiasValue: "0/1", MeteringMode: 5, Flash: 9, FocalLength: "135/1", SubSecTimeOriginal: "00", SubSecTimeDigitized: "00", ColorSpace: 1, PixelXDimension: 100, PixelYDimension: 68, ExposureMode: 1, WhiteBalance: 0, SceneCaptureType: 0, }, "test_exif_full.jpg": { Make: "Apple", Model: "iPhone XS", Orientation: 6, XResolution: "72/1", YResolution: "72/1", ResolutionUnit: 2, Software: "13.3.1", Datetime: "2020:07:28 19:18:49", YCbCrPositioning: 1, Compression: 6, ExposureTime: "1/835", FNumber: "9/5", ExposureProgram: 2, ISOSpeedRatings: 25, ExifVersion: "Unknown Exif Version", DateTimeOriginal: "2020:07:28 19:18:49", DateTimeDigitized: "2020:07:28 19:18:49", ComponentsConfiguration: "Y Cb Cr -", ShutterSpeedValue: "77515/7986", ApertureValue: "54823/32325", BrightnessValue: "77160/8623", ExposureBiasValue: "0/1", MeteringMode: 5, Flash: 16, FocalLength: "17/4", SubjectArea: "2013 1511 2217 1330", MakerNote: "1110 bytes undefined data", SubSecTimeOriginal: "777", SubSecTimeDigitized: "777", ColorSpace: 65535, PixelXDimension: 4032, PixelYDimension: 3024, SensingMethod: 2, SceneType: "Directly photographed", ExposureMode: 0, WhiteBalance: 0, FocalLengthIn35mmFilm: 26, SceneCaptureType: 0, GPSLatitudeRef: "N", GPSLatitude: "55/1 43/1 5287/100", GPSLongitudeRef: "E", GPSLongitude: "37/1 35/1 5571/100", GPSAltitudeRef: "Sea level", GPSAltitude: "90514/693", GPSSpeedRef: "K", GPSSpeed: "114272/41081", GPSImgDirectionRef: "M", GPSImgDirection: "192127/921", GPSDestBearingRef: "M", GPSDestBearing: "192127/921", GPSDateStamp: "2020:07:28", }, } for name, file := range files { metadata, err := Metadata(readFile(name)) if err != nil { t.Fatalf("Cannot read the image: %s -> %s", name, err) } if metadata.EXIF.Make != file.Make { t.Fatalf("Unexpected image exif Make: %s != %s", metadata.EXIF.Make, file.Make) } if metadata.EXIF.Model != file.Model { t.Fatalf("Unexpected image exif Model: %s != %s", metadata.EXIF.Model, file.Model) } if metadata.EXIF.Orientation != file.Orientation { t.Fatalf("Unexpected image exif Orientation: %d != %d", metadata.EXIF.Orientation, file.Orientation) } if metadata.EXIF.XResolution != file.XResolution { t.Fatalf("Unexpected image exif XResolution: %s != %s", metadata.EXIF.XResolution, file.XResolution) } if metadata.EXIF.YResolution != file.YResolution { t.Fatalf("Unexpected image exif YResolution: %s != %s", metadata.EXIF.YResolution, file.YResolution) } if metadata.EXIF.ResolutionUnit != file.ResolutionUnit { t.Fatalf("Unexpected image exif ResolutionUnit: %d != %d", metadata.EXIF.ResolutionUnit, file.ResolutionUnit) } if metadata.EXIF.Software != file.Software { t.Fatalf("Unexpected image exif Software: %s != %s", metadata.EXIF.Software, file.Software) } if metadata.EXIF.Datetime != file.Datetime { t.Fatalf("Unexpected image exif Datetime: %s != %s", metadata.EXIF.Datetime, file.Datetime) } if metadata.EXIF.YCbCrPositioning != file.YCbCrPositioning { t.Fatalf("Unexpected image exif YCbCrPositioning: %d != %d", metadata.EXIF.YCbCrPositioning, file.YCbCrPositioning) } if metadata.EXIF.Compression != file.Compression { t.Fatalf("Unexpected image exif Compression: %d != %d", metadata.EXIF.Compression, file.Compression) } if metadata.EXIF.ExposureTime != file.ExposureTime { t.Fatalf("Unexpected image exif ExposureTime: %s != %s", metadata.EXIF.ExposureTime, file.ExposureTime) } if metadata.EXIF.FNumber != file.FNumber { t.Fatalf("Unexpected image exif FNumber: %s != %s", metadata.EXIF.FNumber, file.FNumber) } if metadata.EXIF.ExposureProgram != file.ExposureProgram { t.Fatalf("Unexpected image exif ExposureProgram: %d != %d", metadata.EXIF.ExposureProgram, file.ExposureProgram) } if metadata.EXIF.ISOSpeedRatings != file.ISOSpeedRatings { t.Fatalf("Unexpected image exif ISOSpeedRatings: %d != %d", metadata.EXIF.ISOSpeedRatings, file.ISOSpeedRatings) } if metadata.EXIF.ExifVersion != file.ExifVersion { t.Fatalf("Unexpected image exif ExifVersion: %s != %s", metadata.EXIF.ExifVersion, file.ExifVersion) } if metadata.EXIF.DateTimeOriginal != file.DateTimeOriginal { t.Fatalf("Unexpected image exif DateTimeOriginal: %s != %s", metadata.EXIF.DateTimeOriginal, file.DateTimeOriginal) } if metadata.EXIF.DateTimeDigitized != file.DateTimeDigitized { t.Fatalf("Unexpected image exif DateTimeDigitized: %s != %s", metadata.EXIF.DateTimeDigitized, file.DateTimeDigitized) } if metadata.EXIF.ComponentsConfiguration != file.ComponentsConfiguration { t.Fatalf("Unexpected image exif ComponentsConfiguration: %s != %s", metadata.EXIF.ComponentsConfiguration, file.ComponentsConfiguration) } if metadata.EXIF.ShutterSpeedValue != file.ShutterSpeedValue { t.Fatalf("Unexpected image exif ShutterSpeedValue: %s != %s", metadata.EXIF.ShutterSpeedValue, file.ShutterSpeedValue) } if metadata.EXIF.ApertureValue != file.ApertureValue { t.Fatalf("Unexpected image exif ApertureValue: %s != %s", metadata.EXIF.ApertureValue, file.ApertureValue) } if metadata.EXIF.BrightnessValue != file.BrightnessValue { t.Fatalf("Unexpected image exif BrightnessValue: %s != %s", metadata.EXIF.BrightnessValue, file.BrightnessValue) } if metadata.EXIF.ExposureBiasValue != file.ExposureBiasValue { t.Fatalf("Unexpected image exif ExposureBiasValue: %s != %s", metadata.EXIF.ExposureBiasValue, file.ExposureBiasValue) } if metadata.EXIF.MeteringMode != file.MeteringMode { t.Fatalf("Unexpected image exif MeteringMode: %d != %d", metadata.EXIF.MeteringMode, file.MeteringMode) } if metadata.EXIF.Flash != file.Flash { t.Fatalf("Unexpected image exif Flash: %d != %d", metadata.EXIF.Flash, file.Flash) } if metadata.EXIF.FocalLength != file.FocalLength { t.Fatalf("Unexpected image exif FocalLength: %s != %s", metadata.EXIF.FocalLength, file.FocalLength) } if metadata.EXIF.SubjectArea != file.SubjectArea { t.Fatalf("Unexpected image exif SubjectArea: %s != %s", metadata.EXIF.SubjectArea, file.SubjectArea) } if metadata.EXIF.MakerNote != file.MakerNote { t.Fatalf("Unexpected image exif MakerNote: %s != %s", metadata.EXIF.MakerNote, file.MakerNote) } if metadata.EXIF.SubSecTimeOriginal != file.SubSecTimeOriginal { t.Fatalf("Unexpected image exif SubSecTimeOriginal: %s != %s", metadata.EXIF.SubSecTimeOriginal, file.SubSecTimeOriginal) } if metadata.EXIF.SubSecTimeDigitized != file.SubSecTimeDigitized { t.Fatalf("Unexpected image exif SubSecTimeDigitized: %s != %s", metadata.EXIF.SubSecTimeDigitized, file.SubSecTimeDigitized) } if metadata.EXIF.ColorSpace != file.ColorSpace { t.Fatalf("Unexpected image exif ColorSpace: %d != %d", metadata.EXIF.ColorSpace, file.ColorSpace) } if metadata.EXIF.PixelXDimension != file.PixelXDimension { t.Fatalf("Unexpected image exif PixelXDimension: %d != %d", metadata.EXIF.PixelXDimension, file.PixelXDimension) } if metadata.EXIF.PixelYDimension != file.PixelYDimension { t.Fatalf("Unexpected image exif PixelYDimension: %d != %d", metadata.EXIF.PixelYDimension, file.PixelYDimension) } if metadata.EXIF.SensingMethod != file.SensingMethod { t.Fatalf("Unexpected image exif SensingMethod: %d != %d", metadata.EXIF.SensingMethod, file.SensingMethod) } if metadata.EXIF.SceneType != file.SceneType { t.Fatalf("Unexpected image exif SceneType: %s != %s", metadata.EXIF.SceneType, file.SceneType) } if metadata.EXIF.ExposureMode != file.ExposureMode { t.Fatalf("Unexpected image exif ExposureMode: %d != %d", metadata.EXIF.ExposureMode, file.ExposureMode) } if metadata.EXIF.WhiteBalance != file.WhiteBalance { t.Fatalf("Unexpected image exif WhiteBalance: %d != %d", metadata.EXIF.WhiteBalance, file.WhiteBalance) } if metadata.EXIF.FocalLengthIn35mmFilm != file.FocalLengthIn35mmFilm { t.Fatalf("Unexpected image exif FocalLengthIn35mmFilm: %d != %d", metadata.EXIF.FocalLengthIn35mmFilm, file.FocalLengthIn35mmFilm) } if metadata.EXIF.SceneCaptureType != file.SceneCaptureType { t.Fatalf("Unexpected image exif SceneCaptureType: %d != %d", metadata.EXIF.SceneCaptureType, file.SceneCaptureType) } if metadata.EXIF.GPSLongitudeRef != file.GPSLongitudeRef { t.Fatalf("Unexpected image exif GPSLongitudeRef: %s != %s", metadata.EXIF.GPSLongitudeRef, file.GPSLongitudeRef) } if metadata.EXIF.GPSLongitude != file.GPSLongitude { t.Fatalf("Unexpected image exif GPSLongitude: %s != %s", metadata.EXIF.GPSLongitude, file.GPSLongitude) } if metadata.EXIF.GPSAltitudeRef != file.GPSAltitudeRef { t.Fatalf("Unexpected image exif GPSAltitudeRef: %s != %s", metadata.EXIF.GPSAltitudeRef, file.GPSAltitudeRef) } if metadata.EXIF.GPSAltitude != file.GPSAltitude { t.Fatalf("Unexpected image exif GPSAltitude: %s != %s", metadata.EXIF.GPSAltitude, file.GPSAltitude) } if metadata.EXIF.GPSSpeedRef != file.GPSSpeedRef { t.Fatalf("Unexpected image exif GPSSpeedRef: %s != %s", metadata.EXIF.GPSSpeedRef, file.GPSSpeedRef) } if metadata.EXIF.GPSSpeed != file.GPSSpeed { t.Fatalf("Unexpected image exif GPSSpeed: %s != %s", metadata.EXIF.GPSSpeed, file.GPSSpeed) } if metadata.EXIF.GPSImgDirectionRef != file.GPSImgDirectionRef { t.Fatalf("Unexpected image exif GPSImgDirectionRef: %s != %s", metadata.EXIF.GPSImgDirectionRef, file.GPSImgDirectionRef) } if metadata.EXIF.GPSImgDirection != file.GPSImgDirection { t.Fatalf("Unexpected image exif GPSImgDirection: %s != %s", metadata.EXIF.GPSImgDirection, file.GPSImgDirection) } if metadata.EXIF.GPSDestBearingRef != file.GPSDestBearingRef { t.Fatalf("Unexpected image exif GPSDestBearingRef: %s != %s", metadata.EXIF.GPSDestBearingRef, file.GPSDestBearingRef) } if metadata.EXIF.GPSDestBearing != file.GPSDestBearing { t.Fatalf("Unexpected image exif GPSDestBearing: %s != %s", metadata.EXIF.GPSDestBearing, file.GPSDestBearing) } if metadata.EXIF.GPSDateStamp != file.GPSDateStamp { t.Fatalf("Unexpected image exif GPSDateStamp: %s != %s", metadata.EXIF.GPSDateStamp, file.GPSDateStamp) } } } func TestColourspaceIsSupported(t *testing.T) { files := []struct { name string }{ {"test.jpg"}, {"test.png"}, {"test.webp"}, } for _, file := range files { supported, err := ColourspaceIsSupported(readFile(file.name)) if err != nil { t.Fatalf("Cannot read the image: %s -> %s", file.name, err) } if supported != true { t.Fatalf("Unsupported image colourspace") } } supported, err := initImage("test.jpg").ColourspaceIsSupported() if err != nil { t.Errorf("Cannot process the image: %#v", err) } if supported != true { t.Errorf("Non-supported colourspace") } } func readFile(file string) []byte { data, _ := os.Open(path.Join("testdata", file)) buf, _ := ioutil.ReadAll(data) return buf }