public void TestSwitch() { // switch was added in libvips 8.9. Skip.IfNot(NetVips.AtLeastLibvips(8, 9), "requires libvips >= 8.9"); var x = Image.Grey(256, 256, uchar: true); // slice into two at 128, we should get 50% of pixels in each half var index = Image.Switch(x < 128, x >= 128); Assert.Equal(0.5, index.Avg()); // slice into four index = Image.Switch( x < 64, x >= 64 && x < 128, x >= 128 && x < 192, x >= 192 ); Assert.Equal(1.5, index.Avg()); // no match should return n + 1 index = Image.Switch(x.Equal(1000), x.Equal(2000)); Assert.Equal(2, index.Avg()); }
public void TestCase() { // case was added in libvips 8.9. Skip.IfNot(NetVips.AtLeastLibvips(8, 9), "requires libvips >= 8.9"); var x = Image.Grey(256, 256, uchar: true); // slice into two at 128, we should get 50% of pixels in each half var index = Image.Switch(x < 128, x >= 128); var y = index.Case(10, 20); Assert.Equal(15, y.Avg()); // slice into four index = Image.Switch( x < 64, x >= 64 && x < 128, x >= 128 && x < 192, x >= 192 ); Assert.Equal(25, index.Case(10, 20, 30, 40).Avg()); // values over N should use the last value Assert.Equal(22.5, index.Case(10, 20, 30).Avg()); }
public void TestMatrixinvert() { // matrixinvert was added in libvips 8.10. Skip.IfNot(NetVips.AtLeastLibvips(8, 10), "requires libvips >= 8.10"); // 4x4 matrix to check if PLU decomposition works var mat = Image.NewFromArray(new[, ] { { 4, 0, 0, 0 }, { 0, 0, 2, 0 }, { 0, 1, 2, 0 }, { 1, 0, 0, 1 } }); var im = mat.Matrixinvert(); Assert.Equal(4, im.Width); Assert.Equal(4, im.Height); Assert.Equal(1, im.Bands); Assert.Equal(Enums.BandFormat.Double, im.Format); var p = im[0, 0]; Assert.Equal(0.25, p[0]); p = im[3, 3]; Assert.Equal(1.0, p[0]); }
public GenerateImageClass() { if (NetVips.AtLeastLibvips(8, 9)) { _gTypeToCSharpDict.Add(GValue.SourceType, "Source"); _gTypeToCSharpDict.Add(GValue.TargetType, "Target"); } }
public void TestGetFields() { Skip.IfNot(NetVips.AtLeastLibvips(8, 5), "requires libvips >= 8.5"); var im = Image.Black(10, 10); var fields = im.GetFields(); // we might add more fields later Assert.True(fields.Length > 10); Assert.Equal("width", fields[0]); }
public void TestGetSuffixes() { Skip.IfNot(NetVips.AtLeastLibvips(8, 8), "requires libvips >= 8.8"); var suffixes = NetVips.GetSuffixes(); // vips supports these file types by default // (without being dependent on external dependencies): // - Native file format (`*.v`, `*.vips`). // - PPM images (`*.ppm`, `*.pgm`, `*.pbm`, `*.pfm`). // - Analyze images (`*.hdr`). Assert.True(suffixes.Length >= 7); }
public void TestCmyk() { Skip.IfNot(NetVips.AtLeastLibvips(8, 8), "requires libvips >= 8.8"); // even without lcms, we should have a working approximation var test = Image.NewFromFile(Helper.JpegFile); var im = test.Colourspace(Enums.Interpretation.Cmyk).Colourspace(Enums.Interpretation.Srgb); var before = test[582, 210]; var after = im[582, 210]; Helper.AssertAlmostEqualObjects(before, after, 10); }
public void TestGifLoad() { Skip.IfNot(Helper.Have("gifload") && File.Exists(Helper.GifFile), "no gif support, skipping test"); void GifValid(Image im) { var a = im[10, 10]; Assert.Equal(new double[] { 33 }, a); Assert.Equal(159, im.Width); Assert.Equal(203, im.Height); Assert.Equal(1, im.Bands); } FileLoader("gifload", Helper.GifFile, GifValid); BufferLoader("gifload_buffer", Helper.GifFile, GifValid); // 'n' param added in 8.5 if (NetVips.AtLeastLibvips(8, 5)) { var x1 = Image.NewFromFile(Helper.GifAnimFile); var x2 = Image.NewFromFile(Helper.GifAnimFile, kwargs: new VOption { { "n", 2 } }); Assert.Equal(2 * x1.Height, x2.Height); var pageHeight = x2.Get("page-height"); Assert.Equal(x1.Height, pageHeight); x2 = Image.NewFromFile(Helper.GifAnimFile, kwargs: new VOption { { "n", -1 } }); Assert.Equal(5 * x1.Height, x2.Height); // delay metadata was added in libvips 8.9 if (NetVips.AtLeastLibvips(8, 9)) { // our test gif has delay 0 for the first frame set in error Assert.Equal(new[] { 0, 50, 50, 50, 50 }, x2.Get("delay")); } x2 = Image.NewFromFile(Helper.GifAnimFile, kwargs: new VOption { { "page", 1 }, { "n", -1 } }); Assert.Equal(4 * x1.Height, x2.Height); } }
public void TestTanh() { Skip.IfNot(NetVips.AtLeastLibvips(8, 12), "requires libvips >= 8.12"); dynamic Tanh(dynamic x) { if (x is Image image) { return(image.Tanh()); } return(Math.Tanh(x)); } RunUnary(_allImages, Tanh, Helper.NonComplexFormats); }
public void TestMagickSave() { Skip.IfNot(Helper.Have("magicksave"), "no magick support, skipping test"); // save to a file and load again ... we can't use SaveLoadFile since // we want to make sure we use magickload/save // don't use BMP - GraphicsMagick always adds an alpha // don't use TIF - IM7 will save as 16-bit var filename = Helper.GetTemporaryFile(_tempDir, ".jpg"); _colour.Magicksave(filename); var x = Image.Magickload(filename); Assert.Equal(_colour.Width, x.Width); Assert.Equal(_colour.Height, x.Height); Assert.Equal(_colour.Bands, x.Bands); Assert.Equal(_colour.Height, x.Height); var maxDiff = (_colour - x).Abs().Max(); Assert.True(maxDiff <= 60); SaveLoadBuffer("magicksave_buffer", "magickload_buffer", _colour, 60, new VOption { { "format", "JPG" } }); // try an animation if (Helper.Have("gifload")) { var x1 = Image.NewFromFile(Helper.GifAnimFile, kwargs: new VOption { { "n", -1 } }); var w1 = x1.MagicksaveBuffer(format: "GIF"); var x2 = Image.NewFromBuffer(w1, kwargs: new VOption { { "n", -1 } }); var delayName = NetVips.AtLeastLibvips(8, 9) ? "delay" : "gif-delay"; Assert.Equal(x2.Get(delayName), x1.Get(delayName)); Assert.Equal(x2.Get("page-height"), x1.Get("page-height")); // magicks vary in how they handle this ... just pray we are close Assert.True(Math.Abs((int)x1.Get("gif-loop") - (int)x2.Get("gif-loop")) < 5); } }
public void TestAtan2() { Skip.IfNot(NetVips.AtLeastLibvips(8, 12), "requires libvips >= 8.12"); dynamic Atan2(dynamic x, dynamic y) { if (x is Image left) { return(left.Atan2(y)); } return(Math.Atan2(x[0], y[0]) * (180.0 / Math.PI)); } var im = (Image.Black(100, 100) + new[] { 0, 1, 2 }) / 3.0; RunBinary(im.Bandsplit(), Atan2, Helper.NonComplexFormats); }
public void TestAtanh() { Skip.IfNot(NetVips.AtLeastLibvips(8, 12), "requires libvips >= 8.12"); dynamic Atanh(dynamic x) { if (x is Image image) { return(image.Atanh()); } return(Math.Atanh(x)); } var im = (Image.Black(100, 100) + new[] { 0, 1, 2 }) / 3.0; RunUnary(new[] { im }, Atanh, Helper.NonComplexFormats); }
public void TestRegion() { Skip.IfNot(NetVips.AtLeastLibvips(8, 8), "requires libvips >= 8.8"); var im = Image.Black(100, 100); var region = Region.New(im); var data = region.Fetch(0, 0, 10, 10); Assert.Equal(10, region.Width); Assert.Equal(10, region.Height); Assert.True(data.Length == 100); Assert.True(data.All(p => p == 0)); data = region.Fetch(0, 0, 20, 10); Assert.Equal(20, region.Width); Assert.Equal(10, region.Height); Assert.True(data.Length == 200); Assert.True(data.All(p => p == 0)); }
public void TestHistLocal() { var im = Image.NewFromFile(Helper.JpegFile); var im2 = im.HistLocal(10, 10); Assert.Equal(im.Width, im2.Width); Assert.Equal(im.Height, im2.Height); Assert.True(im.Avg() < im2.Avg()); Assert.True(im.Deviate() < im2.Deviate()); if (NetVips.AtLeastLibvips(8, 5)) { var im3 = im.HistLocal(10, 10, maxSlope: 3); Assert.Equal(im.Width, im3.Width); Assert.Equal(im.Height, im3.Height); Assert.True(im3.Deviate() < im2.Deviate()); } }
public void TestThumbnail() { Skip.IfNot(NetVips.AtLeastLibvips(8, 5), "requires libvips >= 8.5"); var im = Image.Thumbnail(Helper.JpegFile, 100); Assert.Equal(100, im.Width); Assert.Equal(3, im.Bands); // the average shouldn't move too much var imOrig = Image.NewFromFile(Helper.JpegFile); Assert.True(Math.Abs(imOrig.Avg() - im.Avg()) < 1); // make sure we always get the right width for (var width = 1000; width >= 1; width -= 13) { im = Image.Thumbnail(Helper.JpegFile, width); Assert.Equal(width, im.Width); } // should fit one of width or height im = Image.Thumbnail(Helper.JpegFile, 100, height: 300); Assert.Equal(100, im.Width); Assert.NotEqual(300, im.Height); im = Image.Thumbnail(Helper.JpegFile, 300, height: 100); Assert.NotEqual(300, im.Width); Assert.Equal(100, im.Height); // with @crop, should fit both width and height im = Image.Thumbnail(Helper.JpegFile, 100, height: 300, crop: "centre"); Assert.Equal(100, im.Width); Assert.Equal(300, im.Height); var im1 = Image.Thumbnail(Helper.JpegFile, 100); var buf = File.ReadAllBytes(Helper.JpegFile); var im2 = Image.ThumbnailBuffer(buf, 100); Assert.True(Math.Abs(im1.Avg() - im2.Avg()) < 1); }
public void TestOpenexrLoad() { Skip.IfNot(Helper.Have("openexrload") && File.Exists(Helper.ExrFile), "no openexr support, skipping test"); void ExrValid(Image im) { var a = im[10, 10]; Helper.AssertAlmostEqualObjects(new[] { 0.124512, 0.159668, 0.040375, // OpenEXR alpha is scaled to 0 - 255 in libvips 8.7+ NetVips.AtLeastLibvips(8, 7) ? 255 : 1.0 }, a, 0.00001); Assert.Equal(610, im.Width); Assert.Equal(406, im.Height); Assert.Equal(4, im.Bands); } FileLoader("openexrload", Helper.ExrFile, ExrValid); }
public void TestText() { Skip.IfNot(Helper.Have("text"), "no text in this vips, skipping test"); var im = Image.Text("Hello, world!", dpi: 300); Assert.True(im.Width > 10); Assert.True(im.Height > 10); Assert.Equal(1, im.Bands); Assert.Equal(Enums.BandFormat.Uchar, im.Format); Assert.Equal(255, im.Max()); Assert.Equal(0, im.Min()); if (NetVips.AtLeastLibvips(8, 9)) { // test autofit im = Image.Text("Hello, world!", width: 500, height: 500); // quite a large threshold, since we need to work with a huge range of // text rendering systems Assert.True(Math.Abs(im.Width - 500) < 50); } }
public void TestPdfLoad() { Skip.IfNot(Helper.Have("pdfload") && File.Exists(Helper.PdfFile), "no pdf support, skipping test"); void PdfValid(Image im) { var a = im[10, 10]; Assert.Equal(new double[] { 35, 31, 32, 255 }, a); // New sizing rules in libvips 8.8+, see: // https://github.com/libvips/libvips/commit/29d29533d45848ecc12a3c50c39c26c835458a61 Assert.Equal(NetVips.AtLeastLibvips(8, 8) ? 1134 : 1133, im.Width); Assert.Equal(680, im.Height); Assert.Equal(4, im.Bands); } FileLoader("pdfload", Helper.PdfFile, PdfValid); BufferLoader("pdfload_buffer", Helper.PdfFile, PdfValid); var x = Image.NewFromFile(Helper.PdfFile); var y = Image.NewFromFile(Helper.PdfFile, kwargs: new VOption { { "scale", 2 } }); Assert.True(Math.Abs(x.Width * 2 - y.Width) < 2); Assert.True(Math.Abs(x.Height * 2 - y.Height) < 2); x = Image.NewFromFile(Helper.PdfFile); y = Image.NewFromFile(Helper.PdfFile, kwargs: new VOption { { "dpi", 144 } }); Assert.True(Math.Abs(x.Width * 2 - y.Width) < 2); Assert.True(Math.Abs(x.Height * 2 - y.Height) < 2); }
public void TestHoughLine() { // hough_line changed the way it codes parameter space in 8.7 ... don't // test earlier versions Skip.IfNot(NetVips.AtLeastLibvips(8, 7), "requires libvips >= 8.7"); var test = Image.Black(100, 100).DrawLine(new double[] { 100 }, 10, 90, 90, 10); foreach (var fmt in Helper.AllFormats) { var im = test.Cast(fmt); var hough = im.HoughLine(); var maxPos = hough.MaxPos(); var x = maxPos[1]; var y = maxPos[2]; var angle = Math.Floor(180.0 * x / hough.Width); var distance = Math.Floor(test.Height * y / hough.Height); Assert.Equal(45, angle); Assert.Equal(70, distance); } }
public void TestMapim() { var im = Image.NewFromFile(Helper.JpegFile); var p = ToPolar(im); var r = ToRectangular(p); // the left edge (which is squashed to the origin) will be badly // distorted, but the rest should not be too bad var a = r.Crop(50, 0, im.Width - 50, im.Height).Gaussblur(2); var b = im.Crop(50, 0, im.Width - 50, im.Height).Gaussblur(2); Assert.True((a - b).Abs().Max() < 20); // this was a bug at one point, strangely, if executed with debug // enabled // fixed in 8.7.3 if (NetVips.AtLeastLibvips(8, 7, 3)) { var mp = Image.Xyz(im.Width, im.Height); var interp = Interpolate.NewFromName("bicubic"); Assert.Equal(im.Avg(), im.Mapim(mp, interp).Avg()); } }
public void TestNotEq() { dynamic NotEq(dynamic x, dynamic y) { if (y is Image rightImage && !(x is Image)) { return(x != rightImage); } if (x is Image leftImage && !(y is Image)) { return(y != leftImage); } if (y is Image) { return(y.NotEqual(x)); } return(x != y ? 255 : 0); } RunArithConst(NotEq); RunArith(NotEq); if (NetVips.AtLeastLibvips(8, 9)) { // comparisons against out of range values should always fail, and // comparisons to fractional values should always fail var z = Image.Grey(256, 256, uchar: true); Assert.Equal(0, z.Equal(1000).Max()); Assert.Equal(255, z.Equal(12).Max()); Assert.Equal(0, z.Equal(12.5).Max()); } }
public void TestWebp() { Skip.IfNot(Helper.Have("webpload") && File.Exists(Helper.WebpFile), "no webp support, skipping test"); void WebpValid(Image im) { var a = im[10, 10]; // different webp versions use different rounding systems leading // to small variations Helper.AssertAlmostEqualObjects(new double[] { 71, 166, 236 }, a, 2); Assert.Equal(550, im.Width); Assert.Equal(368, im.Height); Assert.Equal(3, im.Bands); } FileLoader("webpload", Helper.WebpFile, WebpValid); BufferLoader("webpload_buffer", Helper.WebpFile, WebpValid); SaveLoadBuffer("webpsave_buffer", "webpload_buffer", _colour, 60); SaveLoad("%s.webp", _colour); if (Helper.Have("webpload_source")) { SaveLoadStream(".webp", "", _colour, 80); } // test lossless mode var x = Image.NewFromFile(Helper.WebpFile); var buf = x.WebpsaveBuffer(lossless: true); var im2 = Image.NewFromBuffer(buf); Assert.True(Math.Abs(x.Avg() - im2.Avg()) < 1); // higher Q should mean a bigger buffer var b1 = x.WebpsaveBuffer(q: 10); var b2 = x.WebpsaveBuffer(q: 90); Assert.True(b2.Length > b1.Length); // try saving an image with an ICC profile and reading it back ... if we // can do it, our webp supports metadata load/save buf = _colour.WebpsaveBuffer(); x = Image.NewFromBuffer(buf); if (x.Contains("icc-profile-data")) { // verify that the profile comes back unharmed var p1 = _colour.Get("icc-profile-data"); var p2 = x.Get("icc-profile-data"); Assert.Equal(p1, p2); // add tests for exif, xmp, ipct // the exif test will need us to be able to walk the header, // we can't just check exif-data // we can test that exif changes change the output of webpsave // first make sure we have exif support var z = Image.NewFromFile(Helper.JpegFile); if (z.Contains("exif-ifd0-Orientation")) { x = _colour.Copy(); x.Set("orientation", 6); buf = x.WebpsaveBuffer(); var y = Image.NewFromBuffer(buf); Assert.Equal(6, y.Get("orientation")); } } // try converting an animated gif to webp ... can't do back to gif // again without IM support // added in 8.8 if (Helper.Have("gifload") && NetVips.AtLeastLibvips(8, 8)) { var x1 = Image.NewFromFile(Helper.GifAnimFile, kwargs: new VOption { { "n", -1 } }); var w1 = x1.WebpsaveBuffer(q: 10); var x2 = Image.NewFromBuffer(w1, kwargs: new VOption { { "n", -1 } }); Assert.Equal(x2.Width, x1.Width); Assert.Equal(x2.Height, x1.Height); var delayName = NetVips.AtLeastLibvips(8, 9) ? "delay" : "gif-delay"; Assert.Equal(x2.Get(delayName), x1.Get(delayName)); Assert.Equal(x2.Get("page-height"), x1.Get("page-height")); Assert.Equal(x2.Get("gif-loop"), x1.Get("gif-loop")); } }
public void TestColourspace() { // mid-grey in Lab ... put 42 in the extra band, it should be copied // unmodified var test = Image.Black(100, 100) + new[] { 50, 0, 0, 42 }; test = test.Copy(interpretation: Enums.Interpretation.Lab); // a long series should come in a circle var im = test; foreach (var col in Helper.ColourColourspaces.Concat(new[] { Enums.Interpretation.Lab })) { im = im.Colourspace(col); Assert.Equal(col, im.Interpretation); for (var i = 0; i < 4; i++) { var minL = im[i].Min(); var maxH = im[i].Max(); Assert.Equal(minL, maxH); } var pixel = im[10, 10]; Assert.Equal(42, pixel[3], 2); } // alpha won't be equal for RGB16, but it should be preserved if we go // there and back im = im.Colourspace(Enums.Interpretation.Rgb16); im = im.Colourspace(Enums.Interpretation.Lab); var before = test[10, 10]; var after = im[10, 10]; Helper.AssertAlmostEqualObjects(before, after, 0.1); // go between every pair of colour spaces foreach (var start in Helper.ColourColourspaces) { foreach (var end in Helper.ColourColourspaces) { im = test.Colourspace(start); var im2 = im.Colourspace(end); var im3 = im2.Colourspace(Enums.Interpretation.Lab); before = test[10, 10]; after = im3[10, 10]; Helper.AssertAlmostEqualObjects(before, after, 0.1); } } // test Lab->XYZ on mid-grey // checked against http://www.brucelindbloom.com im = test.Colourspace(Enums.Interpretation.Xyz); after = im[10, 10]; Helper.AssertAlmostEqualObjects(new[] { 17.5064, 18.4187, 20.0547, 42 }, after); // grey->colour->grey should be equal foreach (var monoFmt in Helper.MonoColourspaces) { var testGrey = test.Colourspace(monoFmt); im = testGrey; foreach (var col in Helper.ColourColourspaces.Concat(new[] { monoFmt })) { im = im.Colourspace(col); Assert.Equal(col, im.Interpretation); } var pixelBefore = testGrey[10, 10]; var alphaBefore = pixelBefore[1]; var pixelAfter = im[10, 10]; var alphaAfter = pixelAfter[1]; Assert.True(Math.Abs(alphaAfter - alphaBefore) < 1); // GREY16 can wind up rather different due to rounding but 8-bit we should hit exactly Assert.True( Math.Abs(pixelAfter[0] - pixelBefore[0]) < (monoFmt == Enums.Interpretation.Grey16 ? 30 : 1)); } if (NetVips.AtLeastLibvips(8, 8)) { // we should be able to go from cmyk to any 3-band space and back again, // approximately var cmyk = test.Colourspace(Enums.Interpretation.Cmyk); foreach (var end in Helper.ColourColourspaces) { im = cmyk.Colourspace(end); var im2 = im.Colourspace(Enums.Interpretation.Cmyk); before = cmyk[10, 10]; after = im2[10, 10]; Helper.AssertAlmostEqualObjects(before, after, 10); } } }
public void TestThumbnail() { Skip.IfNot(NetVips.AtLeastLibvips(8, 5), "requires libvips >= 8.5"); var im = Image.Thumbnail(Helper.JpegFile, 100); Assert.Equal(100, im.Width); Assert.Equal(3, im.Bands); // the average shouldn't move too much var imOrig = Image.NewFromFile(Helper.JpegFile); Assert.True(Math.Abs(imOrig.Avg() - im.Avg()) < 1); // make sure we always get the right width for (var width = 1000; width >= 1; width -= 13) { im = Image.Thumbnail(Helper.JpegFile, width); Assert.Equal(width, im.Width); } // should fit one of width or height im = Image.Thumbnail(Helper.JpegFile, 100, height: 300); Assert.Equal(100, im.Width); Assert.NotEqual(300, im.Height); im = Image.Thumbnail(Helper.JpegFile, 300, height: 100); Assert.NotEqual(300, im.Width); Assert.Equal(100, im.Height); // with @crop, should fit both width and height im = Image.Thumbnail(Helper.JpegFile, 100, height: 300, crop: "centre"); Assert.Equal(100, im.Width); Assert.Equal(300, im.Height); var im1 = Image.Thumbnail(Helper.JpegFile, 100); var buf = File.ReadAllBytes(Helper.JpegFile); var im2 = Image.ThumbnailBuffer(buf, 100); Assert.True(Math.Abs(im1.Avg() - im2.Avg()) < 1); // OME-TIFF subifd thumbnail support added in 8.10 if (NetVips.AtLeastLibvips(8, 10)) { // should be able to thumbnail many-page tiff im = Image.Thumbnail(Helper.OmeFile, 100); Assert.Equal(100, im.Width); Assert.Equal(38, im.Height); // should be able to thumbnail individual pages from many-page tiff // should be able to thumbnail individual pages from many-page tiff im = Image.Thumbnail(Helper.OmeFile + "[page=0]", 100); Assert.Equal(100, im.Width); Assert.Equal(38, im.Height); im2 = Image.Thumbnail(Helper.OmeFile + "[page=1]", 100); Assert.Equal(100, im2.Width); Assert.Equal(38, im2.Height); Assert.True((im1 - im2).Abs().Max() != 0); // should be able to thumbnail entire many-page tiff as a toilet-roll // image im = Image.Thumbnail(Helper.OmeFile + "[n=-1]", 100); Assert.Equal(100, im.Width); Assert.Equal(570, im.Height); if (Helper.Have("heifload")) { // this image is orientation 6 ... thumbnail should flip it var thumb = Image.Thumbnail(Helper.HeicFile, 100); // thumb should be portrait Assert.True(thumb.Width < thumb.Height); Assert.Equal(100, thumb.Height); } } }
public void TestGifLoad() { Skip.IfNot(Helper.Have("gifload") && File.Exists(Helper.GifFile), "no gif support, skipping test"); void GifValid(Image im) { var a = im[10, 10]; Assert.Equal(new double[] { 33 }, a); Assert.Equal(159, im.Width); Assert.Equal(203, im.Height); Assert.Equal(1, im.Bands); } FileLoader("gifload", Helper.GifFile, GifValid); BufferLoader("gifload_buffer", Helper.GifFile, GifValid); // test fallback stream mechanism, needs libvips >= 8.9 if (NetVips.AtLeastLibvips(8, 9)) { // file-based loader fallback using (var input = Source.NewFromFile(Helper.GifFile)) { var img = Image.NewFromSource(input, access: Enums.Access.Sequential); GifValid(img); } // buffer-based loader fallback using (var input = File.OpenRead(Helper.GifFile)) { var img = Image.NewFromStream(input, access: Enums.Access.Sequential); GifValid(img); } } // 'n' param added in 8.5 if (NetVips.AtLeastLibvips(8, 5)) { var x1 = Image.NewFromFile(Helper.GifAnimFile); var x2 = Image.NewFromFile(Helper.GifAnimFile, kwargs: new VOption { { "n", 2 } }); Assert.Equal(2 * x1.Height, x2.Height); var pageHeight = x2.Get("page-height"); Assert.Equal(x1.Height, pageHeight); x2 = Image.NewFromFile(Helper.GifAnimFile, kwargs: new VOption { { "n", -1 } }); Assert.Equal(5 * x1.Height, x2.Height); // delay metadata was added in libvips 8.9 if (NetVips.AtLeastLibvips(8, 9)) { // our test gif has delay 0 for the first frame set in error Assert.Equal(new[] { 0, 50, 50, 50, 50 }, x2.Get("delay")); } x2 = Image.NewFromFile(Helper.GifAnimFile, kwargs: new VOption { { "page", 1 }, { "n", -1 } }); Assert.Equal(4 * x1.Height, x2.Height); } }
public void TestDzSave() { Skip.IfNot(Helper.Have("dzsave"), "no dzsave support, skipping test"); // dzsave is hard to test, there are so many options // test each option separately and hope they all function together // correctly // default deepzoom layout ... we must use png here, since we want to // test the overlap for equality var filename = Helper.GetTemporaryFile(_tempDir); _colour.Dzsave(filename, suffix: ".png"); // test horizontal overlap ... expect 256 step, overlap 1 var x = Image.NewFromFile(filename + "_files/10/0_0.png"); Assert.Equal(255, x.Width); var y = Image.NewFromFile(filename + "_files/10/1_0.png"); Assert.Equal(256, y.Width); // the right two columns of x should equal the left two columns of y var left = x.ExtractArea(x.Width - 2, 0, 2, x.Height); var right = y.ExtractArea(0, 0, 2, y.Height); Assert.Equal(0, (left - right).Abs().Max()); // test vertical overlap Assert.Equal(255, x.Height); y = Image.NewFromFile(filename + "_files/10/0_1.png"); Assert.Equal(256, y.Height); // the bottom two rows of x should equal the top two rows of y var top = x.ExtractArea(0, x.Height - 2, x.Width, 2); var bottom = y.ExtractArea(0, 0, y.Width, 2); Assert.Equal(0, (top - bottom).Abs().Max()); // there should be a bottom layer x = Image.NewFromFile(filename + "_files/0/0_0.png"); Assert.Equal(1, x.Width); Assert.Equal(1, x.Height); // 10 should be the final layer Assert.False(Directory.Exists(filename + "_files/11")); // default google layout filename = Helper.GetTemporaryFile(_tempDir); _colour.Dzsave(filename, layout: "google"); // test bottom-right tile ... default is 256x256 tiles, overlap 0 x = Image.NewFromFile(filename + "/2/2/3.jpg"); Assert.Equal(256, x.Width); Assert.Equal(256, x.Height); Assert.False(Directory.Exists(filename + "/2/2/4.jpg")); Assert.False(Directory.Exists(filename + "/3")); x = Image.NewFromFile(filename + "/blank.png"); Assert.Equal(256, x.Width); Assert.Equal(256, x.Height); // google layout with overlap ... verify that we clip correctly // overlap 1, 510x510 pixels, 256 pixel tiles, should be exactly 2x2 // tiles, though in fact the bottom and right edges will be white filename = Helper.GetTemporaryFile(_tempDir); _colour.ExtractArea(0, 0, 510, 510).Dzsave(filename, layout: "google", overlap: 1, depth: "one"); x = Image.NewFromFile(filename + "/0/1/1.jpg"); Assert.Equal(256, x.Width); Assert.Equal(256, x.Height); Assert.False(Directory.Exists(filename + "/0/2/2.jpg")); // with 511x511, it'll fit exactly into 2x2 -- we we actually generate // 3x3, since we output the overlaps // 8.6 revised the rules on overlaps, so don't test earlier than that if (NetVips.AtLeastLibvips(8, 6)) { filename = Helper.GetTemporaryFile(_tempDir); _colour.ExtractArea(0, 0, 511, 511).Dzsave(filename, layout: "google", overlap: 1, depth: "one"); x = Image.NewFromFile(filename + "/0/2/2.jpg"); Assert.Equal(256, x.Width); Assert.Equal(256, x.Height); Assert.False(Directory.Exists(filename + "/0/3/3.jpg")); } // default zoomify layout filename = Helper.GetTemporaryFile(_tempDir); _colour.Dzsave(filename, layout: "zoomify"); // 256x256 tiles, no overlap Assert.True(File.Exists(filename + "/ImageProperties.xml")); x = Image.NewFromFile(filename + "/TileGroup0/2-3-2.jpg"); Assert.Equal(256, x.Width); Assert.Equal(256, x.Height); // test zip output filename = Helper.GetTemporaryFile(_tempDir, ".zip"); _colour.Dzsave(filename); Assert.True(File.Exists(filename)); Assert.False(Directory.Exists(filename + "_files")); Assert.False(File.Exists(filename + ".dzi")); // test compressed zip output var filename2 = Helper.GetTemporaryFile(_tempDir, ".zip"); _colour.Dzsave(filename2, compression: -1); Assert.True(File.Exists(filename2)); Assert.True(new FileInfo(filename2).Length < new FileInfo(filename).Length); // test suffix filename = Helper.GetTemporaryFile(_tempDir); _colour.Dzsave(filename, suffix: ".png"); x = Image.NewFromFile(filename + "_files/10/0_0.png"); Assert.Equal(255, x.Width); // test overlap filename = Helper.GetTemporaryFile(_tempDir); _colour.Dzsave(filename, overlap: 200); x = Image.NewFromFile(filename + "_files/10/1_1.jpeg"); Assert.Equal(654, x.Width); // test tile-size filename = Helper.GetTemporaryFile(_tempDir); _colour.Dzsave(filename, tileSize: 512); y = Image.NewFromFile(filename + "_files/10/0_0.jpeg"); Assert.Equal(513, y.Width); Assert.Equal(513, y.Height); // test save to memory buffer if (Helper.Have("dzsave_buffer")) { filename = Helper.GetTemporaryFile(_tempDir, ".zip"); var baseName = Path.GetFileNameWithoutExtension(filename); _colour.Dzsave(filename); var buf1 = File.ReadAllBytes(filename); var buf2 = _colour.DzsaveBuffer(basename: baseName); Assert.Equal(buf1.Length, buf2.Length); // we can't test the bytes are exactly equal -- the timestamps will // be different // added in 8.7 if (NetVips.AtLeastLibvips(8, 7)) { _ = _colour.DzsaveBuffer(regionShrink: "mean"); _ = _colour.DzsaveBuffer(regionShrink: "mode"); _ = _colour.DzsaveBuffer(regionShrink: "median"); } } }
public void TestJpeg() { Skip.IfNot(Helper.Have("jpegload"), "no jpeg support in this vips, skipping test"); void JpegValid(Image im) { var a = im[10, 10]; Assert.Equal(new double[] { 6, 5, 3 }, a); var profile = (byte[])im.Get("icc-profile-data"); Assert.Equal(1352, profile.Length); Assert.Equal(1024, im.Width); Assert.Equal(768, im.Height); Assert.Equal(3, im.Bands); } FileLoader("jpegload", Helper.JpegFile, JpegValid); SaveLoad("%s.jpg", _mono); SaveLoad("%s.jpg", _colour); BufferLoader("jpegload_buffer", Helper.JpegFile, JpegValid); SaveLoadBuffer("jpegsave_buffer", "jpegload_buffer", _colour, 80); if (Helper.Have("jpegload_source")) { SaveLoadStream(".jpg", "", _colour, 80); } // see if we have exif parsing: our test image has this field var x = Image.NewFromFile(Helper.JpegFile); if (x.Contains("exif-ifd0-Orientation")) { // we need a copy of the image to set the new metadata on // otherwise we get caching problems // can set, save and load new orientation x = Image.NewFromFile(Helper.JpegFile); x = x.Copy(); x.Set("orientation", 2); var filename = Helper.GetTemporaryFile(_tempDir, ".jpg"); x.WriteToFile(filename); x = Image.NewFromFile(filename); var y = x.Get("orientation"); Assert.Equal(2, y); // can remove orientation, save, load again, orientation // has reset x = x.Copy(); x.Remove("orientation"); filename = Helper.GetTemporaryFile(_tempDir, ".jpg"); x.WriteToFile(filename); x = Image.NewFromFile(filename); y = x.Get("orientation"); Assert.Equal(1, y); // autorotate load works x = Image.NewFromFile(Helper.JpegFile); x = x.Copy(); x.Set("orientation", 6); filename = Helper.GetTemporaryFile(_tempDir, ".jpg"); x.WriteToFile(filename); var x1 = Image.NewFromFile(filename); var x2 = Image.NewFromFile(filename, kwargs: new VOption { { "autorotate", true } }); Assert.Equal(x1.Width, x2.Height); Assert.Equal(x1.Height, x2.Width); // can set, save and reload ASCII string fields // added in 8.7 if (NetVips.AtLeastLibvips(8, 7)) { x = Image.NewFromFile(Helper.JpegFile); x = x.Copy(); x.Set(GValue.GStrType, "exif-ifd0-ImageDescription", "hello world"); filename = Helper.GetTemporaryFile(_tempDir, ".jpg"); x.WriteToFile(filename); x = Image.NewFromFile(filename); y = x.Get("exif-ifd0-ImageDescription"); // can't use Assert.Equal since the string will have an extra " (xx, yy, zz)" // format area at the end Assert.StartsWith("hello world", (string)y); // can set, save and reload UTF16 string fields ... NetVips is // utf8, but it will be coded as utf16 and back for the XP* fields x = Image.NewFromFile(Helper.JpegFile); x = x.Copy(); x.Set(GValue.GStrType, "exif-ifd0-XPComment", "йцук"); filename = Helper.GetTemporaryFile(_tempDir, ".jpg"); x.WriteToFile(filename); x = Image.NewFromFile(filename); y = x.Get("exif-ifd0-XPComment"); // can't use Assert.Equal since the string will have an extra " (xx, yy, zz)" // format area at the end Assert.StartsWith("йцук", (string)y); // can set/save/load UserComment, a tag which has the // encoding in the first 8 bytes ... though libexif only supports // ASCII for this x = Image.NewFromFile(Helper.JpegFile); x = x.Copy(); x.Set(GValue.GStrType, "exif-ifd2-UserComment", "hello world"); filename = Helper.GetTemporaryFile(_tempDir, ".jpg"); x.WriteToFile(filename); x = Image.NewFromFile(filename); y = x.Get("exif-ifd2-UserComment"); // can't use Assert.Equal since the string will have an extra " (xx, yy, zz)" // format area at the end Assert.StartsWith("hello world", (string)y); } } }
public void TestTiff() { Skip.IfNot(Helper.Have("tiffload") && File.Exists(Helper.TifFile), "no tiff support, skipping test"); void TiffValid(Image im) { var a = im[10, 10]; Assert.Equal(new[] { 38671.0, 33914.0, 26762.0 }, a); Assert.Equal(290, im.Width); Assert.Equal(442, im.Height); Assert.Equal(3, im.Bands); } FileLoader("tiffload", Helper.TifFile, TiffValid); BufferLoader("tiffload_buffer", Helper.TifFile, TiffValid); if (NetVips.AtLeastLibvips(8, 5)) { SaveLoadBuffer("tiffsave_buffer", "tiffload_buffer", _colour); } SaveLoad("%s.tif", _mono); SaveLoad("%s.tif", _colour); SaveLoad("%s.tif", _cmyk); SaveLoad("%s.tif", _oneBit); SaveLoadFile(".tif", "[squash]", _oneBit); SaveLoadFile(".tif", "[miniswhite]", _oneBit); SaveLoadFile(".tif", "[squash,miniswhite]", _oneBit); SaveLoadFile(".tif", $"[profile={Helper.SrgbFile}]", _colour); SaveLoadFile(".tif", "[tile]", _colour); SaveLoadFile(".tif", "[tile,pyramid]", _colour); SaveLoadFile(".tif", "[tile,pyramid,compression=jpeg]", _colour, 80); SaveLoadFile(".tif", "[bigtiff]", _colour); SaveLoadFile(".tif", "[compression=jpeg]", _colour, 80); SaveLoadFile(".tif", "[tile,tile-width=256]", _colour, 10); var filename = Helper.GetTemporaryFile(_tempDir, ".tif"); var x = Image.NewFromFile(Helper.TifFile); x = x.Copy(); x.Set("orientation", 2); x.WriteToFile(filename); x = Image.NewFromFile(filename); var y = x.Get("orientation"); Assert.Equal(2, y); filename = Helper.GetTemporaryFile(_tempDir, ".tif"); x = Image.NewFromFile(Helper.TifFile); x = x.Copy(); x.Set("orientation", 2); x.WriteToFile(filename); x = Image.NewFromFile(filename); y = x.Get("orientation"); Assert.Equal(2, y); x = x.Copy(); x.Remove("orientation"); filename = Helper.GetTemporaryFile(_tempDir, ".tif"); x.WriteToFile(filename); x = Image.NewFromFile(filename); y = x.Get("orientation"); Assert.Equal(1, y); filename = Helper.GetTemporaryFile(_tempDir, ".tif"); x = Image.NewFromFile(Helper.TifFile); x = x.Copy(); x.Set("orientation", 6); x.WriteToFile(filename); var x1 = Image.NewFromFile(filename); var x2 = Image.NewFromFile(filename, kwargs: new VOption { { "autorotate", true } }); Assert.Equal(x1.Width, x2.Height); Assert.Equal(x1.Height, x2.Width); // OME support in 8.5 if (NetVips.AtLeastLibvips(8, 5)) { x = Image.NewFromFile(Helper.OmeFile); Assert.Equal(439, x.Width); Assert.Equal(167, x.Height); var pageHeight = x.Height; x = Image.NewFromFile(Helper.OmeFile, kwargs: new VOption { { "n", -1 } }); Assert.Equal(439, x.Width); Assert.Equal(pageHeight * 15, x.Height); x = Image.NewFromFile(Helper.OmeFile, kwargs: new VOption { { "page", 1 }, { "n", -1 } }); Assert.Equal(439, x.Width); Assert.Equal(pageHeight * 14, x.Height); x = Image.NewFromFile(Helper.OmeFile, kwargs: new VOption { { "page", 1 }, { "n", 2 } }); Assert.Equal(439, x.Width); Assert.Equal(pageHeight * 2, x.Height); x = Image.NewFromFile(Helper.OmeFile, kwargs: new VOption { { "n", -1 } }); Assert.Equal(96, x[0, 166][0]); Assert.Equal(0, x[0, 167][0]); Assert.Equal(1, x[0, 168][0]); filename = Helper.GetTemporaryFile(_tempDir, ".tif"); x.WriteToFile(filename); x = Image.NewFromFile(filename, kwargs: new VOption { { "n", -1 } }); Assert.Equal(439, x.Width); Assert.Equal(pageHeight * 15, x.Height); Assert.Equal(96, x[0, 166][0]); Assert.Equal(0, x[0, 167][0]); Assert.Equal(1, x[0, 168][0]); } // pyr save to buffer added in 8.6 if (NetVips.AtLeastLibvips(8, 6)) { x = Image.NewFromFile(Helper.TifFile); var buf = x.TiffsaveBuffer(tile: true, pyramid: true); filename = Helper.GetTemporaryFile(_tempDir, ".tif"); x.Tiffsave(filename, tile: true, pyramid: true); var buf2 = File.ReadAllBytes(filename); Assert.Equal(buf.Length, buf2.Length); var a = Image.NewFromBuffer(buf, kwargs: new VOption { { "page", 2 } }); var b = Image.NewFromBuffer(buf2, kwargs: new VOption { { "page", 2 } }); Assert.Equal(a.Width, b.Width); Assert.Equal(a.Height, b.Height); Assert.Equal(a.Avg(), b.Avg()); } // region-shrink added in 8.7 if (NetVips.AtLeastLibvips(8, 7)) { x = Image.NewFromFile(Helper.TifFile); _ = x.TiffsaveBuffer(tile: true, pyramid: true, regionShrink: "mean"); _ = x.TiffsaveBuffer(tile: true, pyramid: true, regionShrink: "mode"); _ = x.TiffsaveBuffer(tile: true, pyramid: true, regionShrink: "median"); } }
public void TestMagickLoad() { Skip.IfNot(Helper.Have("magickload") && File.Exists(Helper.BmpFile), "no magick support, skipping test"); void BmpValid(Image im) { var a = im[100, 100]; Helper.AssertAlmostEqualObjects(new double[] { 227, 216, 201 }, a); Assert.Equal(1419, im.Width); Assert.Equal(1001, im.Height); } FileLoader("magickload", Helper.BmpFile, BmpValid); BufferLoader("magickload_buffer", Helper.BmpFile, BmpValid); // we should have rgb or rgba for svg files ... different versions of // IM handle this differently. GM even gives 1 band. var x = Image.Magickload(Helper.SvgFile); Assert.True(x.Bands == 3 || x.Bands == 4 || x.Bands == 1); // density should change size of generated svg x = Image.Magickload(Helper.SvgFile, density: "100"); var width = x.Width; var height = x.Height; // This seems to fail on travis, no idea why, some problem in their IM // perhaps //x = Image.Magickload(Helper.SvgFile, density: "200"); //Assert.Equal(width * 2, x.Width); //Assert.Equal(height * 2, x.Height); // page/n let you pick a range of pages // 'n' param added in 8.5 if (NetVips.AtLeastLibvips(8, 5)) { x = Image.Magickload(Helper.GifAnimFile); width = x.Width; height = x.Height; x = Image.Magickload(Helper.GifAnimFile, page: 1, n: 2); Assert.Equal(width, x.Width); Assert.Equal(height * 2, x.Height); var pageHeight = x.Get("page-height"); Assert.Equal(height, pageHeight); } // should work for dicom x = Image.Magickload(Helper.DicomFile); Assert.Equal(128, x.Width); Assert.Equal(128, x.Height); // some IMs are 3 bands, some are 1, can't really test // Assert.Equal(1, x.Bands); // libvips has its own sniffer for ICO, test that // added in 8.7 if (NetVips.AtLeastLibvips(8, 7)) { var buf = File.ReadAllBytes(Helper.IcoFile); var im = Image.NewFromBuffer(buf); Assert.Equal(16, im.Width); Assert.Equal(16, im.Height); } }