Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cropping and creating thumbnails with Go

Tags:

go

Is there a way for me to crop an image with Go by giving dimensions and offsets?

I'm thinking of something flexible like this php function: http://php.net/manual/en/function.imagecopyresampled.php

I found this: https://github.com/nfnt/resize But that library does not seem to have an offset option.

I need to be able to crop any area of the original image. Not just scaling down, but also a different positioning of the cropped image.

Any suggestions on how I can achieve this?

like image 357
Aiden Avatar asked Sep 12 '15 23:09

Aiden


2 Answers

I'll answer my own question so that it can be of help to other newcomers of Go.

Reading these two articles helped me greatly to understand how to crop images in Go. No need for third libraries. You decide how to crop an image with points and rectangles which is a very neat way of doing it.

http://blog.golang.org/go-image-package

http://blog.golang.org/go-imagedraw-package

like image 130
Aiden Avatar answered Sep 26 '22 14:09

Aiden


Here's a simple program that crops an image. If chops off the image outside of a given rectangle.

package main

import (
    "fmt"
    "image"
    "log"
    "os"

    "image/png"
)

func main() {
    if err := run(); err != nil {
        log.Fatalln(err)
    }
}

func run() error {
    img, err := readImage("pic.png")
    if err != nil {
        return err
    }

    // I've hard-coded a crop rectangle, start (0,0), end (100, 100).
    img, err = cropImage(img, image.Rect(0, 0, 100, 100))
    if err != nil {
        return err
    }

    return writeImage(img, "pic-cropped.png")
}

// readImage reads a image file from disk. We're assuming the file will be png
// format.
func readImage(name string) (image.Image, error) {
    fd, err := os.Open("pic.png")
    if err != nil {
        return nil, err
    }
    defer fd.Close()

    // image.Decode requires that you import the right image package. We've
    // imported "image/png", so Decode will work for png files. If we needed to
    // decode jpeg files then we would need to import "image/jpeg".
    //
    // Ignored return value is image format name.
    img, _, err := image.Decode(fd)
    if err != nil {
        return nil, err
    }

    return img, nil
}

// cropImage takes an image and crops it to the specified rectangle.
func cropImage(img image.Image, crop image.Rectangle) (image.Image, error) {
    type subImager interface {
        SubImage(r image.Rectangle) image.Image
    }

    // img is an Image interface. This checks if the underlying value has a
    // method called SubImage. If it does, then we can use SubImage to crop the
    // image.
    simg, ok := img.(subImager)
    if !ok {
        return nil, fmt.Errorf("image does not support cropping")
    }

    return simg.SubImage(crop), nil
}

// writeImage writes an Image back to the disk.
func writeImage(img image.Image, name string) error {
    fd, err := os.Create(name)
    if err != nil {
        return err
    }
    defer fd.Close()

    return png.Encode(fd, img)
}
like image 42
425nesp Avatar answered Sep 25 '22 14:09

425nesp