1// Same copyright and license as the rest of the files in this project 2 3// +build !gdk_pixbuf_2_2 4 5package gdk 6 7// #cgo pkg-config: gdk-3.0 glib-2.0 gobject-2.0 gmodule-2.0 8// #include <glib.h> 9// #include <gmodule.h> 10// #include <gdk/gdk.h> 11// #include "gdk.go.h" 12// #include "pixbuf.go.h" 13// #include "pixbuf_since_2_4.go.h" 14import "C" 15import ( 16 "errors" 17 "io" 18 "reflect" 19 "runtime" 20 "strconv" 21 "unsafe" 22 23 "github.com/gotk3/gotk3/glib" 24 "github.com/gotk3/gotk3/internal/callback" 25) 26 27// File saving 28 29//export goPixbufSaveCallback 30func goPixbufSaveCallback(buf *C.gchar, count C.gsize, gerr **C.GError, id C.gpointer) C.gboolean { 31 v := callback.Get(uintptr(id)) 32 33 if v == nil { 34 C._pixbuf_error_set_callback_not_found(gerr) 35 return C.FALSE 36 } 37 38 var bytes []byte 39 header := (*reflect.SliceHeader)((unsafe.Pointer(&bytes))) 40 header.Cap = int(count) 41 header.Len = int(count) 42 header.Data = uintptr(unsafe.Pointer(buf)) 43 44 _, err := v.(io.Writer).Write(bytes) 45 if err != nil { 46 cerr := C.CString(err.Error()) 47 defer C.free(unsafe.Pointer(cerr)) 48 49 C._pixbuf_error_set(gerr, cerr) 50 return C.FALSE 51 } 52 53 return C.TRUE 54} 55 56// WritePNG is a convenience wrapper around gdk_pixbuf_save_to_callback() for 57// saving images using a streaming callback API. Compression is a number from 0 58// to 9. 59func (v *Pixbuf) WritePNG(w io.Writer, compression int) error { 60 ccompression := C.CString(strconv.Itoa(compression)) 61 defer C.free(unsafe.Pointer(ccompression)) 62 63 id := callback.Assign(w) 64 65 var err *C.GError 66 c := C._gdk_pixbuf_save_png_writer(v.native(), C.gpointer(id), &err, ccompression) 67 68 callback.Delete(id) 69 70 if !gobool(c) { 71 defer C.g_error_free(err) 72 return errors.New(C.GoString((*C.char)(err.message))) 73 } 74 75 return nil 76} 77 78// WriteJPEG is a convenience wrapper around gdk_pixbuf_save_to_callback() for 79// saving images using a streaming callback API. Quality is a number from 0 to 80// 100. 81func (v *Pixbuf) WriteJPEG(w io.Writer, quality int) error { 82 cquality := C.CString(strconv.Itoa(quality)) 83 defer C.free(unsafe.Pointer(cquality)) 84 85 id := callback.Assign(w) 86 87 var err *C.GError 88 c := C._gdk_pixbuf_save_jpeg_writer(v.native(), C.gpointer(id), &err, cquality) 89 90 callback.Delete(id) 91 92 if !gobool(c) { 93 defer C.g_error_free(err) 94 return errors.New(C.GoString((*C.char)(err.message))) 95 } 96 97 return nil 98} 99 100// TODO: 101// GdkPixbufSaveFunc 102// gdk_pixbuf_save_to_callback(). 103// gdk_pixbuf_save_to_callbackv(). 104// gdk_pixbuf_save_to_buffer(). 105// gdk_pixbuf_save_to_bufferv(). 106 107// File Loading 108 109// PixbufNewFromFileAtSize is a wrapper around gdk_pixbuf_new_from_file_at_size(). 110func PixbufNewFromFileAtSize(filename string, width, height int) (*Pixbuf, error) { 111 cstr := C.CString(filename) 112 defer C.free(unsafe.Pointer(cstr)) 113 114 var err *C.GError = nil 115 c := C.gdk_pixbuf_new_from_file_at_size(cstr, C.int(width), C.int(height), &err) 116 if err != nil { 117 defer C.g_error_free(err) 118 return nil, errors.New(C.GoString((*C.char)(err.message))) 119 } 120 121 if c == nil { 122 return nil, nilPtrErr 123 } 124 125 obj := &glib.Object{glib.ToGObject(unsafe.Pointer(c))} 126 p := &Pixbuf{obj} 127 //obj.Ref() 128 runtime.SetFinalizer(p, func(_ interface{}) { obj.Unref() }) 129 return p, nil 130} 131 132// PixbufGetFileInfo is a wrapper around gdk_pixbuf_get_file_info(). 133func PixbufGetFileInfo(filename string) (*PixbufFormat, int, int, error) { 134 cstr := C.CString(filename) 135 defer C.free(unsafe.Pointer(cstr)) 136 var cw, ch C.gint 137 format := C.gdk_pixbuf_get_file_info((*C.gchar)(cstr), &cw, &ch) 138 if format == nil { 139 return nil, -1, -1, nilPtrErr 140 } 141 // The returned PixbufFormat value is owned by Pixbuf and should not be freed. 142 return wrapPixbufFormat(format), int(cw), int(ch), nil 143} 144