feat(#3, #5): support image operations

master
Tomas Aparicio 11 years ago
parent 63f4b01c8d
commit 61997bc68b

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 64 KiB

@ -1,5 +1,11 @@
package bimg package bimg
/*
#cgo pkg-config: vips
#include "vips/vips.h"
*/
import "C"
const QUALITY = 80 const QUALITY = 80
type Gravity int type Gravity int
@ -16,6 +22,26 @@ func (i Interpolator) String() string {
return interpolations[i] return interpolations[i]
} }
type Rotation struct {
angle int
}
func (a Rotation) calculate() int {
angle := a.angle
divisor := angle % 90
if divisor != 0 {
angle = a.angle - divisor
}
return angle
}
type Direction int
const (
HORIZONTAL Direction = C.VIPS_DIRECTION_HORIZONTAL
VERTICAL Direction = C.VIPS_DIRECTION_VERTICAL
)
type Options struct { type Options struct {
Height int Height int
Width int Width int
@ -23,7 +49,9 @@ type Options struct {
Enlarge bool Enlarge bool
Extend int Extend int
Embed bool Embed bool
Interpolator Interpolator
Gravity Gravity
Quality int Quality int
Rotate int
Flip Direction
Gravity Gravity
Interpolator Interpolator
} }

@ -18,7 +18,6 @@ const (
func Resize(buf []byte, o Options) ([]byte, error) { func Resize(buf []byte, o Options) ([]byte, error) {
// detect (if possible) the file type // detect (if possible) the file type
defer C.vips_thread_shutdown() defer C.vips_thread_shutdown()
image, err := vipsRead(buf) image, err := vipsRead(buf)
@ -26,16 +25,6 @@ func Resize(buf []byte, o Options) ([]byte, error) {
return nil, err return nil, err
} }
//var tmpImage *C.struct__VipsImage
/*
// feed it
imageLength := C.size_t(len(buf))
imageBuf := unsafe.Pointer(&buf[0])
debug("buffer: %s", buf[0])
C.vips_jpegload_buffer_seq(imageBuf, imageLength, &image)
*/
// defaults // defaults
if o.Quality == 0 { if o.Quality == 0 {
o.Quality = QUALITY o.Quality = QUALITY
@ -46,7 +35,6 @@ func Resize(buf []byte, o Options) ([]byte, error) {
inHeight := int(image.Ysize) inHeight := int(image.Ysize)
// crop // crop
if o.Crop { if o.Crop {
left, top := calculateCrop(inWidth, inHeight, o.Width, o.Height, o.Gravity) left, top := calculateCrop(inWidth, inHeight, o.Width, o.Height, o.Gravity)
o.Width = int(math.Min(float64(inWidth), float64(o.Width))) o.Width = int(math.Min(float64(inWidth), float64(o.Width)))
@ -55,31 +43,16 @@ func Resize(buf []byte, o Options) ([]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
//err := C.vips_extract_area_0(image, &tmpImage, C.int(left), C.int(top), C.int(o.Width), C.int(o.Height))
//C.g_object_unref(C.gpointer(image))
//image = tmpImage
} }
// rotate // rotate
r := Rotation{180} if o.Rotate > 0 {
image, err = Rotate(image, r) image, err = Rotate(image, Rotation{o.Rotate})
if err != nil { if err != nil {
return nil, err return nil, err
}
} }
// Finally save
//var ptr unsafe.Pointer
//length := C.size_t(0)
//C.vips_jpegsave_custom(image, &ptr, &length, 1, C.int(o.Quality), 0)
//C.g_object_unref(C.gpointer(image))
//C.g_object_unref(C.gpointer(newImage))
// get back the buffer
//buf = C.GoBytes(ptr, C.int(length))
// cleanup
//C.g_free(C.gpointer(ptr))
buf, err = vipsSave(image, vipsSaveOptions{Quality: o.Quality}) buf, err = vipsSave(image, vipsSaveOptions{Quality: o.Quality})
if err != nil { if err != nil {
return nil, err return nil, err
@ -89,19 +62,6 @@ func Resize(buf []byte, o Options) ([]byte, error) {
return buf, nil return buf, nil
} }
type Rotation struct {
angle int
}
func (a Rotation) calculate() int {
angle := a.angle
divisor := angle % 90
if divisor != 0 {
angle = a.angle - divisor
}
return angle
}
func Rotate(image *C.struct__VipsImage, r Rotation) (*C.struct__VipsImage, error) { func Rotate(image *C.struct__VipsImage, r Rotation) (*C.struct__VipsImage, error) {
//vips := &Vips{} //vips := &Vips{}
return vipsRotate(image, r.calculate()) return vipsRotate(image, r.calculate())

@ -8,7 +8,7 @@ import (
) )
func TestResize(t *testing.T) { func TestResize(t *testing.T) {
options := Options{Width: 800, Height: 600, Crop: false} options := Options{Width: 800, Height: 600, Crop: false, Rotate: 270}
img, err := os.Open("fixtures/space.jpg") img, err := os.Open("fixtures/space.jpg")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

@ -1,5 +1,14 @@
package bimg package bimg
const (
UNKNOWN = "unknown"
JPEG = "jpeg"
WEBP = "webp"
PNG = "png"
TIFF = "tiff"
MAGICK = "magick"
)
type Type struct { type Type struct {
Name string Name string
Mime string Mime string

@ -9,6 +9,7 @@ import "C"
import ( import (
"errors" "errors"
"runtime" "runtime"
"strings"
"unsafe" "unsafe"
) )
@ -44,9 +45,24 @@ func vipsRotate(image *C.struct__VipsImage, degrees int) (*C.struct__VipsImage,
return out, nil return out, nil
} }
func vipsFlip(image *C.struct__VipsImage, direction Direction) (*C.struct__VipsImage, error) {
var out *C.struct__VipsImage
err := C.vips_flip_seq(image, &out)
C.g_object_unref(C.gpointer(image))
if err != 0 {
return nil, vipsError()
}
defer C.g_object_unref(C.gpointer(out))
return out, nil
}
func vipsRead(buf []byte) (*C.struct__VipsImage, error) { func vipsRead(buf []byte) (*C.struct__VipsImage, error) {
var image *C.struct__VipsImage var image *C.struct__VipsImage
debug("Format: %s", vipsImageType(buf))
// feed it // feed it
length := C.size_t(len(buf)) length := C.size_t(len(buf))
imageBuf := unsafe.Pointer(&buf[0]) imageBuf := unsafe.Pointer(&buf[0])
@ -75,6 +91,34 @@ type vipsSaveOptions struct {
Quality int Quality int
} }
func vipsImageType(buf []byte) string {
imageType := UNKNOWN
length := C.size_t(len(buf))
imageBuf := unsafe.Pointer(&buf[0])
bufferType := C.GoString(C.vips_foreign_find_load_buffer(imageBuf, length))
switch {
case strings.HasSuffix(bufferType, "JpegBuffer"):
imageType = JPEG
break
case strings.HasSuffix(bufferType, "PngBuffer"):
imageType = PNG
break
case strings.HasSuffix(bufferType, "TiffBuffer"):
imageType = TIFF
break
case strings.HasSuffix(bufferType, "WebpBuffer"):
imageType = WEBP
break
case strings.HasSuffix(bufferType, "MagickBuffer"):
imageType = MAGICK
break
}
return imageType
}
func vipsSave(image *C.struct__VipsImage, o vipsSaveOptions) ([]byte, error) { func vipsSave(image *C.struct__VipsImage, o vipsSaveOptions) ([]byte, error) {
var ptr unsafe.Pointer var ptr unsafe.Pointer
length := C.size_t(0) length := C.size_t(0)

@ -20,6 +20,13 @@ vips_jpegload_buffer_seq(void *buf, size_t len, VipsImage **out)
return vips_jpegload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL); return vips_jpegload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL);
}; };
VipsImage*
vips_image_buffer_seq(void *buf, size_t len)
{
// todo: handle postclose callback
return vips_image_new_from_buffer(buf, len, "access", VIPS_ACCESS_SEQUENTIAL, NULL);
};
int int
vips_jpegload_buffer_shrink(void *buf, size_t len, VipsImage **out, int shrink) vips_jpegload_buffer_shrink(void *buf, size_t len, VipsImage **out, int shrink)
{ {
@ -32,6 +39,12 @@ vips_webpload_buffer_seq(void *buf, size_t len, VipsImage **out)
return vips_webpload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL); return vips_webpload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL);
}; };
int
vips_flip_seq(VipsImage *in, VipsImage **out)
{
return vips_flip(in, out, VIPS_DIRECTION_HORIZONTAL, NULL);
};
int int
vips_pngload_buffer_seq(void *buf, size_t len, VipsImage **out) vips_pngload_buffer_seq(void *buf, size_t len, VipsImage **out)
{ {
@ -48,7 +61,7 @@ int
vips_copy_0(VipsImage *in, VipsImage **out) vips_copy_0(VipsImage *in, VipsImage **out)
{ {
return vips_copy(in, out, NULL); return vips_copy(in, out, NULL);
} };
int int
vips_rotate(VipsImage *in, VipsImage **buf, int angle) vips_rotate(VipsImage *in, VipsImage **buf, int angle)
@ -64,13 +77,13 @@ vips_rotate(VipsImage *in, VipsImage **buf, int angle)
} }
return vips_rot(in, buf, rotate, NULL); return vips_rot(in, buf, rotate, NULL);
} };
int int
vips_embed_extend(VipsImage *in, VipsImage **out, int left, int top, int width, int height, int extend) vips_embed_extend(VipsImage *in, VipsImage **out, int left, int top, int width, int height, int extend)
{ {
return vips_embed(in, out, left, top, width, height, "extend", extend, NULL); return vips_embed(in, out, left, top, width, height, "extend", extend, NULL);
} };
int int
vips_colourspace_0(VipsImage *in, VipsImage **out, VipsInterpretation space) vips_colourspace_0(VipsImage *in, VipsImage **out, VipsInterpretation space)
@ -82,10 +95,10 @@ int
vips_extract_area_0(VipsImage *in, VipsImage **out, int left, int top, int width, int height) vips_extract_area_0(VipsImage *in, VipsImage **out, int left, int top, int width, int height)
{ {
return vips_extract_area(in, out, left, top, width, height, NULL); return vips_extract_area(in, out, left, top, width, height, NULL);
} };
int int
vips_jpegsave_custom(VipsImage *in, void **buf, size_t *len, int strip, int quality, int interlace) vips_jpegsave_custom(VipsImage *in, void **buf, size_t *len, int strip, int quality, int interlace)
{ {
return vips_jpegsave_buffer(in, buf, len, "strip", strip, "Q", quality, "optimize_coding", TRUE, "interlace", interlace, NULL); return vips_jpegsave_buffer(in, buf, len, "strip", strip, "Q", quality, "optimize_coding", TRUE, "interlace", interlace, NULL);
} };

Loading…
Cancel
Save