diff --git a/resources/gif-animated.GIF_Animated-macos-12.golden.gif b/resources/gif-animated.GIF_Animated-macos-12.golden.gif new file mode 100644 index 00000000..878a88b5 Binary files /dev/null and b/resources/gif-animated.GIF_Animated-macos-12.golden.gif differ diff --git a/resources/gif-animated.GIF_Animated_ExportNative-macos-12.golden.gif b/resources/gif-animated.GIF_Animated_ExportNative-macos-12.golden.gif new file mode 100644 index 00000000..d9c4e874 Binary files /dev/null and b/resources/gif-animated.GIF_Animated_ExportNative-macos-12.golden.gif differ diff --git a/resources/gif-animated.GIF_Animated_Resize-macos-12.golden.gif b/resources/gif-animated.GIF_Animated_Resize-macos-12.golden.gif new file mode 100644 index 00000000..708f040e Binary files /dev/null and b/resources/gif-animated.GIF_Animated_Resize-macos-12.golden.gif differ diff --git a/resources/gif-animated.GIF_Animated_Rotate270-macos-12.golden.gif b/resources/gif-animated.GIF_Animated_Rotate270-macos-12.golden.gif new file mode 100644 index 00000000..210331fd Binary files /dev/null and b/resources/gif-animated.GIF_Animated_Rotate270-macos-12.golden.gif differ diff --git a/resources/gif-animated.GIF_Animated_Rotate90-macos-12.golden.gif b/resources/gif-animated.GIF_Animated_Rotate90-macos-12.golden.gif new file mode 100644 index 00000000..a600a3c5 Binary files /dev/null and b/resources/gif-animated.GIF_Animated_Rotate90-macos-12.golden.gif differ diff --git a/resources/gif-animated.GIF_Animated_to_WebP-macos-12.golden.webp b/resources/gif-animated.GIF_Animated_to_WebP-macos-12.golden.webp new file mode 100644 index 00000000..aa9205ac Binary files /dev/null and b/resources/gif-animated.GIF_Animated_to_WebP-macos-12.golden.webp differ diff --git a/vips/conversion.c b/vips/conversion.c index bf7a1f7a..ca90c83e 100644 --- a/vips/conversion.c +++ b/vips/conversion.c @@ -207,3 +207,7 @@ int arrayjoin(VipsImage **in, VipsImage **out, int n, int across) { int replicate(VipsImage *in, VipsImage **out, int across, int down) { return vips_replicate(in, out, across, down, NULL); } + +int grid(VipsImage *in, VipsImage **out, int tileHeight, int across, int down){ + return vips_grid(in, out, tileHeight, across, down, NULL); +} diff --git a/vips/conversion.go b/vips/conversion.go index 445bae19..fb542b94 100644 --- a/vips/conversion.go +++ b/vips/conversion.go @@ -416,3 +416,14 @@ func vipsReplicate(in *C.VipsImage, across int, down int) (*C.VipsImage, error) } return out, nil } + +// https://www.libvips.org/API/current/libvips-conversion.html#vips-grid +func vipsGrid(in *C.VipsImage, tileHeight, across, down int) (*C.VipsImage, error) { + incOpCounter("grid") + var out *C.VipsImage + + if err := C.grid(in, &out, C.int(tileHeight), C.int(across), C.int(down)); err != 0 { + return nil, handleImageError(out) + } + return out, nil +} diff --git a/vips/conversion.h b/vips/conversion.h index b0f3770b..e5ad1c16 100644 --- a/vips/conversion.h +++ b/vips/conversion.h @@ -50,3 +50,5 @@ int arrayjoin(VipsImage **in, VipsImage **out, int n, int across); int is_16bit(VipsInterpretation interpretation); int replicate(VipsImage *in, VipsImage **out, int across, int down); + +int grid(VipsImage *in, VipsImage **out, int tileHeight, int across, int down); diff --git a/vips/error.go b/vips/error.go index 08eb41e7..51b5a0e5 100644 --- a/vips/error.go +++ b/vips/error.go @@ -12,7 +12,8 @@ import ( var ( // ErrUnsupportedImageFormat when image type is unsupported - ErrUnsupportedImageFormat = errors.New("unsupported image format") + ErrUnsupportedImageFormat = errors.New("unsupported image format") + ErrUnsupportedMultiPageOperation = errors.New("unsupported operation for multi-page image") ) func handleImageError(out *C.VipsImage) error { diff --git a/vips/header.c b/vips/header.c index 8e83548d..110d88d8 100644 --- a/vips/header.c +++ b/vips/header.c @@ -50,11 +50,26 @@ void set_meta_orientation(VipsImage *in, int orientation) { vips_image_set_int(in, VIPS_META_ORIENTATION, orientation); } -//https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-n-pages -int get_image_get_n_pages(VipsImage *in) { - int page = 0; - page = vips_image_get_n_pages(in); - return page; +// https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-n-pages +int get_image_n_pages(VipsImage *in) { + int n_pages = 0; + n_pages = vips_image_get_n_pages(in); + return n_pages; +} + +void set_image_n_pages(VipsImage *in, int n_pages) { + vips_image_set_int(in, VIPS_META_N_PAGES, n_pages); +} + +// https://www.libvips.org/API/current/libvips-header.html#vips-image-get-page-height +int get_page_height(VipsImage *in) { + int page_height = 0; + page_height = vips_image_get_page_height(in); + return page_height; +} + +void set_page_height(VipsImage *in, int height) { + vips_image_set_int(in, VIPS_META_PAGE_HEIGHT, height); } int get_meta_loader(const VipsImage *in, const char **out) { diff --git a/vips/header.go b/vips/header.go index d3f69e0f..3daf925e 100644 --- a/vips/header.go +++ b/vips/header.go @@ -52,8 +52,20 @@ func vipsSetMetaOrientation(in *C.VipsImage, orientation int) { C.set_meta_orientation(in, C.int(orientation)) } -func vipsImageGetPages(in *C.VipsImage) int { - return int(C.get_image_get_n_pages(in)) +func vipsGetImageNPages(in *C.VipsImage) int { + return int(C.get_image_n_pages(in)) +} + +func vipsSetImageNPages(in *C.VipsImage, pages int) { + C.set_image_n_pages(in, C.int(pages)) +} + +func vipsGetPageHeight(in *C.VipsImage) int { + return int(C.get_page_height(in)) +} + +func vipsSetPageHeight(in *C.VipsImage, height int) { + C.set_page_height(in, C.int(height)) } func vipsImageGetMetaLoader(in *C.VipsImage) (string, bool) { diff --git a/vips/header.h b/vips/header.h index 3d70a47d..127292ff 100644 --- a/vips/header.h +++ b/vips/header.h @@ -15,5 +15,8 @@ void remove_metadata(VipsImage *in); int get_meta_orientation(VipsImage *in); void remove_meta_orientation(VipsImage *in); void set_meta_orientation(VipsImage *in, int orientation); -int get_image_get_n_pages(VipsImage *in); +int get_image_n_pages(VipsImage *in); +void set_image_n_pages(VipsImage *in, int n_pages); +int get_page_height(VipsImage *in); +void set_page_height(VipsImage *in, int height); int get_meta_loader(const VipsImage *in, const char **out); diff --git a/vips/image.go b/vips/image.go index 384a6a6e..82358a8c 100644 --- a/vips/image.go +++ b/vips/image.go @@ -41,6 +41,7 @@ type ImageMetadata struct { Height int Colorspace Interpretation Orientation int + Pages int } type Parameter struct { @@ -339,13 +340,18 @@ func NewImageFromReader(r io.Reader) (*ImageRef, error) { // NewImageFromFile loads an image from file and creates a new ImageRef func NewImageFromFile(file string) (*ImageRef, error) { + return LoadImageFromFile(file, nil) +} + +// LoadImageFromFile loads an image from file and creates a new ImageRef +func LoadImageFromFile(file string, params *ImportParams) (*ImageRef, error) { buf, err := ioutil.ReadFile(file) if err != nil { return nil, err } - govipsLog("govips", LogLevelDebug, fmt.Sprintf("creating imageref from file %s", file)) - return NewImageFromBuffer(buf) + govipsLog("govips", LogLevelDebug, fmt.Sprintf("creating imageRef from file %s", file)) + return LoadImageFromBuffer(buf, params) } // NewImageFromBuffer loads an image buffer and creates a new Image @@ -368,7 +374,7 @@ func LoadImageFromBuffer(buf []byte, params *ImportParams) (*ImageRef, error) { ref := newImageRef(vipsImage, format, buf) - govipsLog("govips", LogLevelDebug, fmt.Sprintf("created imageref %p", ref)) + govipsLog("govips", LogLevelDebug, fmt.Sprintf("created imageRef %p", ref)) return ref, nil } @@ -435,9 +441,12 @@ func NewThumbnailWithSizeFromBuffer(buf []byte, width, height int, crop Interest // Metadata returns the metadata (ImageMetadata struct) of the associated ImageRef func (r *ImageRef) Metadata() *ImageMetadata { return &ImageMetadata{ - Format: r.Format(), - Width: r.Width(), - Height: r.Height(), + Format: r.Format(), + Width: r.Width(), + Height: r.Height(), + Orientation: r.Orientation(), + Colorspace: r.ColorSpace(), + Pages: r.Pages(), } } @@ -542,11 +551,16 @@ func (r *ImageRef) HasAlpha() bool { return vipsHasAlpha(r.image) } -// GetOrientation returns the orientation number as it appears in the EXIF, if present -func (r *ImageRef) GetOrientation() int { +// Orientation returns the orientation number as it appears in the EXIF, if present +func (r *ImageRef) Orientation() int { return vipsGetMetaOrientation(r.image) } +// Deprecated: use Orientation() instead +func (r *ImageRef) GetOrientation() int { + return r.Orientation() +} + // SetOrientation sets the orientation in the EXIF header of the associated image. func (r *ImageRef) SetOrientation(orientation int) error { out, err := vipsCopyImage(r.image) @@ -618,19 +632,54 @@ func (r *ImageRef) IsColorSpaceSupported() bool { return vipsIsColorSpaceSupported(r.image) } -func (r *ImageRef) newMetadata(format ImageType) *ImageMetadata { - return &ImageMetadata{ - Format: format, - Width: r.Width(), - Height: r.Height(), - Colorspace: r.ColorSpace(), - Orientation: r.GetOrientation(), - } +// Pages returns the number of pages in the Image +// For animated images this corresponds to the number of frames +func (r *ImageRef) Pages() int { + return vipsGetImageNPages(r.image) } -// GetPages returns the number of Image +// Deprecated: use Pages() instead func (r *ImageRef) GetPages() int { - return vipsImageGetPages(r.image) + return r.Pages() +} + +// SetPages sets the number of pages in the Image +// For animated images this corresponds to the number of frames +func (r *ImageRef) SetPages(pages int) error { + out, err := vipsCopyImage(r.image) + if err != nil { + return err + } + + vipsSetImageNPages(r.image, pages) + + r.setImage(out) + return nil +} + +// PageHeight return the height of a single page +func (r *ImageRef) PageHeight() int { + return vipsGetPageHeight(r.image) +} + +// GetPageHeight return the height of a single page +// Deprecated use PageHeight() instead +func (r *ImageRef) GetPageHeight() int { + return vipsGetPageHeight(r.image) +} + +// SetPageHeight set the height of a page +// For animated images this is used when "unrolling" back to frames +func (r *ImageRef) SetPageHeight(height int) error { + out, err := vipsCopyImage(r.image) + if err != nil { + return err + } + + vipsSetPageHeight(out, height) + + r.setImage(out) + return nil } // Export creates a byte array of the image for use. @@ -722,6 +771,8 @@ func (r *ImageRef) ExportNative() ([]byte, *ImageMetadata, error) { return r.ExportAvif(NewAvifExportParams()) case ImageTypeJP2K: return r.ExportJp2k(NewJp2kExportParams()) + case ImageTypeGIF: + return r.ExportGIF(NewGifExportParams()) default: return r.ExportJpeg(NewJpegExportParams()) } @@ -1099,6 +1150,7 @@ func GetRotationAngleFromExif(orientation int) (Angle, bool) { // N.B. libvips does not flip images currently (i.e. no support for orientations 2, 4, 5 and 7). // N.B. due to the HEIF image standard, HEIF images are always autorotated by default on load. // Thus, calling AutoRotate for HEIF images is not needed. +// todo: use https://www.libvips.org/API/current/libvips-conversion.html#vips-autorot-remove-angle func (r *ImageRef) AutoRotate() error { out, err := vipsAutoRotate(r.image) if err != nil { @@ -1110,6 +1162,10 @@ func (r *ImageRef) AutoRotate() error { // ExtractArea crops the image to a specified area func (r *ImageRef) ExtractArea(left, top, width, height int) error { + if err := r.multiPageNotSupported(); err != nil { + return err + } + out, err := vipsExtractArea(r.image, left, top, width, height) if err != nil { return err @@ -1134,7 +1190,6 @@ func (r *ImageRef) RemoveICCProfile() error { // TransformICCProfile transforms from the embedded ICC profile of the image to the icc profile at the given path. func (r *ImageRef) TransformICCProfile(outputProfilePath string) error { - // If the image has an embedded profile, that will be used and the input profile ignored. // Otherwise, images without an input profile are assumed to use a standard RGB profile. embedded := r.HasICCProfile() @@ -1393,17 +1448,30 @@ func (r *ImageRef) Resize(scale float64, kernel Kernel) error { // ResizeWithVScale resizes the image with both horizontal and vertical scaling. // The parameters are the scaling factors. func (r *ImageRef) ResizeWithVScale(hScale, vScale float64, kernel Kernel) error { - err := r.PremultiplyAlpha() - if err != nil { + if err := r.PremultiplyAlpha(); err != nil { return err } + pages := r.Pages() + pageHeight := r.GetPageHeight() + out, err := vipsResizeWithVScale(r.image, hScale, vScale, kernel) if err != nil { return err } r.setImage(out) + if pages > 1 { + scale := hScale + if vScale != -1 { + scale = vScale + } + newPageHeight := int(float64(pageHeight) * scale) + if err := r.SetPageHeight(newPageHeight); err != nil { + return err + } + } + return r.UnpremultiplyAlpha() } @@ -1472,11 +1540,38 @@ func (r *ImageRef) Flip(direction Direction) error { // Rotate rotates the image by multiples of 90 degrees. To rotate by arbitrary angles use Similarity. func (r *ImageRef) Rotate(angle Angle) error { + width := r.Width() + + if r.Pages() > 1 && (angle == Angle90 || angle == Angle270) { + if angle == Angle270 { + if err := r.Flip(DirectionHorizontal); err != nil { + return err + } + } + + if err := r.Grid(r.GetPageHeight(), r.Pages(), 1); err != nil { + return err + } + + if angle == Angle270 { + if err := r.Flip(DirectionHorizontal); err != nil { + return err + } + } + + } + out, err := vipsRotate(r.image, angle) if err != nil { return err } r.setImage(out) + + if r.Pages() > 1 && (angle == Angle90 || angle == Angle270) { + if err := r.SetPageHeight(width); err != nil { + return err + } + } return nil } @@ -1494,6 +1589,16 @@ func (r *ImageRef) Similarity(scale float64, angle float64, backgroundColor *Col return nil } +// Grid tiles the image pages into a matrix across*down +func (r *ImageRef) Grid(tileHeight, across, down int) error { + out, err := vipsGrid(r.image, tileHeight, across, down) + if err != nil { + return err + } + r.setImage(out) + return nil +} + // SmartCrop will crop the image based on interesting factor func (r *ImageRef) SmartCrop(width int, height int, interesting Interesting) error { out, err := vipsSmartCrop(r.image, width, height, interesting) @@ -1595,6 +1700,25 @@ const ( CodingRAD Coding = C.VIPS_CODING_RAD ) +func (r *ImageRef) newMetadata(format ImageType) *ImageMetadata { + return &ImageMetadata{ + Format: format, + Width: r.Width(), + Height: r.Height(), + Colorspace: r.ColorSpace(), + Orientation: r.Orientation(), + Pages: r.Pages(), + } +} + +func (r *ImageRef) multiPageNotSupported() error { + if r.Pages() > 1 { + return ErrUnsupportedMultiPageOperation + } + + return nil +} + // Pixelate applies a simple pixelate filter to the image func Pixelate(imageRef *ImageRef, factor float64) (err error) { if factor < 1 { diff --git a/vips/image_gif_test.go b/vips/image_gif_test.go new file mode 100644 index 00000000..3d621859 --- /dev/null +++ b/vips/image_gif_test.go @@ -0,0 +1,71 @@ +package vips + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestI_GIF_Animated_Pages(t *testing.T) { + Startup(nil) + image, err := NewImageFromFile(resources + "gif-animated.gif") + require.NoError(t, err) + + pages := image.Pages() + assert.Equal(t, 8, pages) +} + +func TestImage_GIF_Animated(t *testing.T) { + goldenAnimatedTest(t, resources+"gif-animated.gif", + -1, + nil, + nil, + exportGif(NewGifExportParams())) +} + +func TestImage_GIF_Animated_ExportNative(t *testing.T) { + goldenAnimatedTest(t, resources+"gif-animated.gif", + 3, + nil, + nil, + nil) +} + +func TestImage_GIF_Animated_to_WebP(t *testing.T) { + goldenAnimatedTest(t, resources+"gif-animated.gif", + 3, + nil, + nil, + exportWebp(NewWebpExportParams())) +} + +func TestImage_GIF_Animated_Resize(t *testing.T) { + goldenAnimatedTest(t, resources+"gif-animated.gif", + 3, + func(img *ImageRef) error { + return img.Resize(2, KernelCubic) + }, + nil, + nil) +} + +func TestImage_GIF_Animated_Rotate90(t *testing.T) { + goldenAnimatedTest(t, resources+"gif-animated.gif", + -1, + func(img *ImageRef) error { + return img.Rotate(Angle90) + }, + nil, + nil) +} + +func TestImage_GIF_Animated_Rotate270(t *testing.T) { + goldenAnimatedTest(t, resources+"gif-animated.gif", + -1, + func(img *ImageRef) error { + return img.Rotate(Angle270) + }, + nil, + nil) +} diff --git a/vips/image_golden_test.go b/vips/image_golden_test.go index c4ce9060..af58748d 100644 --- a/vips/image_golden_test.go +++ b/vips/image_golden_test.go @@ -194,7 +194,7 @@ func TestImageRef_RemoveMetadata_Leave_Orientation(t *testing.T) { return img.RemoveMetadata() }, func(result *ImageRef) { - assert.Equal(t, 5, result.GetOrientation()) + assert.Equal(t, 5, result.Orientation()) }, nil) } @@ -204,7 +204,7 @@ func TestImageRef_Orientation_Issue(t *testing.T) { return img.Resize(0.9, KernelLanczos3) }, func(result *ImageRef) { - assert.Equal(t, 6, result.GetOrientation()) + assert.Equal(t, 6, result.Orientation()) }, exportWebp(nil), ) @@ -226,7 +226,7 @@ func TestImage_AutoRotate_0(t *testing.T) { return img.AutoRotate() }, func(result *ImageRef) { - assert.Equal(t, 0, result.GetOrientation()) + assert.Equal(t, 0, result.Orientation()) }, nil) } @@ -236,7 +236,7 @@ func TestImage_AutoRotate_1(t *testing.T) { return img.AutoRotate() }, func(result *ImageRef) { - assert.Equal(t, 1, result.GetOrientation()) + assert.Equal(t, 1, result.Orientation()) }, nil) } @@ -246,7 +246,7 @@ func TestImage_AutoRotate_5(t *testing.T) { return img.AutoRotate() }, func(result *ImageRef) { - assert.Equal(t, 1, result.GetOrientation()) + assert.Equal(t, 1, result.Orientation()) }, nil) } @@ -256,7 +256,7 @@ func TestImage_AutoRotate_6(t *testing.T) { return img.AutoRotate() }, func(result *ImageRef) { - assert.Equal(t, 1, result.GetOrientation()) + assert.Equal(t, 1, result.Orientation()) }, nil) } @@ -269,7 +269,7 @@ func TestImage_AutoRotate_6__jpeg_to_webp(t *testing.T) { // expected should be 1 // Known issue: libvips does not write EXIF into WebP: // https://github.com/libvips/libvips/pull/1745 - //assert.Equal(t, 0, result.GetOrientation()) + //assert.Equal(t, 0, result.Orientation()) }, exportWebp(nil), ) @@ -281,7 +281,7 @@ func TestImage_AutoRotate_6__heic_to_jpg(t *testing.T) { return img.AutoRotate() }, func(result *ImageRef) { - assert.Equal(t, 1, result.GetOrientation()) + assert.Equal(t, 1, result.Orientation()) }, exportJpeg(nil), ) } @@ -916,6 +916,12 @@ func exportPng(exportParams *PngExportParams) func(img *ImageRef) ([]byte, *Imag } } +func exportGif(exportParams *GifExportParams) func(img *ImageRef) ([]byte, *ImageMetadata, error) { + return func(img *ImageRef) ([]byte, *ImageMetadata, error) { + return img.ExportGIF(exportParams) + } +} + func goldenTest( t *testing.T, path string, @@ -1071,3 +1077,47 @@ func assertGoldenMatch(t *testing.T, file string, buf []byte, format ImageType) err := ioutil.WriteFile(goldenFile, buf, 0644) assert.NoError(t, err) } + +func goldenAnimatedTest( + t *testing.T, + path string, + pages int, + exec func(img *ImageRef) error, + validate func(img *ImageRef), + export func(img *ImageRef) ([]byte, *ImageMetadata, error), +) []byte { + if exec == nil { + exec = func(*ImageRef) error { return nil } + } + + if validate == nil { + validate = func(*ImageRef) {} + } + + if export == nil { + export = func(img *ImageRef) ([]byte, *ImageMetadata, error) { return img.ExportNative() } + } + + Startup(nil) + + importParams := NewImportParams() + importParams.NumPages.Set(pages) + + img, err := LoadImageFromFile(path, importParams) + require.NoError(t, err) + + err = exec(img) + require.NoError(t, err) + + buf, metadata, err := export(img) + require.NoError(t, err) + + result, err := NewImageFromBuffer(buf) + require.NoError(t, err) + + validate(result) + + assertGoldenMatch(t, path, buf, metadata.Format) + + return buf +} diff --git a/vips/image_test.go b/vips/image_test.go index 3b4d4ad2..227c8237 100644 --- a/vips/image_test.go +++ b/vips/image_test.go @@ -312,7 +312,7 @@ func TestImageRef_GetOrientation__HasEXIF(t *testing.T) { image, err := NewImageFromFile(resources + "jpg-orientation-6.jpg") require.NoError(t, err) - assert.Equal(t, 6, image.GetOrientation()) + assert.Equal(t, 6, image.Orientation()) } func TestImageRef_GetOrientation__NoEXIF(t *testing.T) { @@ -321,7 +321,7 @@ func TestImageRef_GetOrientation__NoEXIF(t *testing.T) { image, err := NewImageFromFile(resources + "png-24bit.png") require.NoError(t, err) - assert.Equal(t, 0, image.GetOrientation()) + assert.Equal(t, 0, image.Orientation()) } func TestImageRef_SetOrientation__HasEXIF(t *testing.T) { @@ -333,7 +333,7 @@ func TestImageRef_SetOrientation__HasEXIF(t *testing.T) { err = image.SetOrientation(5) require.NoError(t, err) - assert.Equal(t, 5, image.GetOrientation()) + assert.Equal(t, 5, image.Orientation()) } func TestImageRef_SetOrientation__NoEXIF(t *testing.T) { @@ -345,7 +345,7 @@ func TestImageRef_SetOrientation__NoEXIF(t *testing.T) { err = image.SetOrientation(5) require.NoError(t, err) - assert.Equal(t, 5, image.GetOrientation()) + assert.Equal(t, 5, image.Orientation()) } func TestImageRef_RemoveOrientation__HasEXIF(t *testing.T) { @@ -357,7 +357,7 @@ func TestImageRef_RemoveOrientation__HasEXIF(t *testing.T) { err = image.RemoveOrientation() require.NoError(t, err) - assert.Equal(t, 0, image.GetOrientation()) + assert.Equal(t, 0, image.Orientation()) } func TestImageRef_RemoveOrientation__NoEXIF(t *testing.T) { @@ -369,7 +369,7 @@ func TestImageRef_RemoveOrientation__NoEXIF(t *testing.T) { err = image.RemoveOrientation() require.NoError(t, err) - assert.Equal(t, 0, image.GetOrientation()) + assert.Equal(t, 0, image.Orientation()) } func TestImageRef_RemoveMetadata__RetainsProfile(t *testing.T) { @@ -396,7 +396,7 @@ func TestImageRef_RemoveMetadata__RetainsOrientation(t *testing.T) { err = image.RemoveMetadata() require.NoError(t, err) - assert.Equal(t, 5, image.GetOrientation()) + assert.Equal(t, 5, image.Orientation()) } // Known issue: libvips does not write EXIF into WebP: @@ -410,7 +410,7 @@ func TestImageRef_RemoveMetadata__RetainsOrientation__WebP(t *testing.T) { err = image.RemoveMetadata() require.NoError(t, err) - assert.Equal(t, 6, image.GetOrientation()) + assert.Equal(t, 6, image.Orientation()) } func TestImageRef_RemoveICCProfile(t *testing.T) { @@ -801,21 +801,12 @@ func TestIsColorSpaceSupport(t *testing.T) { assert.Error(t, err) } -func TestGetPages_gif(t *testing.T) { - Startup(nil) - image, err := NewImageFromFile(resources + "gif-animated.gif") - require.NoError(t, err) - - pages := image.GetPages() - assert.Equal(t, 8, pages) -} - -func TestGetPages_webp(t *testing.T) { +func TestPages_webp(t *testing.T) { Startup(nil) image, err := NewImageFromFile(resources + "webp-animated.webp") require.NoError(t, err) - pages := image.GetPages() + pages := image.Pages() assert.Equal(t, 8, pages) } @@ -976,6 +967,15 @@ func TestImageRef_JP2K(t *testing.T) { assert.Equal(t, ImageTypeJP2K, metadata.Format) } +func TestImageRef_ExtractArea_MultiPage_Unsupported(t *testing.T) { + Startup(nil) + image, err := NewImageFromFile(resources + "gif-animated.gif") + require.NoError(t, err) + + err = image.ExtractArea(1, 2, 3, 4) + assert.Error(t, err) +} + // TODO unit tests to cover: // NewImageFromReader failing test // NewImageFromFile failing test