Skip to content

Commit

Permalink
Initial Resize Function
Browse files Browse the repository at this point in the history
  • Loading branch information
Leon Wolf committed Jan 28, 2020
1 parent a7b2d8c commit 9d58433
Show file tree
Hide file tree
Showing 5 changed files with 243 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@

# Dependency directories (remove the comment below to include it)
# vendor/

.idea/
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
153 changes: 151 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,151 @@
# canvas
A simple go library for transforming images using mostly native go functionalitys
# This package is no longer being updated! Please look for alternatives if that bothers you.

Resize
======

Image resizing for the [Go programming language](http://golang.org) with common interpolation methods.

[![Build Status](https://travis-ci.org/nfnt/resize.svg)](https://travis-ci.org/nfnt/resize)

Installation
------------

```bash
$ go get github.com/nfnt/resize
```

It's that easy!

Usage
-----

This package needs at least Go 1.1. Import package with

```go
import "github.com/nfnt/resize"
```

The resize package provides 2 functions:

* `resize.Resize` creates a scaled image with new dimensions (`width`, `height`) using the interpolation function `interp`.
If either `width` or `height` is set to 0, it will be set to an aspect ratio preserving value.
* `resize.Thumbnail` downscales an image preserving its aspect ratio to the maximum dimensions (`maxWidth`, `maxHeight`).
It will return the original image if original sizes are smaller than the provided dimensions.

```go
resize.Resize(width, height uint, img image.Image, interp resize.InterpolationFunction) image.Image
resize.Thumbnail(maxWidth, maxHeight uint, img image.Image, interp resize.InterpolationFunction) image.Image
```

The provided interpolation functions are (from fast to slow execution time)

- `NearestNeighbor`: [Nearest-neighbor interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation)
- `Bilinear`: [Bilinear interpolation](http://en.wikipedia.org/wiki/Bilinear_interpolation)
- `Bicubic`: [Bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation)
- `MitchellNetravali`: [Mitchell-Netravali interpolation](http://dl.acm.org/citation.cfm?id=378514)
- `Lanczos2`: [Lanczos resampling](http://en.wikipedia.org/wiki/Lanczos_resampling) with a=2
- `Lanczos3`: [Lanczos resampling](http://en.wikipedia.org/wiki/Lanczos_resampling) with a=3

Which of these methods gives the best results depends on your use case.

Sample usage:

```go
package main

import (
"github.com/nfnt/resize"
"image/jpeg"
"log"
"os"
)

func main() {
// open "test.jpg"
file, err := os.Open("test.jpg")
if err != nil {
log.Fatal(err)
}

// decode jpeg into image.Image
img, err := jpeg.Decode(file)
if err != nil {
log.Fatal(err)
}
file.Close()

// resize to width 1000 using Lanczos resampling
// and preserve aspect ratio
m := resize.Resize(1000, 0, img, resize.Lanczos3)

out, err := os.Create("test_resized.jpg")
if err != nil {
log.Fatal(err)
}
defer out.Close()

// write new image to file
jpeg.Encode(out, m, nil)
}
```

Caveats
-------

* Optimized access routines are used for `image.RGBA`, `image.NRGBA`, `image.RGBA64`, `image.NRGBA64`, `image.YCbCr`, `image.Gray`, and `image.Gray16` types. All other image types are accessed in a generic way that will result in slow processing speed.
* JPEG images are stored in `image.YCbCr`. This image format stores data in a way that will decrease processing speed. A resize may be up to 2 times slower than with `image.RGBA`.


Downsizing Samples
-------

Downsizing is not as simple as it might look like. Images have to be filtered before they are scaled down, otherwise aliasing might occur.
Filtering is highly subjective: Applying too much will blur the whole image, too little will make aliasing become apparent.
Resize tries to provide sane defaults that should suffice in most cases.

### Artificial sample

Original image
![Rings](http://nfnt.github.com/img/rings_lg_orig.png)

<table>
<tr>
<th><img src="http://nfnt.github.com/img/rings_300_NearestNeighbor.png" /><br>Nearest-Neighbor</th>
<th><img src="http://nfnt.github.com/img/rings_300_Bilinear.png" /><br>Bilinear</th>
</tr>
<tr>
<th><img src="http://nfnt.github.com/img/rings_300_Bicubic.png" /><br>Bicubic</th>
<th><img src="http://nfnt.github.com/img/rings_300_MitchellNetravali.png" /><br>Mitchell-Netravali</th>
</tr>
<tr>
<th><img src="http://nfnt.github.com/img/rings_300_Lanczos2.png" /><br>Lanczos2</th>
<th><img src="http://nfnt.github.com/img/rings_300_Lanczos3.png" /><br>Lanczos3</th>
</tr>
</table>

### Real-Life sample

Original image
![Original](http://nfnt.github.com/img/IMG_3694_720.jpg)

<table>
<tr>
<th><img src="http://nfnt.github.com/img/IMG_3694_300_NearestNeighbor.png" /><br>Nearest-Neighbor</th>
<th><img src="http://nfnt.github.com/img/IMG_3694_300_Bilinear.png" /><br>Bilinear</th>
</tr>
<tr>
<th><img src="http://nfnt.github.com/img/IMG_3694_300_Bicubic.png" /><br>Bicubic</th>
<th><img src="http://nfnt.github.com/img/IMG_3694_300_MitchellNetravali.png" /><br>Mitchell-Netravali</th>
</tr>
<tr>
<th><img src="http://nfnt.github.com/img/IMG_3694_300_Lanczos2.png" /><br>Lanczos2</th>
<th><img src="http://nfnt.github.com/img/IMG_3694_300_Lanczos3.png" /><br>Lanczos3</th>
</tr>
</table>


License
-------

Copyright (c) 2012 Jan Schlicht <[email protected]>
Resize is released under a MIT style license.
45 changes: 45 additions & 0 deletions resize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package canvas

import (
"golang.org/x/image/draw"
"image"
)

type InterpolationFunction int

// InterpolationFunction constants
const (
Bilinear InterpolationFunction = iota
CatmullRom
)

// kernal, returns an InterpolationFunctions taps and kernel.
func (i InterpolationFunction) kernel() *draw.Kernel {
switch i {
case Bilinear:
return draw.BiLinear
case CatmullRom:
return draw.CatmullRom
default:
return draw.CatmullRom
}
}

func Resize(img image.Image, width int, height int, intFunc InterpolationFunction) (image.Image, error) {

if width == 0 && height == 0 {
width = img.Bounds().Dx()
height = img.Bounds().Dy()
} else if width == 0 && height != 0 {
width = img.Bounds().Dx() / img.Bounds().Dy() * height
} else if width != 0 && height == 0 {
height = img.Bounds().Dy() / img.Bounds().Dx() * width
}
// new size of image
dstRect := image.Rect(0, 0, width, height)
// perform resizing
dstImg := image.NewRGBA(dstRect)
intFunc.kernel().Scale(dstImg, dstRect, img, img.Bounds(), draw.Over, nil)

return dstImg, nil
}
44 changes: 44 additions & 0 deletions resize_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package canvas

import (
"image"
"image/color"
"log"
"runtime"
"testing"
)

var img = image.NewNRGBA(image.Rect(0, 0, 5, 5))

func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
img.Set(5, 5, color.Black)
}

func Test_SameSize(t *testing.T) {
newImg, _ := Resize(img, 0, 0, CatmullRom)
if newImg.Bounds() != img.Bounds() {
log.Print(img.Bounds().Dx(), "x", img.Bounds().Dy())
log.Print(newImg.Bounds().Dx(), "x", newImg.Bounds().Dy())
t.Fail()
}
}

func Test_Height(t *testing.T) {
newImg, err := Resize(img, 0, 100, CatmullRom)
if err != nil || newImg.Bounds().Dy() != 100 || newImg.Bounds().Dx() != 100 {
t.Fail()
}
}
func Test_Width(t *testing.T) {
newImg, err := Resize(img, 200, 0, CatmullRom)
if err != nil || newImg.Bounds().Dy() != 200 || newImg.Bounds().Dx() != 200 {
t.Fail()
}
}
func Test_WidthAndHeight(t *testing.T) {
newImg, err := Resize(img, 300, 300, CatmullRom)
if err != nil || newImg.Bounds() != image.Rect(0, 0, 300, 300) {
t.Fail()
}
}

0 comments on commit 9d58433

Please sign in to comment.