feat(version): v1 release. see history for details

master
Tomas Aparicio 10 years ago
parent a0fc602e69
commit c57a8c1320

@ -1,10 +1,19 @@
language: go language: go
go: go:
- 1.6 - 1.6
- 1.5 - 1.5
- 1.4
- 1.3
- release
- tip - tip
script:
- diff -u <(echo -n) <(gofmt -s -d ./)
- diff -u <(echo -n) <(go vet ./)
- diff -u <(echo -n) <(golint ./)
- go test -v -race ./...
- go test -v -race -covermode=atomic -coverprofile=coverage.out
after_success:
- goveralls -coverprofile=coverage.out -service=travis-ci
before_install: before_install:
- curl -s https://raw.githubusercontent.com/lovell/sharp/master/preinstall.sh | sudo bash - - curl -s https://raw.githubusercontent.com/lovell/sharp/master/preinstall.sh | sudo bash -

@ -0,0 +1,5 @@
## 1.0.0 / 21-04-2016
- refactor(api): breaking changes: normalize public members to follow Go naming idioms.
- feat(version): bump to major version. API contract won't be compromised in `v1`.
- feat(docs): add missing inline godoc documentation.

@ -11,6 +11,9 @@ If you're looking for an HTTP based image processing solution, see [imaginary](h
bimg was heavily inspired in [sharp](https://github.com/lovell/sharp), its homologous package built for [node.js](http://nodejs.org). bimg was heavily inspired in [sharp](https://github.com/lovell/sharp), its homologous package built for [node.js](http://nodejs.org).
**v1 notice**: `bimg` introduces some minor breaking changes in `v1` release.
If you're using `gopkg.in`, you can still rely in the `v0` without worrying about breaking changes.
## Contents ## Contents
- [Supported image operations](#supported-image-operations) - [Supported image operations](#supported-image-operations)

@ -1,5 +0,0 @@
package bimg
import . "github.com/tj/go-debug"
var debug = Debug("bimg")

@ -2,10 +2,14 @@ package bimg
import "io/ioutil" import "io/ioutil"
// Read reads all the content of the given file path
// and returns it as byte buffer.
func Read(path string) ([]byte, error) { func Read(path string) ([]byte, error) {
return ioutil.ReadFile(path) return ioutil.ReadFile(path)
} }
// Write writes the given byte buffer into disk
// to the given file path.
func Write(path string, buf []byte) error { func Write(path string, buf []byte) error {
return ioutil.WriteFile(path, buf, 0644) return ioutil.WriteFile(path, buf, 0644)
} }

@ -1,16 +1,16 @@
package bimg package bimg
// Image encapsulates the whole image buffer // Image provides a simple method DSL to transform a given image as byte buffer.
type Image struct { type Image struct {
buffer []byte buffer []byte
} }
// Creates a new image // NewImage creates a new Image struct with method DSL.
func NewImage(buf []byte) *Image { func NewImage(buf []byte) *Image {
return &Image{buf} return &Image{buf}
} }
// Resize the image to fixed width and height // Resize resizes the image to fixed width and height.
func (i *Image) Resize(width, height int) ([]byte, error) { func (i *Image) Resize(width, height int) ([]byte, error) {
options := Options{ options := Options{
Width: width, Width: width,
@ -20,7 +20,7 @@ func (i *Image) Resize(width, height int) ([]byte, error) {
return i.Process(options) return i.Process(options)
} }
// Force resize with custom size (aspect ratio won't be maintained) // ForceResize resizes with custom size (aspect ratio won't be maintained).
func (i *Image) ForceResize(width, height int) ([]byte, error) { func (i *Image) ForceResize(width, height int) ([]byte, error) {
options := Options{ options := Options{
Width: width, Width: width,
@ -30,7 +30,7 @@ func (i *Image) ForceResize(width, height int) ([]byte, error) {
return i.Process(options) return i.Process(options)
} }
// Resize the image to fixed width and height with additional crop transformation // ResizeAndCrop resizes the image to fixed width and height with additional crop transformation.
func (i *Image) ResizeAndCrop(width, height int) ([]byte, error) { func (i *Image) ResizeAndCrop(width, height int) ([]byte, error) {
options := Options{ options := Options{
Width: width, Width: width,
@ -41,7 +41,7 @@ func (i *Image) ResizeAndCrop(width, height int) ([]byte, error) {
return i.Process(options) return i.Process(options)
} }
// Extract area from the by X/Y axis // Extract area from the by X/Y axis in the current image.
func (i *Image) Extract(top, left, width, height int) ([]byte, error) { func (i *Image) Extract(top, left, width, height int) ([]byte, error) {
options := Options{ options := Options{
Top: top, Top: top,
@ -57,7 +57,7 @@ func (i *Image) Extract(top, left, width, height int) ([]byte, error) {
return i.Process(options) return i.Process(options)
} }
// Enlarge the image by width and height. Aspect ratio is maintained // Enlarge enlarges the image by width and height. Aspect ratio is maintained.
func (i *Image) Enlarge(width, height int) ([]byte, error) { func (i *Image) Enlarge(width, height int) ([]byte, error) {
options := Options{ options := Options{
Width: width, Width: width,
@ -67,7 +67,7 @@ func (i *Image) Enlarge(width, height int) ([]byte, error) {
return i.Process(options) return i.Process(options)
} }
// Enlarge the image by width and height with additional crop transformation // EnlargeAndCrop enlarges the image by width and height with additional crop transformation.
func (i *Image) EnlargeAndCrop(width, height int) ([]byte, error) { func (i *Image) EnlargeAndCrop(width, height int) ([]byte, error) {
options := Options{ options := Options{
Width: width, Width: width,
@ -78,7 +78,7 @@ func (i *Image) EnlargeAndCrop(width, height int) ([]byte, error) {
return i.Process(options) return i.Process(options)
} }
// Crop the image to the exact size specified // Crop crops the image to the exact size specified.
func (i *Image) Crop(width, height int, gravity Gravity) ([]byte, error) { func (i *Image) Crop(width, height int, gravity Gravity) ([]byte, error) {
options := Options{ options := Options{
Width: width, Width: width,
@ -89,7 +89,7 @@ func (i *Image) Crop(width, height int, gravity Gravity) ([]byte, error) {
return i.Process(options) return i.Process(options)
} }
// Crop an image by width (auto height) // CropByWidth crops an image by width only param (auto height).
func (i *Image) CropByWidth(width int) ([]byte, error) { func (i *Image) CropByWidth(width int) ([]byte, error) {
options := Options{ options := Options{
Width: width, Width: width,
@ -98,7 +98,7 @@ func (i *Image) CropByWidth(width int) ([]byte, error) {
return i.Process(options) return i.Process(options)
} }
// Crop an image by height (auto width) // CropByHeight crops an image by height (auto width).
func (i *Image) CropByHeight(height int) ([]byte, error) { func (i *Image) CropByHeight(height int) ([]byte, error) {
options := Options{ options := Options{
Height: height, Height: height,
@ -107,7 +107,7 @@ func (i *Image) CropByHeight(height int) ([]byte, error) {
return i.Process(options) return i.Process(options)
} }
// Thumbnail the image by the a given width by aspect ratio 4:4 // Thumbnail creates a thumbnail of the image by the a given width by aspect ratio 4:4.
func (i *Image) Thumbnail(pixels int) ([]byte, error) { func (i *Image) Thumbnail(pixels int) ([]byte, error) {
options := Options{ options := Options{
Width: pixels, Width: pixels,
@ -118,50 +118,52 @@ func (i *Image) Thumbnail(pixels int) ([]byte, error) {
return i.Process(options) return i.Process(options)
} }
// Add text as watermark on the given image // Watermark adds text as watermark on the given image.
func (i *Image) Watermark(w Watermark) ([]byte, error) { func (i *Image) Watermark(w Watermark) ([]byte, error) {
options := Options{Watermark: w} options := Options{Watermark: w}
return i.Process(options) return i.Process(options)
} }
// Zoom the image by the given factor. // Zoom zooms the image by the given factor.
// You should probably call Extract() before // You should probably call Extract() before.
func (i *Image) Zoom(factor int) ([]byte, error) { func (i *Image) Zoom(factor int) ([]byte, error) {
options := Options{Zoom: factor} options := Options{Zoom: factor}
return i.Process(options) return i.Process(options)
} }
// Rotate the image by given angle degrees (0, 90, 180 or 270) // Rotate rotates the image by given angle degrees (0, 90, 180 or 270).
func (i *Image) Rotate(a Angle) ([]byte, error) { func (i *Image) Rotate(a Angle) ([]byte, error) {
options := Options{Rotate: a} options := Options{Rotate: a}
return i.Process(options) return i.Process(options)
} }
// Flip the image about the vertical Y axis // Flip flips the image about the vertical Y axis.
func (i *Image) Flip() ([]byte, error) { func (i *Image) Flip() ([]byte, error) {
options := Options{Flip: true} options := Options{Flip: true}
return i.Process(options) return i.Process(options)
} }
// Flop the image about the horizontal X axis // Flop flops the image about the horizontal X axis.
func (i *Image) Flop() ([]byte, error) { func (i *Image) Flop() ([]byte, error) {
options := Options{Flop: true} options := Options{Flop: true}
return i.Process(options) return i.Process(options)
} }
// Convert image to another format // Convert converts image to another format.
func (i *Image) Convert(t ImageType) ([]byte, error) { func (i *Image) Convert(t ImageType) ([]byte, error) {
options := Options{Type: t} options := Options{Type: t}
return i.Process(options) return i.Process(options)
} }
// Colour space conversion // Colourspace performs a color space conversion bsaed on the given interpretation.
func (i *Image) Colourspace(c Interpretation) ([]byte, error) { func (i *Image) Colourspace(c Interpretation) ([]byte, error) {
options := Options{Interpretation: c} options := Options{Interpretation: c}
return i.Process(options) return i.Process(options)
} }
// Transform the image by custom options // Process processes the image based on the given transformation options,
// talking with libvips bindings accordingly and returning the resultant
// image buffer.
func (i *Image) Process(o Options) ([]byte, error) { func (i *Image) Process(o Options) ([]byte, error) {
image, err := Resize(i.buffer, o) image, err := Resize(i.buffer, o)
if err != nil { if err != nil {
@ -171,33 +173,34 @@ func (i *Image) Process(o Options) ([]byte, error) {
return image, nil return image, nil
} }
// Get image metadata (size, alpha channel, profile, EXIF rotation) // Metadata returns the image metadata (size, alpha channel, profile, EXIF rotation).
func (i *Image) Metadata() (ImageMetadata, error) { func (i *Image) Metadata() (ImageMetadata, error) {
return Metadata(i.buffer) return Metadata(i.buffer)
} }
// Get the image interpretation type // Interpretation gets the image interpretation type.
// See: http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation // See: http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation
func (i *Image) Interpretation() (Interpretation, error) { func (i *Image) Interpretation() (Interpretation, error) {
return ImageInterpretation(i.buffer) return ImageInterpretation(i.buffer)
} }
// Check if the current image has a valid colourspace // ColourspaceIsSupported checks if the current image
// color space is supported.
func (i *Image) ColourspaceIsSupported() (bool, error) { func (i *Image) ColourspaceIsSupported() (bool, error) {
return ColourspaceIsSupported(i.buffer) return ColourspaceIsSupported(i.buffer)
} }
// Get image type format (jpeg, png, webp, tiff) // Type returns the image type format (jpeg, png, webp, tiff).
func (i *Image) Type() string { func (i *Image) Type() string {
return DetermineImageTypeName(i.buffer) return DetermineImageTypeName(i.buffer)
} }
// Get image size // Size returns the image size as form of width and height pixels.
func (i *Image) Size() (ImageSize, error) { func (i *Image) Size() (ImageSize, error) {
return Size(i.buffer) return Size(i.buffer)
} }
// Get image buffer // Image returns the current resultant image image buffer.
func (i *Image) Image() []byte { func (i *Image) Image() []byte {
return i.buffer return i.buffer
} }

@ -91,7 +91,7 @@ func TestImageEnlargeAndCrop(t *testing.T) {
} }
func TestImageCrop(t *testing.T) { func TestImageCrop(t *testing.T) {
buf, err := initImage("test.jpg").Crop(800, 600, NORTH) buf, err := initImage("test.jpg").Crop(800, 600, GravityNorth)
if err != nil { if err != nil {
t.Errorf("Cannot process the image: %s", err) t.Errorf("Cannot process the image: %s", err)
} }
@ -148,7 +148,7 @@ func TestImageThumbnail(t *testing.T) {
func TestImageWatermark(t *testing.T) { func TestImageWatermark(t *testing.T) {
image := initImage("test.jpg") image := initImage("test.jpg")
_, err := image.Crop(800, 600, NORTH) _, err := image.Crop(800, 600, GravityNorth)
if err != nil { if err != nil {
t.Errorf("Cannot process the image: %#v", err) t.Errorf("Cannot process the image: %#v", err)
} }
@ -178,7 +178,7 @@ func TestImageWatermark(t *testing.T) {
func TestImageWatermarkNoReplicate(t *testing.T) { func TestImageWatermarkNoReplicate(t *testing.T) {
image := initImage("test.jpg") image := initImage("test.jpg")
_, err := image.Crop(800, 600, NORTH) _, err := image.Crop(800, 600, GravityNorth)
if err != nil { if err != nil {
t.Errorf("Cannot process the image: %s", err) t.Errorf("Cannot process the image: %s", err)
} }
@ -294,7 +294,7 @@ func TestInterpretation(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("Cannot process the image: %#v", err) t.Errorf("Cannot process the image: %#v", err)
} }
if interpretation != INTERPRETATION_sRGB { if interpretation != InterpretationSRGB {
t.Errorf("Invalid interpretation: %d", interpretation) t.Errorf("Invalid interpretation: %d", interpretation)
} }
} }
@ -304,8 +304,8 @@ func TestImageColourspace(t *testing.T) {
file string file string
interpretation Interpretation interpretation Interpretation
}{ }{
{"test.jpg", INTERPRETATION_sRGB}, {"test.jpg", InterpretationSRGB},
{"test.jpg", INTERPRETATION_B_W}, {"test.jpg", InterpretationBW},
} }
for _, test := range tests { for _, test := range tests {

@ -12,7 +12,7 @@ type ImageSize struct {
Height int Height int
} }
// ImageMedatada represents the basic metadata fields // ImageMetadata represents the basic metadata fields
type ImageMetadata struct { type ImageMetadata struct {
Orientation int Orientation int
Channels int Channels int
@ -24,7 +24,7 @@ type ImageMetadata struct {
Size ImageSize Size ImageSize
} }
// Get the image size by width and height pixels // Size returns the image size by width and height pixels.
func Size(buf []byte) (ImageSize, error) { func Size(buf []byte) (ImageSize, error) {
metadata, err := Metadata(buf) metadata, err := Metadata(buf)
if err != nil { if err != nil {
@ -37,18 +37,18 @@ func Size(buf []byte) (ImageSize, error) {
}, nil }, nil
} }
// Check in the image colourspace is supported by libvips // ColourspaceIsSupported checks if the image colourspace is supported by libvips.
func ColourspaceIsSupported(buf []byte) (bool, error) { func ColourspaceIsSupported(buf []byte) (bool, error) {
return vipsColourspaceIsSupportedBuffer(buf) return vipsColourspaceIsSupportedBuffer(buf)
} }
// Get the image interpretation type // ImageInterpretation returns the image interpretation type.
// See: http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation // See: http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation
func ImageInterpretation(buf []byte) (Interpretation, error) { func ImageInterpretation(buf []byte) (Interpretation, error) {
return vipsInterpretationBuffer(buf) return vipsInterpretationBuffer(buf)
} }
// Extract the image metadata (size, type, alpha channel, profile, EXIF orientation...) // Metadata returns the image metadata (size, type, alpha channel, profile, EXIF orientation...).
func Metadata(buf []byte) (ImageMetadata, error) { func Metadata(buf []byte) (ImageMetadata, error) {
defer C.vips_thread_shutdown() defer C.vips_thread_shutdown()

@ -72,9 +72,9 @@ func TestImageInterpretation(t *testing.T) {
name string name string
interpretation Interpretation interpretation Interpretation
}{ }{
{"test.jpg", INTERPRETATION_sRGB}, {"test.jpg", InterpretationSRGB},
{"test.png", INTERPRETATION_sRGB}, {"test.png", InterpretationSRGB},
{"test.webp", INTERPRETATION_sRGB}, {"test.webp", InterpretationSRGB},
} }
for _, file := range files { for _, file := range files {

@ -7,83 +7,115 @@ package bimg
import "C" import "C"
const ( const (
QUALITY = 80 // Quality defines the default JPEG quality to be used.
MAX_SIZE = 16383 Quality = 80
// MaxSize defines the maximum pixels width or height supported.
MaxSize = 16383
) )
// Gravity represents the image gravity value.
type Gravity int type Gravity int
const ( const (
CENTRE Gravity = iota // GravityCentre represents the centre value used for image gravity orientation.
NORTH GravityCentre Gravity = iota
EAST // GravityNorth represents the north value used for image gravity orientation.
SOUTH GravityNorth
WEST // GravityEast represents the east value used for image gravity orientation.
GravityEast
// GravitySouth represents the south value used for image gravity orientation.
GravitySouth
// GravityWest represents the west value used for image gravity orientation.
GravityWest
) )
// Interpolator represents the image interpolation value.
type Interpolator int type Interpolator int
const ( const (
BICUBIC Interpolator = iota // Bicubic interpolation value.
BILINEAR Bicubic Interpolator = iota
NOHALO // Bilinear interpolation value.
Bilinear
// Nohalo interpolation value.
Nohalo
) )
var interpolations = map[Interpolator]string{ var interpolations = map[Interpolator]string{
BICUBIC: "bicubic", Bicubic: "bicubic",
BILINEAR: "bilinear", Bilinear: "bilinear",
NOHALO: "nohalo", Nohalo: "nohalo",
} }
func (i Interpolator) String() string { func (i Interpolator) String() string {
return interpolations[i] return interpolations[i]
} }
// Angle represents the image rotation angle value.
type Angle int type Angle int
const ( const (
// D0 represents the rotation angle 0 degrees.
D0 Angle = 0 D0 Angle = 0
// D90 represents the rotation angle 90 degrees.
D90 Angle = 90 D90 Angle = 90
// D180 represents the rotation angle 180 degrees.
D180 Angle = 180 D180 Angle = 180
// D270 represents the rotation angle 270 degrees.
D270 Angle = 270 D270 Angle = 270
) )
// Direction represents the image direction value.
type Direction int type Direction int
const ( const (
HORIZONTAL Direction = C.VIPS_DIRECTION_HORIZONTAL // Horizontal represents the orizontal image direction value.
VERTICAL Direction = C.VIPS_DIRECTION_VERTICAL Horizontal Direction = C.VIPS_DIRECTION_HORIZONTAL
// Vertical represents the vertical image direction value.
Vertical Direction = C.VIPS_DIRECTION_VERTICAL
) )
// Image interpretation type // Interpretation represents the image interpretation type.
// See: http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation // See: http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation
type Interpretation int type Interpretation int
const ( const (
INTERPRETATION_ERROR Interpretation = C.VIPS_INTERPRETATION_ERROR // InterpretationError points to the libvips interpretation error type.
INTERPRETATION_MULTIBAND Interpretation = C.VIPS_INTERPRETATION_MULTIBAND InterpretationError Interpretation = C.VIPS_INTERPRETATION_ERROR
INTERPRETATION_B_W Interpretation = C.VIPS_INTERPRETATION_B_W // InterpretationMultiband points to its libvips interpretation equivalent type.
INTERPRETATION_CMYK Interpretation = C.VIPS_INTERPRETATION_CMYK InterpretationMultiband Interpretation = C.VIPS_INTERPRETATION_MULTIBAND
INTERPRETATION_RGB Interpretation = C.VIPS_INTERPRETATION_RGB // InterpretationBW points to its libvips interpretation equivalent type.
INTERPRETATION_sRGB Interpretation = C.VIPS_INTERPRETATION_sRGB InterpretationBW Interpretation = C.VIPS_INTERPRETATION_B_W
INTERPRETATION_RGB16 Interpretation = C.VIPS_INTERPRETATION_RGB16 // InterpretationCMYK points to its libvips interpretation equivalent type.
INTERPRETATION_GREY16 Interpretation = C.VIPS_INTERPRETATION_GREY16 InterpretationCMYK Interpretation = C.VIPS_INTERPRETATION_CMYK
INTERPRETATION_scRGB Interpretation = C.VIPS_INTERPRETATION_scRGB // InterpretationRGB points to its libvips interpretation equivalent type.
INTERPRETATION_LAB Interpretation = C.VIPS_INTERPRETATION_LAB InterpretationRGB Interpretation = C.VIPS_INTERPRETATION_RGB
INTERPRETATION_XYZ Interpretation = C.VIPS_INTERPRETATION_XYZ // InterpretationSRGB points to its libvips interpretation equivalent type.
InterpretationSRGB Interpretation = C.VIPS_INTERPRETATION_sRGB
// InterpretationRGB16 points to its libvips interpretation equivalent type.
InterpretationRGB16 Interpretation = C.VIPS_INTERPRETATION_RGB16
// InterpretationGREY16 points to its libvips interpretation equivalent type.
InterpretationGREY16 Interpretation = C.VIPS_INTERPRETATION_GREY16
// InterpretationScRGB points to its libvips interpretation equivalent type.
InterpretationScRGB Interpretation = C.VIPS_INTERPRETATION_scRGB
// InterpretationLAB points to its libvips interpretation equivalent type.
InterpretationLAB Interpretation = C.VIPS_INTERPRETATION_LAB
// InterpretationXYZ points to its libvips interpretation equivalent type.
InterpretationXYZ Interpretation = C.VIPS_INTERPRETATION_XYZ
) )
const WATERMARK_FONT = "sans 10" // WatermarkFont defines the default watermark font to be used.
var WatermarkFont = "sans 10"
// Color represents a traditional RGB color scheme // Color represents a traditional RGB color scheme.
type Color struct { type Color struct {
R, G, B uint8 R, G, B uint8
} }
// Shortcut to black RGB color representation // ColorBlack is a shortcut to black RGB color representation.
var ColorBlack = Color{0, 0, 0} var ColorBlack = Color{0, 0, 0}
// Text-based watermark configuration // Watermark represents the text-based watermark supported options.
type Watermark struct { type Watermark struct {
Width int Width int
DPI int DPI int
@ -95,11 +127,13 @@ type Watermark struct {
Background Color Background Color
} }
// GaussianBlur represents the gaussian image transformation values.
type GaussianBlur struct { type GaussianBlur struct {
Sigma float64 Sigma float64
MinAmpl float64 MinAmpl float64
} }
// Sharpen represents the image sharp transformation options.
type Sharpen struct { type Sharpen struct {
Radius int Radius int
X1 float64 X1 float64
@ -109,7 +143,7 @@ type Sharpen struct {
M2 float64 M2 float64
} }
// Supported image transformation options // Options represents the supported image transformation options.
type Options struct { type Options struct {
Height int Height int
Width int Width int

@ -11,6 +11,8 @@ import (
"math" "math"
) )
// Resize is used to transform a given image as byte buffer
// with the passed options.
func Resize(buf []byte, o Options) ([]byte, error) { func Resize(buf []byte, o Options) ([]byte, error) {
defer C.vips_thread_shutdown() defer C.vips_thread_shutdown()
@ -131,7 +133,7 @@ func Resize(buf []byte, o Options) ([]byte, error) {
func applyDefaults(o Options, imageType ImageType) Options { func applyDefaults(o Options, imageType ImageType) Options {
if o.Quality == 0 { if o.Quality == 0 {
o.Quality = QUALITY o.Quality = Quality
} }
if o.Compression == 0 { if o.Compression == 0 {
o.Compression = 6 o.Compression = 6
@ -140,7 +142,7 @@ func applyDefaults(o Options, imageType ImageType) Options {
o.Type = imageType o.Type = imageType
} }
if o.Interpretation == 0 { if o.Interpretation == 0 {
o.Interpretation = INTERPRETATION_sRGB o.Interpretation = InterpretationSRGB
} }
return o return o
} }
@ -224,7 +226,7 @@ func applyEffects(image *C.VipsImage, o Options) (*C.VipsImage, error) {
} }
func extractOrEmbedImage(image *C.VipsImage, o Options) (*C.VipsImage, error) { func extractOrEmbedImage(image *C.VipsImage, o Options) (*C.VipsImage, error) {
var err error = nil var err error
inWidth := int(image.Xsize) inWidth := int(image.Xsize)
inHeight := int(image.Ysize) inHeight := int(image.Ysize)
@ -278,9 +280,9 @@ func rotateAndFlipImage(image *C.VipsImage, o Options) (*C.VipsImage, bool, erro
} }
if o.Flip { if o.Flip {
direction = HORIZONTAL direction = Horizontal
} else if o.Flop { } else if o.Flop {
direction = VERTICAL direction = Vertical
} }
if direction != -1 { if direction != -1 {
@ -298,7 +300,7 @@ func watermakImage(image *C.VipsImage, w Watermark) (*C.VipsImage, error) {
// Defaults // Defaults
if w.Font == "" { if w.Font == "" {
w.Font = WATERMARK_FONT w.Font = WatermarkFont
} }
if w.Width == 0 { if w.Width == 0 {
w.Width = int(math.Floor(float64(image.Xsize / 6))) w.Width = int(math.Floor(float64(image.Xsize / 6)))
@ -420,15 +422,15 @@ func calculateCrop(inWidth, inHeight, outWidth, outHeight int, gravity Gravity)
left, top := 0, 0 left, top := 0, 0
switch gravity { switch gravity {
case NORTH: case GravityNorth:
left = (inWidth - outWidth + 1) / 2 left = (inWidth - outWidth + 1) / 2
case EAST: case GravityEast:
left = inWidth - outWidth left = inWidth - outWidth
top = (inHeight - outHeight + 1) / 2 top = (inHeight - outHeight + 1) / 2
case SOUTH: case GravitySouth:
left = (inWidth - outWidth + 1) / 2 left = (inWidth - outWidth + 1) / 2
top = inHeight - outHeight top = inHeight - outHeight
case WEST: case GravityWest:
top = (inHeight - outHeight + 1) / 2 top = (inHeight - outHeight + 1) / 2
default: default:
left = (inWidth - outWidth + 1) / 2 left = (inWidth - outWidth + 1) / 2

@ -1,17 +1,24 @@
package bimg package bimg
// ImageType represents an image type value.
type ImageType int type ImageType int
const ( const (
// UNKNOWN represents an unknow image type value.
UNKNOWN ImageType = iota UNKNOWN ImageType = iota
// JPEG represents the JPEG image type.
JPEG JPEG
// WEBP represents the WEBP image type.
WEBP WEBP
// PNG represents the PNG image type.
PNG PNG
// TIFF represents the TIFF image type.
TIFF TIFF
// MAGICK represents the libmagick compatible genetic image type.
MAGICK MAGICK
) )
// Pairs of image type and its name // ImageTypes stores as pairs of image types supported and its alias names.
var ImageTypes = map[ImageType]string{ var ImageTypes = map[ImageType]string{
JPEG: "jpeg", JPEG: "jpeg",
PNG: "png", PNG: "png",
@ -20,22 +27,22 @@ var ImageTypes = map[ImageType]string{
MAGICK: "magick", MAGICK: "magick",
} }
// Determines the image type format (jpeg, png, webp or tiff) // DetermineImageType determines the image type format (jpeg, png, webp or tiff)
func DetermineImageType(buf []byte) ImageType { func DetermineImageType(buf []byte) ImageType {
return vipsImageType(buf) return vipsImageType(buf)
} }
// Determines the image type format by name (jpeg, png, webp or tiff) // DetermineImageTypeName determines the image type format by name (jpeg, png, webp or tiff)
func DetermineImageTypeName(buf []byte) string { func DetermineImageTypeName(buf []byte) string {
return ImageTypeName(vipsImageType(buf)) return ImageTypeName(vipsImageType(buf))
} }
// Check if a given image type is supported // IsTypeSupported checks if a given image type is supported
func IsTypeSupported(t ImageType) bool { func IsTypeSupported(t ImageType) bool {
return ImageTypes[t] != "" return ImageTypes[t] != ""
} }
// Check if a given image type name is supported // IsTypeNameSupported checks if a given image type name is supported
func IsTypeNameSupported(t string) bool { func IsTypeNameSupported(t string) bool {
for _, name := range ImageTypes { for _, name := range ImageTypes {
if name == t { if name == t {
@ -45,6 +52,7 @@ func IsTypeNameSupported(t string) bool {
return false return false
} }
// ImageTypeName is used to get the human friendly name of an image format.
func ImageTypeName(t ImageType) string { func ImageTypeName(t ImageType) string {
imageType := ImageTypes[t] imageType := ImageTypes[t]
if imageType == "" { if imageType == "" {

@ -1,3 +1,4 @@
package bimg package bimg
const Version = "0.1.24" // Version represents the current package semantic version.
const Version = "1.0.0"

@ -14,11 +14,18 @@ import (
"strings" "strings"
"sync" "sync"
"unsafe" "unsafe"
d "github.com/tj/go-debug"
) )
// Current libvips version // debug is internally used to
var debug = d.Debug("bimg")
// VipsVersion exposes the current libvips semantic version
const VipsVersion = string(C.VIPS_VERSION) const VipsVersion = string(C.VIPS_VERSION)
// HasMagickSupport exposes if the current libvips compilation
// supports libmagick bindings.
const HasMagickSupport = int(C.VIPS_MAGICK_SUPPORT) == 1 const HasMagickSupport = int(C.VIPS_MAGICK_SUPPORT) == 1
const ( const (
@ -31,12 +38,14 @@ var (
initialized bool initialized bool
) )
// VipsMemoryInfo represents the memory stats provided by libvips.
type VipsMemoryInfo struct { type VipsMemoryInfo struct {
Memory int64 Memory int64
MemoryHighwater int64 MemoryHighwater int64
Allocations int64 Allocations int64
} }
// vipsSaveOptions represents the internal option used to talk with libvips.
type vipsSaveOptions struct { type vipsSaveOptions struct {
Quality int Quality int
Compression int Compression int
@ -64,8 +73,8 @@ func init() {
Initialize() Initialize()
} }
// Explicit thread-safe start of libvips. // Initialize is used to explicitly start libvips in thread-safe way.
// Only call this function if you previously shutdown libvips // Only call this function if you have previously turned off libvips.
func Initialize() { func Initialize() {
if C.VIPS_MAJOR_VERSION <= 7 && C.VIPS_MINOR_VERSION < 40 { if C.VIPS_MAJOR_VERSION <= 7 && C.VIPS_MINOR_VERSION < 40 {
panic("unsupported libvips version!") panic("unsupported libvips version!")
@ -99,7 +108,7 @@ func Initialize() {
initialized = true initialized = true
} }
// Thread-safe function to shutdown libvips. // Shutdown is used to shutdown libvips in a thread-safe way.
// You can call this to drop caches as well. // You can call this to drop caches as well.
// If libvips was already initialized, the function is no-op // If libvips was already initialized, the function is no-op
func Shutdown() { func Shutdown() {
@ -112,12 +121,12 @@ func Shutdown() {
} }
} }
// Output to stdout vips collected data. Useful for debugging // VipsDebugInfo outputs to stdout libvips collected data. Useful for debugging.
func VipsDebugInfo() { func VipsDebugInfo() {
C.im__print_all() C.im__print_all()
} }
// Get memory info stats from vips (cache size, memory allocs...) // VipsMemory gets memory info stats from libvips (cache size, memory allocs...)
func VipsMemory() VipsMemoryInfo { func VipsMemory() VipsMemoryInfo {
return VipsMemoryInfo{ return VipsMemoryInfo{
Memory: int64(C.vips_tracked_get_mem()), Memory: int64(C.vips_tracked_get_mem()),
@ -246,7 +255,7 @@ func vipsColourspaceIsSupported(image *C.VipsImage) bool {
func vipsInterpretationBuffer(buf []byte) (Interpretation, error) { func vipsInterpretationBuffer(buf []byte) (Interpretation, error) {
image, _, err := vipsRead(buf) image, _, err := vipsRead(buf)
if err != nil { if err != nil {
return INTERPRETATION_ERROR, err return InterpretationError, err
} }
C.g_object_unref(C.gpointer(image)) C.g_object_unref(C.gpointer(image))
return vipsInterpretation(image), nil return vipsInterpretation(image), nil
@ -284,7 +293,7 @@ func vipsPreSave(image *C.VipsImage, o *vipsSaveOptions) (*C.VipsImage, error) {
// Use a default interpretation and cast it to C type // Use a default interpretation and cast it to C type
if o.Interpretation == 0 { if o.Interpretation == 0 {
o.Interpretation = INTERPRETATION_sRGB o.Interpretation = InterpretationSRGB
} }
interpretation := C.VipsInterpretation(o.Interpretation) interpretation := C.VipsInterpretation(o.Interpretation)
@ -364,7 +373,7 @@ func vipsExtract(image *C.VipsImage, left, top, width, height int) (*C.VipsImage
var buf *C.VipsImage var buf *C.VipsImage
defer C.g_object_unref(C.gpointer(image)) defer C.g_object_unref(C.gpointer(image))
if width > MAX_SIZE || height > MAX_SIZE { if width > MaxSize || height > MaxSize {
return nil, errors.New("Maximum image size exceeded") return nil, errors.New("Maximum image size exceeded")
} }

Loading…
Cancel
Save