Skip to content

Commit

Permalink
Merge 24a12ab into 2da4e08
Browse files Browse the repository at this point in the history
  • Loading branch information
Arimeka authored Nov 20, 2019
2 parents 2da4e08 + 24a12ab commit b82a495
Show file tree
Hide file tree
Showing 9 changed files with 389 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.git
.idea
.DS_Store
source/
77 changes: 76 additions & 1 deletion operation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package imgvips_test

import (
"errors"
"io/ioutil"
"log"
"testing"

Expand Down Expand Up @@ -47,6 +48,33 @@ func TestOperation_Exec(t *testing.T) {
save(t, resizeOut)
}

func TestOperation_ExecFromBytes(t *testing.T) {
imgvips.VipsDetectMemoryLeak(true)

out, loadOp := webpLoadBytes(t)
defer loadOp.Free()

resizeOut, resizeOp := resize(t, out)
defer resizeOp.Free()

save(t, resizeOut)
}

func TestOperation_ExecSaveToBytes(t *testing.T) {
imgvips.VipsDetectMemoryLeak(true)

out, loadOp := webpLoadBytes(t)
defer loadOp.Free()

resizeOut, resizeOp := resize(t, out)
defer resizeOp.Free()

bytes := saveToBytes(t, resizeOut)
if len(bytes) == 0 {
t.Fatal("Expected some data, got nil")
}
}

func webpLoad(t *testing.T) (*imgvips.GValue, *imgvips.Operation) {
op, err := imgvips.NewOperation("webpload")
if err != nil {
Expand All @@ -65,6 +93,29 @@ func webpLoad(t *testing.T) (*imgvips.GValue, *imgvips.Operation) {
return out, op
}

func webpLoadBytes(t *testing.T) (*imgvips.GValue, *imgvips.Operation) {
data, err := ioutil.ReadFile("./tests/fixtures/small.webp")
if err != nil {
t.Fatalf("Unexpected error %v", err)
}

op, err := imgvips.NewOperation("webpload_buffer")
if err != nil {
t.Fatalf("Unexpected error %v", err)
}

out := imgvips.GNullVipsImage()
op.AddInput("buffer", imgvips.GVipsBlob(data))
op.AddInput("scale", imgvips.GDouble(6))
op.AddOutput("out", out)

if err := op.Exec(); err != nil {
t.Fatalf("Unexpected error %v", err)
}

return out, op
}

func resize(t *testing.T, in *imgvips.GValue) (*imgvips.GValue, *imgvips.Operation) {
resizeOp, err := imgvips.NewOperation("resize")
if err != nil {
Expand Down Expand Up @@ -123,6 +174,30 @@ func save(t *testing.T, in *imgvips.GValue) {
}
}

func saveToBytes(t *testing.T, in *imgvips.GValue) []byte {
saveOp, err := imgvips.NewOperation("jpegsave_buffer")
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
defer saveOp.Free()

gData := imgvips.GNullVipsBlob()
saveOp.AddInput("in", in)
saveOp.AddInput("Q", imgvips.GInt(50))
saveOp.AddOutput("buffer", gData)

if err := saveOp.Exec(); err != nil {
t.Fatalf("Unexpected error %v", err)
}

data, ok := gData.Bytes()
if !ok {
t.Fatalf("Expected *C.VipsBlob")
}

return data
}

func BenchmarkOperation_Exec(b *testing.B) {
imgvips.VipsDetectMemoryLeak(true)

Expand Down Expand Up @@ -195,7 +270,7 @@ func BenchmarkOperation_Exec(b *testing.B) {
}
}

func ExampleOperation_Exec() {
func Example() {
op, err := imgvips.NewOperation("webpload")
if err != nil {
log.Println(err)
Expand Down
38 changes: 38 additions & 0 deletions tests/docker/vips-8.2.2/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
FROM ubuntu:xenial

RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
g++ \
gcc \
git \
libc6-dev \
make \
pkg-config \
wget \
libvips-dev=8.2.2-1 && \
rm -rf /var/lib/apt/lists/*

ENV GOLANG_VERSION 1.11.13

RUN wget -O go.tgz https://golang.org/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz && \
tar -C /usr/local -xzf go.tgz && rm go.tgz && \
export PATH="/usr/local/go/bin:$PATH" && \
go version

ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"

RUN go get golang.org/x/lint/golint && \
go get -v github.com/go-lintpack/lintpack/... && \
go get -v github.com/go-critic/go-critic/... && \
go get -v github.com/fzipp/gocyclo && \
go get -v github.com/gordonklaus/ineffassign && \
lintpack build -o $GOPATH/bin/gocritic -linter.name='gocritic' github.com/go-critic/go-critic/checkers

WORKDIR /test

COPY . .

CMD exec make test
38 changes: 38 additions & 0 deletions tests/docker/vips-8.4.5/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
FROM ubuntu:bionic

RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
g++ \
gcc \
git \
libc6-dev \
make \
pkg-config \
wget \
libvips-dev=8.4.5-1build1 && \
rm -rf /var/lib/apt/lists/*

ENV GOLANG_VERSION 1.11.13

RUN wget -O go.tgz https://golang.org/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz && \
tar -C /usr/local -xzf go.tgz && rm go.tgz && \
export PATH="/usr/local/go/bin:$PATH" && \
go version

ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"

RUN go get golang.org/x/lint/golint && \
go get -v github.com/go-lintpack/lintpack/... && \
go get -v github.com/go-critic/go-critic/... && \
go get -v github.com/fzipp/gocyclo && \
go get -v github.com/gordonklaus/ineffassign && \
lintpack build -o $GOPATH/bin/gocritic -linter.name='gocritic' github.com/go-critic/go-critic/checkers

WORKDIR /test

COPY . .

CMD exec make test
38 changes: 38 additions & 0 deletions tests/docker/vips-8.7.4/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
FROM ubuntu:disco

RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
g++ \
gcc \
git \
libc6-dev \
make \
pkg-config \
wget \
libvips-dev=8.7.4-1 && \
rm -rf /var/lib/apt/lists/*

ENV GOLANG_VERSION 1.11.13

RUN wget -O go.tgz https://golang.org/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz && \
tar -C /usr/local -xzf go.tgz && rm go.tgz && \
export PATH="/usr/local/go/bin:$PATH" && \
go version

ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"

RUN go get golang.org/x/lint/golint && \
go get -v github.com/go-lintpack/lintpack/... && \
go get -v github.com/go-critic/go-critic/... && \
go get -v github.com/fzipp/gocyclo && \
go get -v github.com/gordonklaus/ineffassign && \
lintpack build -o $GOPATH/bin/gocritic -linter.name='gocritic' github.com/go-critic/go-critic/checkers

WORKDIR /test

COPY . .

CMD exec make test
38 changes: 38 additions & 0 deletions tests/docker/vips-8.8.3/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
FROM ubuntu:focal

RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
g++ \
gcc \
git \
libc6-dev \
make \
pkg-config \
wget \
libvips-dev=8.8.3-3 && \
rm -rf /var/lib/apt/lists/*

ENV GOLANG_VERSION 1.11.13

RUN wget -O go.tgz https://golang.org/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz && \
tar -C /usr/local -xzf go.tgz && rm go.tgz && \
export PATH="/usr/local/go/bin:$PATH" && \
go version

ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"

RUN go get golang.org/x/lint/golint && \
go get -v github.com/go-lintpack/lintpack/... && \
go get -v github.com/go-critic/go-critic/... && \
go get -v github.com/fzipp/gocyclo && \
go get -v github.com/gordonklaus/ineffassign && \
lintpack build -o $GOPATH/bin/gocritic -linter.name='gocritic' github.com/go-critic/go-critic/checkers

WORKDIR /test

COPY . .

CMD exec make test
Binary file added tests/fixtures/small.webp
Binary file not shown.
96 changes: 96 additions & 0 deletions value.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ package imgvips
import "C"

import (
"errors"
"sync"
"unsafe"
)

var (
// ErrCopyForbidden returns when GValue forbid copy function
ErrCopyForbidden = errors.New("copy forbidden for this type")
)

// GValue contains glib gValue and its type
type GValue struct {
gType C.GType
Expand Down Expand Up @@ -68,6 +74,35 @@ func (v *GValue) Boolean() (value, ok bool) {
return true, true
}

// Bytes return bytes slice from GValue.
// It unset gValue after call, so for next call you get nil value
// If type not match, ok will return false.
// If VipsBlob already freed, return nil value, ok will be true.
func (v *GValue) Bytes() (value []byte, ok bool) {
v.mu.Lock()
defer v.mu.Unlock()

if v.gType != C.vips_blob_get_type() {
return nil, false
}
if v.gValue == nil {
return nil, true
}
ptr := C.g_value_peek_pointer(v.gValue)
if ptr == nil {
return nil, true
}

var gSize C.gsize
result := C.vips_blob_get((*C.VipsBlob)(ptr), &gSize)

// Copy data from *ptr and return []byte
// Better create []byte from *ptr address, but it kinda horrible
value = C.GoBytes(result, (C.int)(gSize))

return value, true
}

// Int return int gValue, if type is GInt.
// If type not match, ok will return false.
// If gValue already freed, gValue will be 0, ok will be true.
Expand Down Expand Up @@ -312,6 +347,67 @@ func GString(value string) *GValue {
return v
}

// GVipsBlob copy data to VipsBlob
// VipsBlob is used in load_buffer and save_buffer.
// VipsBlob is a boxed type, so we use g_value_set_boxed instead of g_value_set_object.
// Calling Copy() at GValue with type VipsBlob is forbidden.
func GVipsBlob(data []byte) *GValue {
v := GNullVipsBlob()
v.free = func(val *GValue) {
if val.gValue == nil {
return
}

ptr := C.g_value_peek_pointer(val.gValue)
if ptr != nil {
// VipsBlob can be freed like *C.VipsArea
C.vips_area_unref((*C.VipsArea)(ptr))
}
C.g_value_unset(val.gValue)

val.gValue = nil
}

cBytes := C.CBytes(data)
defer C.free(cBytes)

size := C.ulong(len(data))
blob := C.vips_blob_copy(cBytes, size)

C.g_value_set_boxed(v.gValue, C.gconstpointer(blob))

return v
}

// GNullVipsBlob create empty glib object gValue with type for *C.VipsBlob
// Calling Copy() at GValue with type VipsBlob is forbidden.
func GNullVipsBlob() *GValue {
var gValue C.GValue

v := &GValue{
gType: C.vips_blob_get_type(),
gValue: &gValue,
}
v.free = func(val *GValue) {
if val.gValue == nil {
return
}

// GNullVipsBlob is used for get result from save_buffer operations,
// and will be unrefereed with operation
C.g_value_unset(val.gValue)

val.gValue = nil
}
v.copy = func(val *GValue) (*GValue, error) {
return nil, ErrCopyForbidden
}

C.g_value_init(v.gValue, v.gType)

return v
}

// GVipsImage return gValue, contains new empty VipsImage
func GVipsImage() *GValue {
value := C.vips_image_new()
Expand Down
Loading

0 comments on commit b82a495

Please sign in to comment.