1/* 2 * GO interface to libheif 3 * Copyright (c) 2018 struktur AG, Joachim Bauch <bauch@struktur.de> 4 * 5 * This file is part of heif, an example application using libheif. 6 * 7 * heif is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * heif is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with heif. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21package heif 22 23import ( 24 "fmt" 25 "image" 26 "io/ioutil" 27 "os" 28 "path" 29 "testing" 30) 31 32func TestGetVersion(t *testing.T) { 33 version := GetVersion() 34 if version == "" { 35 t.Fatal("Version is missing") 36 } 37} 38 39type decodeTest struct { 40 colorspace Colorspace 41 chroma Chroma 42} 43 44func CheckHeifImage(t *testing.T, handle *ImageHandle, thumbnail bool) { 45 handle.GetWidth() 46 handle.GetHeight() 47 handle.HasAlphaChannel() 48 handle.HasDepthImage() 49 count := handle.GetNumberOfDepthImages() 50 if ids := handle.GetListOfDepthImageIDs(); len(ids) != count { 51 t.Errorf("Expected %d depth image ids, got %d", count, len(ids)) 52 } 53 if !thumbnail { 54 count = handle.GetNumberOfThumbnails() 55 ids := handle.GetListOfThumbnailIDs() 56 if len(ids) != count { 57 t.Errorf("Expected %d thumbnail image ids, got %d", count, len(ids)) 58 } 59 for _, id := range ids { 60 if thumb, err := handle.GetThumbnail(id); err != nil { 61 t.Errorf("Could not get thumbnail %d: %s", id, err) 62 } else { 63 CheckHeifImage(t, thumb, true) 64 } 65 } 66 } 67 68 if img, err := handle.DecodeImage(ColorspaceUndefined, ChromaUndefined, nil); err != nil { 69 t.Errorf("Could not decode image: %s", err) 70 } else { 71 img.GetColorspace() 72 img.GetChromaFormat() 73 } 74 75 decodeTests := []decodeTest{ 76 decodeTest{ColorspaceYCbCr, Chroma420}, 77 decodeTest{ColorspaceYCbCr, Chroma422}, 78 decodeTest{ColorspaceYCbCr, Chroma444}, 79 decodeTest{ColorspaceRGB, Chroma444}, 80 decodeTest{ColorspaceRGB, ChromaInterleavedRGB}, 81 decodeTest{ColorspaceRGB, ChromaInterleavedRGBA}, 82 decodeTest{ColorspaceRGB, ChromaInterleavedRRGGBB_BE}, 83 decodeTest{ColorspaceRGB, ChromaInterleavedRRGGBBAA_BE}, 84 } 85 for _, test := range decodeTests { 86 if img, err := handle.DecodeImage(test.colorspace, test.chroma, nil); err != nil { 87 t.Errorf("Could not decode image with %v / %v: %s", test.colorspace, test.chroma, err) 88 } else { 89 img.GetColorspace() 90 img.GetChromaFormat() 91 92 if _, err := img.GetImage(); err != nil { 93 t.Errorf("Could not get image with %v /%v: %s", test.colorspace, test.chroma, err) 94 continue 95 } 96 } 97 } 98} 99 100func CheckHeifFile(t *testing.T, ctx *Context) { 101 if count := ctx.GetNumberOfTopLevelImages(); count != 2 { 102 t.Errorf("Expected %d top level images, got %d", 2, count) 103 } 104 if ids := ctx.GetListOfTopLevelImageIDs(); len(ids) != 2 { 105 t.Errorf("Expected %d top level image ids, got %+v", 2, ids) 106 } 107 if _, err := ctx.GetPrimaryImageID(); err != nil { 108 t.Errorf("Expected a primary image, got %s", err) 109 } 110 if handle, err := ctx.GetPrimaryImageHandle(); err != nil { 111 t.Errorf("Could not get primary image handle: %s", err) 112 } else { 113 if !handle.IsPrimaryImage() { 114 t.Error("Expected primary image") 115 } 116 CheckHeifImage(t, handle, false) 117 } 118} 119 120func TestReadFromFile(t *testing.T) { 121 ctx, err := NewContext() 122 if err != nil { 123 t.Fatalf("Can't create context: %s", err) 124 } 125 126 filename := path.Join("..", "..", "examples", "example.heic") 127 if err := ctx.ReadFromFile(filename); err != nil { 128 t.Fatalf("Can't read from %s: %s", filename, err) 129 } 130 131 CheckHeifFile(t, ctx) 132} 133 134func TestReadFromMemory(t *testing.T) { 135 ctx, err := NewContext() 136 if err != nil { 137 t.Fatalf("Can't create context: %s", err) 138 } 139 140 filename := path.Join("..", "..", "examples", "example.heic") 141 data, err := ioutil.ReadFile(filename) 142 if err != nil { 143 t.Fatalf("Can't read file %s: %s", filename, err) 144 } 145 if err := ctx.ReadFromMemory(data); err != nil { 146 t.Fatalf("Can't read from memory: %s", err) 147 } 148 data = nil // Make sure future processing works if "data" is GC'd 149 150 CheckHeifFile(t, ctx) 151} 152 153func TestReadImage(t *testing.T) { 154 filename := path.Join("..", "..", "examples", "example.heic") 155 fp, err := os.Open(filename) 156 if err != nil { 157 t.Fatalf("Could not open %s: %s", filename, err) 158 } 159 defer fp.Close() 160 161 config, format1, err := image.DecodeConfig(fp) 162 if err != nil { 163 t.Fatalf("Could not load image config from %s: %s", filename, err) 164 } 165 if format1 != "heif" { 166 t.Errorf("Expected format heif, got %s", format1) 167 } 168 if _, err := fp.Seek(0, 0); err != nil { 169 t.Fatalf("Could not seek to start of %s: %s", filename, err) 170 } 171 172 img, format2, err := image.Decode(fp) 173 if err != nil { 174 t.Fatalf("Could not load image from %s: %s", filename, err) 175 } 176 if format2 != "heif" { 177 t.Errorf("Expected format heif, got %s", format2) 178 } 179 180 r := img.Bounds() 181 if config.Width != (r.Max.X-r.Min.X) || config.Height != (r.Max.Y-r.Min.Y) { 182 fmt.Printf("Image size %+v does not match config %+v\n", r, config) 183 } 184} 185