Parcourir la source

Add: thumbnail helper function

Dobrosław Żybort il y a 12 ans
Parent
commit
b744503c5c
2 fichiers modifiés avec 102 ajouts et 0 suppressions
  1. 55 0
      thumbnail.go
  2. 47 0
      thumbnail_test.go

+ 55 - 0
thumbnail.go

@@ -0,0 +1,55 @@
+/*
+Copyright (c) 2012, Jan Schlicht <jan.schlicht@gmail.com>
+
+Permission to use, copy, modify, and/or distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright notice
+and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+*/
+
+package resize
+
+import (
+	"image"
+)
+
+// Thumbnail will downscale provided image to max width and height preserving
+// original aspect ratio and using the interpolation function interp.
+// It will return original image, without processing it, if original sizes
+// are already smaller than provided constraints.
+func Thumbnail(maxWidth, maxHeight uint, img image.Image, interp InterpolationFunction) image.Image {
+	origBounds := img.Bounds()
+	origWidth := uint(origBounds.Dx())
+	origHeight := uint(origBounds.Dy())
+	newWidth, newHeight := origWidth, origHeight
+
+	// Return original image if it have same or smaller size as constraints
+	if maxWidth >= origWidth && maxHeight >= origHeight {
+		return img
+	}
+
+	// Preserve aspect ratio
+	if origWidth > maxWidth {
+		newHeight = uint(origHeight * maxWidth / origWidth)
+		if newHeight < 1 {
+			newHeight = 1
+		}
+		newWidth = maxWidth
+	}
+
+	if newHeight > maxHeight {
+		newWidth = uint(newWidth * maxHeight / newHeight)
+		if newWidth < 1 {
+			newWidth = 1
+		}
+		newHeight = maxHeight
+	}
+	return Resize(newWidth, newHeight, img, interp)
+}

+ 47 - 0
thumbnail_test.go

@@ -0,0 +1,47 @@
+package resize
+
+import (
+	"image"
+	"runtime"
+	"testing"
+)
+
+func init() {
+	runtime.GOMAXPROCS(runtime.NumCPU())
+}
+
+var thumbnailTests = []struct {
+	origWidth      int
+	origHeight     int
+	maxWidth       uint
+	maxHeight      uint
+	expectedWidth  uint
+	expectedHeight uint
+}{
+	{5, 5, 10, 10, 5, 5},
+	{10, 10, 5, 5, 5, 5},
+	{10, 50, 10, 10, 2, 10},
+	{50, 10, 10, 10, 10, 2},
+	{50, 100, 60, 90, 45, 90},
+	{120, 100, 60, 90, 60, 50},
+	{200, 250, 200, 150, 120, 150},
+}
+
+func TestThumbnail(t *testing.T) {
+	for i, tt := range thumbnailTests {
+		img := image.NewGray16(image.Rect(0, 0, tt.origWidth, tt.origHeight))
+
+		outImg := Thumbnail(tt.maxWidth, tt.maxHeight, img, NearestNeighbor)
+
+		newWidth := uint(outImg.Bounds().Dx())
+		newHeight := uint(outImg.Bounds().Dy())
+		if newWidth != tt.expectedWidth ||
+			newHeight != tt.expectedHeight {
+			t.Errorf("%d. Thumbnail(%v, %v, img, NearestNeighbor) => "+
+				"width: %v, height: %v, want width: %v, height: %v",
+				i, tt.maxWidth, tt.maxHeight,
+				newWidth, newHeight, tt.expectedWidth, tt.expectedHeight,
+			)
+		}
+	}
+}