From 7cf4ee954ba7e8f226b4dd09529277cb15e39d28 Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Tue, 27 Aug 2024 14:38:15 +0200 Subject: [PATCH] Add method to write file to io.Writer --- context.go | 52 ++++++++++++++++++++++++++++++++++++--- context_writer.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 context_writer.go diff --git a/context.go b/context.go index ba81a78..8de2bd5 100644 --- a/context.go +++ b/context.go @@ -20,14 +20,34 @@ package libheif // #cgo pkg-config: libheif -// #include -// #include -// #include +/* +#include +#include +#include + +extern struct heif_error writeGo(void* data, size_t size, void* userdata); + +struct heif_error writeCgo(struct heif_context* ctx, const void* data, size_t size, void* userdata) { + struct heif_error err = writeGo((char*)data, size, userdata); + if (!err.message) { + switch (err.code) { + case heif_error_Ok: + err.message = "Success"; + break; + default: + err.message = "Error writing"; + break; + } + } + return err; +} +*/ import "C" import ( "errors" "fmt" + "io" "runtime" "unsafe" ) @@ -112,6 +132,32 @@ func (c *Context) NewEncoder(compression CompressionFormat) (*Encoder, error) { return c.convertEncoderDescriptor(descriptors[0]) } +// Write saves the current image. +func (c *Context) Write(w io.Writer) error { + defer runtime.KeepAlive(c) + + writer := &C.struct_heif_writer{ + writer_api_version: 1, + + write: (*[0]byte)(C.writeCgo), + } + writerData := &writerData{ + w: w, + } + + var p runtime.Pinner + p.Pin(w) + defer p.Unpin() + + err := C.heif_context_write(c.context, writer, unsafe.Pointer(writerData)) + if writerData.err != nil { + // Bubble up error returned by passed io.Writer + return writerData.err + } + + return convertHeifError(err) +} + // WriteToFile saves the current image to the given file. func (c *Context) WriteToFile(filename string) error { defer runtime.KeepAlive(c) diff --git a/context_writer.go b/context_writer.go new file mode 100644 index 0000000..24b7510 --- /dev/null +++ b/context_writer.go @@ -0,0 +1,62 @@ +/* + * Go interface to libheif + * + * Copyright (c) 2018-2024 struktur AG, Joachim Bauch + * + * libheif is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * libheif is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libheif. If not, see . + */ +package libheif + +// #cgo pkg-config: libheif +/* +#include +#include +#include +*/ +import "C" + +import ( + "io" + "unsafe" +) + +type writerData struct { + w io.Writer + err error +} + +//export writeGo +func writeGo(data *C.void, size C.size_t, userdata *C.void) C.struct_heif_error { + writer := (*writerData)(unsafe.Pointer(userdata)) + if writer.err != nil { + return C.struct_heif_error{ + code: C.heif_error_Ok, + subcode: C.heif_suberror_Unspecified, + } + } + + _, err := writer.w.Write(C.GoBytes(unsafe.Pointer(data), C.int(size))) + if err != nil { + writer.err = err + return C.struct_heif_error{ + code: C.heif_error_Usage_error, + subcode: C.heif_suberror_Unspecified, + } + } + + return C.struct_heif_error{ + code: C.heif_error_Ok, + subcode: C.heif_suberror_Unspecified, + } +}