refactor(#47): minor refactors, code normalization and test coverage

master
Tomas Aparicio 11 years ago
parent 6edd96ee41
commit ed4faadba6

@ -238,7 +238,7 @@ bimg.Write("new.jpg", newImage)
Run the process passing the `DEBUG` environment variable
```
DEBUG=* ./app
DEBUG=bimg ./app
```
Enable libvips traces (note that a lot of data will be written in stdout):
@ -248,6 +248,12 @@ VIPS_TRACE=1 ./app
### Programmatic API
#### func ColourspaceIsSupported
```go
func ColourspaceIsSupported(buf []byte) (bool, error)
```
Check in the image colourspace is supported by libvips
#### func DetermineImageTypeName
@ -295,7 +301,7 @@ func Resize(buf []byte, o Options) ([]byte, error)
```go
func Shutdown()
```
Thread-safe function to shutdown libvips. You could call this to drop caches as
Thread-safe function to shutdown libvips. You can call this to drop caches as
well. If libvips was already initialized, the function is no-op
#### func VipsDebugInfo
@ -383,6 +389,20 @@ func NewImage(buf []byte) *Image
```
Creates a new image
#### func (*Image) Colourspace
```go
func (i *Image) Colourspace(c Interpretation) ([]byte, error)
```
Colour space conversion
#### func (*Image) ColourspaceIsSupported
```go
func (i *Image) ColourspaceIsSupported() (bool, error)
```
Check if the current image has a valid colourspace
#### func (*Image) Convert
```go
@ -453,6 +473,14 @@ func (i *Image) Image() []byte
```
Get image buffer
#### func (*Image) Interpretation
```go
func (i *Image) Interpretation() (Interpretation, error)
```
Get the image interpretation type See:
http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation
#### func (*Image) Metadata
```go
@ -533,6 +561,7 @@ type ImageMetadata struct {
Profile bool
Type string
Space string
Colourspace string
Size ImageSize
}
```
@ -609,6 +638,37 @@ const (
func (i Interpolator) String() string
```
#### type Interpretation
```go
type Interpretation int
```
Image interpretation type See:
http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation
```go
const (
INTERPRETATION_ERROR Interpretation = C.VIPS_INTERPRETATION_ERROR
INTERPRETATION_MULTIBAND Interpretation = C.VIPS_INTERPRETATION_MULTIBAND
INTERPRETATION_B_W Interpretation = C.VIPS_INTERPRETATION_B_W
INTERPRETATION_CMYK Interpretation = C.VIPS_INTERPRETATION_CMYK
INTERPRETATION_RGB Interpretation = C.VIPS_INTERPRETATION_RGB
INTERPRETATION_sRGB Interpretation = C.VIPS_INTERPRETATION_sRGB
INTERPRETATION_RGB16 Interpretation = C.VIPS_INTERPRETATION_RGB16
INTERPRETATION_GREY16 Interpretation = C.VIPS_INTERPRETATION_GREY16
INTERPRETATION_scRGB Interpretation = C.VIPS_INTERPRETATION_scRGB
)
```
#### func ImageInterpretation
```go
func ImageInterpretation(buf []byte) (Interpretation, error)
```
Get the image interpretation type See:
http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation
#### type Options
```go
@ -636,6 +696,7 @@ type Options struct {
Watermark Watermark
Type ImageType
Interpolator Interpolator
Interpretation Interpretation
}
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

@ -155,6 +155,17 @@ func (i *Image) Metadata() (ImageMetadata, error) {
return Metadata(i.buffer)
}
// Get the image interpretation type
// See: http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation
func (i *Image) Interpretation() (Interpretation, error) {
return ImageInterpretation(i.buffer)
}
// Check if the current image has a valid colourspace
func (i *Image) ColourspaceIsSupported() (bool, error) {
return ColourspaceIsSupported(i.buffer)
}
// Get image type format (jpeg, png, webp, tiff)
func (i *Image) Type() string {
return DetermineImageTypeName(i.buffer)

@ -262,12 +262,36 @@ func TestImageMetadata(t *testing.T) {
}
}
func TestInterpretation(t *testing.T) {
interpretation, err := initImage("test.jpg").Interpretation()
if err != nil {
t.Errorf("Cannot process the image: %#v", err)
}
if interpretation != INTERPRETATION_sRGB {
t.Errorf("Invalid interpretation: %d", interpretation)
}
}
func TestImageColourspaceBW(t *testing.T) {
buf, err := initImage("test.jpg").Colourspace(B_W)
buf, err := initImage("test.jpg").Colourspace(INTERPRETATION_B_W)
if err != nil {
t.Errorf("Cannot process the image: %#v", err)
}
interpretation, err := ImageInterpretation(buf)
if interpretation != INTERPRETATION_B_W {
t.Errorf("Invalid colourspace")
}
}
func TestImageColourspaceIsSupported(t *testing.T) {
supported, err := initImage("test.jpg").ColourspaceIsSupported()
if err != nil {
t.Errorf("Cannot process the image: %#v", err)
}
Write("fixtures/test_image_colourspace_b_w.jpg", buf)
if supported != true {
t.Errorf("Non-supported colourspace")
}
}
func TestFluentInterface(t *testing.T) {

@ -18,6 +18,7 @@ type ImageMetadata struct {
Profile bool
Type string
Space string
Colourspace string
Size ImageSize
}
@ -34,6 +35,17 @@ func Size(buf []byte) (ImageSize, error) {
}, nil
}
// Check in the image colourspace is supported by libvips
func ColourspaceIsSupported(buf []byte) (bool, error) {
return vipsColourspaceIsSupportedBuffer(buf)
}
// Get the image interpretation type
// See: http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation
func ImageInterpretation(buf []byte) (Interpretation, error) {
return vipsInterpretationBuffer(buf)
}
// Extract the image metadata (size, type, alpha channel, profile, EXIF orientation...)
func Metadata(buf []byte) (ImageMetadata, error) {
defer C.vips_thread_shutdown()

@ -38,9 +38,9 @@ func TestMetadata(t *testing.T) {
profile bool
space string
}{
{"test.jpg", "jpeg", 0, false, false, "bicubic"},
{"test.png", "png", 0, true, false, "bicubic"},
{"test.webp", "webp", 0, false, false, "bicubic"},
{"test.jpg", "jpeg", 0, false, false, "srgb"},
{"test.png", "png", 0, true, false, "srgb"},
{"test.webp", "webp", 0, false, false, "srgb"},
}
for _, file := range files {
@ -61,6 +61,58 @@ func TestMetadata(t *testing.T) {
if metadata.Profile != file.profile {
t.Fatalf("Unexpected image profile: %s != %s", metadata.Profile, file.profile)
}
if metadata.Space != file.space {
t.Fatalf("Unexpected image profile: %s != %s", metadata.Profile, file.profile)
}
}
}
func TestImageInterpretation(t *testing.T) {
files := []struct {
name string
interpretation Interpretation
}{
{"test.jpg", INTERPRETATION_sRGB},
{"test.png", INTERPRETATION_sRGB},
{"test.webp", INTERPRETATION_sRGB},
}
for _, file := range files {
interpretation, err := ImageInterpretation(readFile(file.name))
if err != nil {
t.Fatalf("Cannot read the image: %s -> %s", file.name, err)
}
if interpretation != file.interpretation {
t.Fatalf("Unexpected image interpretation")
}
}
}
func TestColourspaceIsSupported(t *testing.T) {
files := []struct {
name string
}{
{"test.jpg"},
{"test.png"},
{"test.webp"},
}
for _, file := range files {
supported, err := ColourspaceIsSupported(readFile(file.name))
if err != nil {
t.Fatalf("Cannot read the image: %s -> %s", file.name, err)
}
if supported != true {
t.Fatalf("Unsupported image colourspace")
}
}
supported, err := initImage("test.jpg").ColourspaceIsSupported()
if err != nil {
t.Errorf("Cannot process the image: %#v", err)
}
if supported != true {
t.Errorf("Non-supported colourspace")
}
}

@ -55,18 +55,20 @@ const (
VERTICAL Direction = C.VIPS_DIRECTION_VERTICAL
)
// Image interpretation type
// See: http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation
type Interpretation int
const (
ERROR Interpretation = C.VIPS_INTERPRETATION_ERROR
MULTIBAND Interpretation = C.VIPS_INTERPRETATION_MULTIBAND
B_W Interpretation = C.VIPS_INTERPRETATION_B_W
CMYK Interpretation = C.VIPS_INTERPRETATION_CMYK
RGB Interpretation = C.VIPS_INTERPRETATION_RGB
sRGB Interpretation = C.VIPS_INTERPRETATION_sRGB
RGB16 Interpretation = C.VIPS_INTERPRETATION_RGB16
GREY16 Interpretation = C.VIPS_INTERPRETATION_GREY16
scRGB Interpretation = C.VIPS_INTERPRETATION_scRGB
INTERPRETATION_ERROR Interpretation = C.VIPS_INTERPRETATION_ERROR
INTERPRETATION_MULTIBAND Interpretation = C.VIPS_INTERPRETATION_MULTIBAND
INTERPRETATION_B_W Interpretation = C.VIPS_INTERPRETATION_B_W
INTERPRETATION_CMYK Interpretation = C.VIPS_INTERPRETATION_CMYK
INTERPRETATION_RGB Interpretation = C.VIPS_INTERPRETATION_RGB
INTERPRETATION_sRGB Interpretation = C.VIPS_INTERPRETATION_sRGB
INTERPRETATION_RGB16 Interpretation = C.VIPS_INTERPRETATION_RGB16
INTERPRETATION_GREY16 Interpretation = C.VIPS_INTERPRETATION_GREY16
INTERPRETATION_scRGB Interpretation = C.VIPS_INTERPRETATION_scRGB
)
const WATERMARK_FONT = "sans 10"

@ -125,7 +125,7 @@ func Resize(buf []byte, o Options) ([]byte, error) {
Interpretation: o.Interpretation,
}
// Finally save as buffer
// Finally get the resultant buffer
buf, err = vipsSave(image, saveOptions)
if err != nil {
return nil, err
@ -145,7 +145,7 @@ func applyDefaults(o *Options, imageType ImageType) {
o.Type = imageType
}
if o.Interpretation == 0 {
o.Interpretation = sRGB
o.Interpretation = INTERPRETATION_sRGB
}
}

@ -224,41 +224,85 @@ func vipsRead(buf []byte) (*C.struct__VipsImage, ImageType, error) {
return image, imageType, nil
}
func vipsSave(image *C.struct__VipsImage, o vipsSaveOptions) ([]byte, error) {
length := C.size_t(0)
err := C.int(0)
interlace := C.int(boolToInt(o.Interlace))
if o.Interpretation == 0 {
o.Interpretation = sRGB
func vipsColourspaceIsSupportedBuffer(buf []byte) (bool, error) {
image, _, err := vipsRead(buf)
defer C.g_object_unref(C.gpointer(image))
if err != nil {
return false, err
}
interpretation := C.VipsInterpretation(o.Interpretation)
return vipsColourspaceIsSupported(image), nil
}
func vipsColourspaceIsSupported(image *C.struct__VipsImage) bool {
return int(C.vips_colourspace_issupported_bridge(image)) == 1
}
func vipsInterpretationBuffer(buf []byte) (Interpretation, error) {
image, _, err := vipsRead(buf)
defer C.g_object_unref(C.gpointer(image))
if err != nil {
return Interpretation(-1), err
}
return vipsInterpretation(image), nil
}
func vipsInterpretation(image *C.struct__VipsImage) Interpretation {
return Interpretation(C.vips_image_guess_interpretation_bridge(image))
}
func vipsPreSave(image *C.struct__VipsImage, o *vipsSaveOptions) (*C.struct__VipsImage, error) {
// Remove ICC profile metadata
if o.NoProfile {
C.remove_profile(image)
}
// Force RGB color space
// Use a default interpretation and cast it to C type
if o.Interpretation == 0 {
o.Interpretation = INTERPRETATION_sRGB
}
interpretation := C.VipsInterpretation(o.Interpretation)
// Apply the proper colour space
var outImage *C.struct__VipsImage
C.vips_colourspace_bridge(image, &outImage, interpretation)
if vipsColourspaceIsSupported(image) {
err := int(C.vips_colourspace_bridge(image, &outImage, interpretation))
C.g_object_unref(C.gpointer(image))
if err != 0 {
return nil, catchVipsError()
}
image = outImage
}
return image, nil
}
func vipsSave(image *C.struct__VipsImage, o vipsSaveOptions) ([]byte, error) {
defer C.g_object_unref(C.gpointer(image))
defer C.g_object_unref(C.gpointer(outImage))
image, err := vipsPreSave(image, &o)
if err != nil {
return nil, err
}
length := C.size_t(0)
saveErr := C.int(0)
interlace := C.int(boolToInt(o.Interlace))
quality := C.int(o.Quality)
var ptr unsafe.Pointer
switch o.Type {
case PNG:
err = C.vips_pngsave_bridge(outImage, &ptr, &length, 1, C.int(o.Compression), C.int(o.Quality), interlace)
break
case WEBP:
err = C.vips_webpsave_bridge(outImage, &ptr, &length, 1, C.int(o.Quality))
saveErr = C.vips_webpsave_bridge(image, &ptr, &length, 1, quality)
break
case PNG:
saveErr = C.vips_pngsave_bridge(image, &ptr, &length, 1, C.int(o.Compression), quality, interlace)
break
default:
err = C.vips_jpegsave_bridge(outImage, &ptr, &length, 1, C.int(o.Quality), interlace)
saveErr = C.vips_jpegsave_bridge(image, &ptr, &length, 1, quality, interlace)
break
}
if int(err) != 0 {
if int(saveErr) != 0 {
return nil, catchVipsError()
}

@ -134,6 +134,17 @@ vips_extract_area_bridge(VipsImage *in, VipsImage **out, int left, int top, int
return vips_extract_area(in, out, left, top, width, height, NULL);
};
int
vips_colourspace_issupported_bridge(VipsImage *in)
{
return vips_colourspace_issupported(in) ? 1 : 0;
};
VipsInterpretation
vips_image_guess_interpretation_bridge(VipsImage *in) {
return vips_image_guess_interpretation(in);
};
int
vips_colourspace_bridge(VipsImage *in, VipsImage **out, VipsInterpretation space)
{

Loading…
Cancel
Save