| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644 |
- package bimg
- import (
- "bytes"
- "crypto/md5"
- "image"
- "image/jpeg"
- "io/ioutil"
- "os"
- "path"
- "strconv"
- "testing"
- )
- func TestResize(t *testing.T) {
- options := Options{Width: 800, Height: 600}
- buf, _ := Read("fixtures/test.jpg")
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- if DetermineImageType(newImg) != JPEG {
- t.Fatal("Image is not jpeg")
- }
- size, _ := Size(newImg)
- if size.Height != options.Height || size.Width != options.Width {
- t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- Write("fixtures/test_out.jpg", newImg)
- }
- func TestResizeVerticalImage(t *testing.T) {
- tests := []struct {
- format ImageType
- options Options
- }{
- {JPEG, Options{Width: 800, Height: 600}},
- {JPEG, Options{Width: 1000, Height: 1000}},
- {JPEG, Options{Width: 1000, Height: 1500}},
- {JPEG, Options{Width: 1000}},
- {JPEG, Options{Height: 1500}},
- {JPEG, Options{Width: 100, Height: 50}},
- {JPEG, Options{Width: 2000, Height: 2000}},
- {JPEG, Options{Width: 500, Height: 1000}},
- {JPEG, Options{Width: 500}},
- {JPEG, Options{Height: 500}},
- {JPEG, Options{Crop: true, Width: 500, Height: 1000}},
- {JPEG, Options{Crop: true, Enlarge: true, Width: 2000, Height: 1400}},
- {JPEG, Options{Enlarge: true, Force: true, Width: 2000, Height: 2000}},
- {JPEG, Options{Force: true, Width: 2000, Height: 2000}},
- }
- buf, _ := Read("fixtures/vertical.jpg")
- for _, test := range tests {
- image, err := Resize(buf, test.options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", test.options, err)
- }
- if DetermineImageType(image) != test.format {
- t.Fatalf("Image format is invalid. Expected: %#v", test.format)
- }
- size, _ := Size(image)
- if test.options.Height > 0 && size.Height != test.options.Height {
- t.Fatalf("Invalid height: %d", size.Height)
- }
- if test.options.Width > 0 && size.Width != test.options.Width {
- t.Fatalf("Invalid width: %d", size.Width)
- }
- Write("fixtures/test_vertical_"+strconv.Itoa(test.options.Width)+"x"+strconv.Itoa(test.options.Height)+"_out.jpg", image)
- }
- }
- func TestResizeCustomSizes(t *testing.T) {
- tests := []struct {
- format ImageType
- options Options
- }{
- {JPEG, Options{Width: 800, Height: 600}},
- {JPEG, Options{Width: 1000, Height: 1000}},
- {JPEG, Options{Width: 100, Height: 50}},
- {JPEG, Options{Width: 2000, Height: 2000}},
- {JPEG, Options{Width: 500, Height: 1000}},
- {JPEG, Options{Width: 500}},
- {JPEG, Options{Height: 500}},
- {JPEG, Options{Crop: true, Width: 500, Height: 1000}},
- {JPEG, Options{Crop: true, Enlarge: true, Width: 2000, Height: 1400}},
- {JPEG, Options{Enlarge: true, Force: true, Width: 2000, Height: 2000}},
- {JPEG, Options{Force: true, Width: 2000, Height: 2000}},
- }
- buf, _ := Read("fixtures/test.jpg")
- for _, test := range tests {
- image, err := Resize(buf, test.options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", test.options, err)
- }
- if DetermineImageType(image) != test.format {
- t.Fatalf("Image format is invalid. Expected: %#v", test.format)
- }
- size, _ := Size(image)
- if test.options.Height > 0 && size.Height != test.options.Height {
- t.Fatalf("Invalid height: %d", size.Height)
- }
- if test.options.Width > 0 && size.Width != test.options.Width {
- t.Fatalf("Invalid width: %d", size.Width)
- }
- }
- }
- func TestResizePrecision(t *testing.T) {
- // see https://github.com/h2non/bimg/issues/99
- img := image.NewGray16(image.Rect(0, 0, 1920, 1080))
- input := &bytes.Buffer{}
- jpeg.Encode(input, img, nil)
- opts := Options{Width: 300}
- newImg, err := Resize(input.Bytes(), opts)
- if err != nil {
- t.Fatalf("Resize(imgData, %#v) error: %#v", opts, err)
- }
- size, _ := Size(newImg)
- if size.Width != opts.Width {
- t.Fatalf("Invalid width: %d", size.Width)
- }
- }
- func TestRotate(t *testing.T) {
- options := Options{Width: 800, Height: 600, Rotate: 270, Crop: true}
- buf, _ := Read("fixtures/test.jpg")
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- if DetermineImageType(newImg) != JPEG {
- t.Error("Image is not jpeg")
- }
- size, _ := Size(newImg)
- if size.Width != options.Width || size.Height != options.Height {
- t.Errorf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- Write("fixtures/test_rotate_out.jpg", newImg)
- }
- func TestInvalidRotateDegrees(t *testing.T) {
- options := Options{Width: 800, Height: 600, Rotate: 111, Crop: true}
- buf, _ := Read("fixtures/test.jpg")
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- if DetermineImageType(newImg) != JPEG {
- t.Errorf("Image is not jpeg")
- }
- size, _ := Size(newImg)
- if size.Width != options.Width || size.Height != options.Height {
- t.Errorf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- Write("fixtures/test_rotate_invalid_out.jpg", newImg)
- }
- func TestCorruptedImage(t *testing.T) {
- options := Options{Width: 800, Height: 600}
- buf, _ := Read("fixtures/corrupt.jpg")
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- if DetermineImageType(newImg) != JPEG {
- t.Fatal("Image is not jpeg")
- }
- size, _ := Size(newImg)
- if size.Height != options.Height || size.Width != options.Width {
- t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- Write("fixtures/test_corrupt_out.jpg", newImg)
- }
- func TestNoColorProfile(t *testing.T) {
- options := Options{Width: 800, Height: 600, NoProfile: true}
- buf, _ := Read("fixtures/test.jpg")
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- metadata, err := Metadata(newImg)
- if metadata.Profile == true {
- t.Fatal("Invalid profile data")
- }
- size, _ := Size(newImg)
- if size.Height != options.Height || size.Width != options.Width {
- t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- }
- func TestEmbedExtendColor(t *testing.T) {
- options := Options{Width: 400, Height: 600, Crop: false, Embed: true, Extend: ExtendWhite, Background: Color{255, 20, 10}}
- buf, _ := Read("fixtures/test_issue.jpg")
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- size, _ := Size(newImg)
- if size.Height != options.Height || size.Width != options.Width {
- t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- Write("fixtures/test_extend_white_out.jpg", newImg)
- }
- func TestEmbedExtendWithCustomColor(t *testing.T) {
- options := Options{Width: 400, Height: 600, Crop: false, Embed: true, Extend: 5, Background: Color{255, 20, 10}}
- buf, _ := Read("fixtures/test_issue.jpg")
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- size, _ := Size(newImg)
- if size.Height != options.Height || size.Width != options.Width {
- t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- Write("fixtures/test_extend_background_out.jpg", newImg)
- }
- func TestGaussianBlur(t *testing.T) {
- options := Options{Width: 800, Height: 600, GaussianBlur: GaussianBlur{Sigma: 5}}
- buf, _ := Read("fixtures/test.jpg")
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- size, _ := Size(newImg)
- if size.Height != options.Height || size.Width != options.Width {
- t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- Write("fixtures/test_gaussian_out.jpg", newImg)
- }
- func TestSharpen(t *testing.T) {
- options := Options{Width: 800, Height: 600, Sharpen: Sharpen{Radius: 1, X1: 1.5, Y2: 20, Y3: 50, M1: 1, M2: 2}}
- buf, _ := Read("fixtures/test.jpg")
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- size, _ := Size(newImg)
- if size.Height != options.Height || size.Width != options.Width {
- t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- Write("fixtures/test_sharpen_out.jpg", newImg)
- }
- func TestExtractWithDefaultAxis(t *testing.T) {
- options := Options{AreaWidth: 200, AreaHeight: 200}
- buf, _ := Read("fixtures/test.jpg")
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- size, _ := Size(newImg)
- if size.Height != options.AreaHeight || size.Width != options.AreaWidth {
- t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- Write("fixtures/test_extract_defaults_out.jpg", newImg)
- }
- func TestExtractCustomAxis(t *testing.T) {
- options := Options{Top: 100, Left: 100, AreaWidth: 200, AreaHeight: 200}
- buf, _ := Read("fixtures/test.jpg")
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- size, _ := Size(newImg)
- if size.Height != options.AreaHeight || size.Width != options.AreaWidth {
- t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- Write("fixtures/test_extract_custom_axis_out.jpg", newImg)
- }
- func TestConvert(t *testing.T) {
- width, height := 300, 240
- formats := [3]ImageType{PNG, WEBP, JPEG}
- files := []string{
- "test.jpg",
- "test.png",
- "test.webp",
- }
- for _, file := range files {
- img, err := os.Open("fixtures/" + file)
- if err != nil {
- t.Fatal(err)
- }
- buf, err := ioutil.ReadAll(img)
- if err != nil {
- t.Fatal(err)
- }
- img.Close()
- for _, format := range formats {
- options := Options{Width: width, Height: height, Crop: true, Type: format}
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- if DetermineImageType(newImg) != format {
- t.Fatal("Image is not png")
- }
- size, _ := Size(newImg)
- if size.Height != height || size.Width != width {
- t.Fatalf("Invalid image size: %dx%d", size.Width, size.Height)
- }
- }
- }
- }
- func TestResizePngWithTransparency(t *testing.T) {
- width, height := 300, 240
- options := Options{Width: width, Height: height, Crop: true}
- img, err := os.Open("fixtures/transparent.png")
- if err != nil {
- t.Fatal(err)
- }
- defer img.Close()
- buf, err := ioutil.ReadAll(img)
- if err != nil {
- t.Fatal(err)
- }
- newImg, err := Resize(buf, options)
- if err != nil {
- t.Errorf("Resize(imgData, %#v) error: %#v", options, err)
- }
- if DetermineImageType(newImg) != PNG {
- t.Fatal("Image is not png")
- }
- size, _ := Size(newImg)
- if size.Height != height || size.Width != width {
- t.Fatal("Invalid image size")
- }
- Write("fixtures/transparent_out.png", newImg)
- }
- func TestIfBothSmartCropOptionsAreIdentical(t *testing.T) {
- if !(VipsMajorVersion >= 8 && VipsMinorVersion > 4) {
- t.Skipf("Skipping this test, libvips doesn't meet version requirement %s > 8.4", VipsVersion)
- }
- benchmarkOptions := Options{Width: 100, Height: 100, Crop: true}
- smartCropOptions := Options{Width: 100, Height: 100, Crop: true, SmartCrop: true}
- gravityOptions := Options{Width: 100, Height: 100, Crop: true, Gravity: GravitySmart}
- testImg, err := os.Open("fixtures/northern_cardinal_bird.jpg")
- if err != nil {
- t.Fatal(err)
- }
- defer testImg.Close()
- testImgByte, err := ioutil.ReadAll(testImg)
- if err != nil {
- t.Fatal(err)
- }
- scImg, err := Resize(testImgByte, smartCropOptions)
- if err != nil {
- t.Fatal(err)
- }
- gImg, err := Resize(testImgByte, gravityOptions)
- if err != nil {
- t.Fatal(err)
- }
- benchmarkImg, err := Resize(testImgByte, benchmarkOptions)
- if err != nil {
- t.Fatal(err)
- }
- sch, gh, bh := md5.Sum(scImg), md5.Sum(gImg), md5.Sum(benchmarkImg)
- if gh == bh || sch == bh {
- t.Error("Expected both options produce a different result from a standard crop.")
- }
- if sch != gh {
- t.Errorf("Expected both options to result in the same output, %x != %x", sch, gh)
- }
- }
- func runBenchmarkResize(file string, o Options, b *testing.B) {
- buf, _ := Read(path.Join("fixtures", file))
- for n := 0; n < b.N; n++ {
- Resize(buf, o)
- }
- }
- func BenchmarkRotateJpeg(b *testing.B) {
- options := Options{Rotate: 180}
- runBenchmarkResize("test.jpg", options, b)
- }
- func BenchmarkResizeLargeJpeg(b *testing.B) {
- options := Options{
- Width: 800,
- Height: 600,
- }
- runBenchmarkResize("test.jpg", options, b)
- }
- func BenchmarkResizePng(b *testing.B) {
- options := Options{
- Width: 200,
- Height: 200,
- }
- runBenchmarkResize("test.png", options, b)
- }
- func BenchmarkResizeWebP(b *testing.B) {
- options := Options{
- Width: 200,
- Height: 200,
- }
- runBenchmarkResize("test.webp", options, b)
- }
- func BenchmarkConvertToJpeg(b *testing.B) {
- options := Options{Type: JPEG}
- runBenchmarkResize("test.png", options, b)
- }
- func BenchmarkConvertToPng(b *testing.B) {
- options := Options{Type: PNG}
- runBenchmarkResize("test.jpg", options, b)
- }
- func BenchmarkConvertToWebp(b *testing.B) {
- options := Options{Type: WEBP}
- runBenchmarkResize("test.jpg", options, b)
- }
- func BenchmarkCropJpeg(b *testing.B) {
- options := Options{
- Width: 800,
- Height: 600,
- }
- runBenchmarkResize("test.jpg", options, b)
- }
- func BenchmarkCropPng(b *testing.B) {
- options := Options{
- Width: 800,
- Height: 600,
- }
- runBenchmarkResize("test.png", options, b)
- }
- func BenchmarkCropWebP(b *testing.B) {
- options := Options{
- Width: 800,
- Height: 600,
- }
- runBenchmarkResize("test.webp", options, b)
- }
- func BenchmarkExtractJpeg(b *testing.B) {
- options := Options{
- Top: 100,
- Left: 50,
- AreaWidth: 600,
- AreaHeight: 480,
- }
- runBenchmarkResize("test.jpg", options, b)
- }
- func BenchmarkExtractPng(b *testing.B) {
- options := Options{
- Top: 100,
- Left: 50,
- AreaWidth: 600,
- AreaHeight: 480,
- }
- runBenchmarkResize("test.png", options, b)
- }
- func BenchmarkExtractWebp(b *testing.B) {
- options := Options{
- Top: 100,
- Left: 50,
- AreaWidth: 600,
- AreaHeight: 480,
- }
- runBenchmarkResize("test.webp", options, b)
- }
- func BenchmarkZoomJpeg(b *testing.B) {
- options := Options{Zoom: 1}
- runBenchmarkResize("test.jpg", options, b)
- }
- func BenchmarkZoomPng(b *testing.B) {
- options := Options{Zoom: 1}
- runBenchmarkResize("test.png", options, b)
- }
- func BenchmarkZoomWebp(b *testing.B) {
- options := Options{Zoom: 1}
- runBenchmarkResize("test.webp", options, b)
- }
- func BenchmarkWatermarkJpeg(b *testing.B) {
- options := Options{
- Watermark: Watermark{
- Text: "Chuck Norris (c) 2315",
- Opacity: 0.25,
- Width: 200,
- DPI: 100,
- Margin: 150,
- Font: "sans bold 12",
- Background: Color{255, 255, 255},
- },
- }
- runBenchmarkResize("test.jpg", options, b)
- }
- func BenchmarkWatermarPng(b *testing.B) {
- options := Options{
- Watermark: Watermark{
- Text: "Chuck Norris (c) 2315",
- Opacity: 0.25,
- Width: 200,
- DPI: 100,
- Margin: 150,
- Font: "sans bold 12",
- Background: Color{255, 255, 255},
- },
- }
- runBenchmarkResize("test.png", options, b)
- }
- func BenchmarkWatermarWebp(b *testing.B) {
- options := Options{
- Watermark: Watermark{
- Text: "Chuck Norris (c) 2315",
- Opacity: 0.25,
- Width: 200,
- DPI: 100,
- Margin: 150,
- Font: "sans bold 12",
- Background: Color{255, 255, 255},
- },
- }
- runBenchmarkResize("test.webp", options, b)
- }
- func BenchmarkWatermarkImageJpeg(b *testing.B) {
- watermark := readFile("transparent.png")
- options := Options{
- WatermarkImage: WatermarkImage{
- Buf: watermark,
- Opacity: 0.25,
- Left: 100,
- Top: 100,
- },
- }
- runBenchmarkResize("test.jpg", options, b)
- }
- func BenchmarkWatermarImagePng(b *testing.B) {
- watermark := readFile("transparent.png")
- options := Options{
- WatermarkImage: WatermarkImage{
- Buf: watermark,
- Opacity: 0.25,
- Left: 100,
- Top: 100,
- },
- }
- runBenchmarkResize("test.png", options, b)
- }
- func BenchmarkWatermarImageWebp(b *testing.B) {
- watermark := readFile("transparent.png")
- options := Options{
- WatermarkImage: WatermarkImage{
- Buf: watermark,
- Opacity: 0.25,
- Left: 100,
- Top: 100,
- },
- }
- runBenchmarkResize("test.webp", options, b)
- }
|