Skip to content

Commit

Permalink
expose ImageOutput API
Browse files Browse the repository at this point in the history
  • Loading branch information
SamLok authored and justinfx committed Nov 17, 2016
1 parent 8db5a76 commit 3f813fd
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 0 deletions.
1 change: 1 addition & 0 deletions all.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "cpp/oiio.cpp"
#include "cpp/imageinput.cpp"
#include "cpp/imageoutput.cpp"
#include "cpp/imagespec.cpp"
#include "cpp/imagebuf.cpp"
#include "cpp/imagecache.cpp"
Expand Down
42 changes: 42 additions & 0 deletions cpp/imageoutput.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <OpenImageIO/imageio.h>

#include <string>

#include "oiio.h"

extern "C" {

void deleteImageOutput(ImageOutput *out) {
delete static_cast<OIIO::ImageOutput*>(out);
}

ImageOutput* ImageOutput_Create(const char* filename, const char* plugin_searchpath) {
std::string s_filename(filename);
std::string s_path(plugin_searchpath);
return (ImageOutput*) OIIO::ImageOutput::create(s_filename, s_path);
}

const char* ImageOutput_geterror(ImageOutput *out) {
std::string sstring = static_cast<OIIO::ImageOutput*>(out)->geterror();
if (sstring.empty()){
return NULL;
}
return sstring.c_str();
}

const char* ImageOutput_format_name(ImageOutput *out) {
return static_cast<OIIO::ImageOutput*>(out)->format_name();
}

const ImageSpec* ImageOutput_spec(ImageOutput *out) {
const OIIO::ImageSpec *spec = &(static_cast<OIIO::ImageOutput*>(out)->spec());
return (ImageSpec*) spec;
}

bool ImageOutput_supports(ImageOutput *out, const char* feature){
std::string s_feature(feature);
return static_cast<OIIO::ImageOutput*>(out)->supports(s_feature);
}


} // extern "C"
9 changes: 9 additions & 0 deletions cpp/oiio.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,17 @@ bool ImageInput_read_image_format(ImageInput *in, TypeDesc format, void* data, v

const char* ImageInput_geterror(ImageInput *in);

// ImageOutput
//

void deleteImageOutput(ImageOutput *out);
ImageOutput* ImageOutput_Create(const char* filename, const char* plugin_searchpath);

const char* ImageOutput_format_name(ImageOutput *out);
const ImageSpec* ImageOutput_spec(ImageOutput *out);
bool ImageOutput_supports(ImageOutput *out, const char* feature);

const char* ImageOutput_geterror(ImageOutput *out);

// ImageSpec
//
Expand Down
93 changes: 93 additions & 0 deletions imageoutput.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package oiio
import "C"

import (
"errors"
"runtime"
"unsafe"
)
Expand All @@ -30,3 +31,95 @@ func deleteImageOutput(i *ImageOutput) {
i.ptr = nil
}
}

// Create an ImageOutput that will write to a file, with the format
// inferred from the extension of the name. This just creates the ImageOutput, it
// does not open the file.
func OpenImageOutput(filename string) (*ImageOutput, error) {
c_str := C.CString(filename)

// TODO: Provide optional argument for plugin path
c_path := C.CString("")

defer C.free(unsafe.Pointer(c_str))
defer C.free(unsafe.Pointer(c_path))

ptr := C.ImageOutput_Create(c_str, c_path)

out := newImageOutput(ptr)

return out, out.LastError()
}

// Return the last error generated by API calls.
// An nil error will be returned if no error has occured.
func (i *ImageOutput) LastError() error {
c_str := C.ImageOutput_geterror(i.ptr)
if c_str == nil {
return nil
}
err := C.GoString(c_str)
if err == "" {
return nil
}
return errors.New(err)
}

// Given the name of a 'feature', return whether this ImageOutput
// supports output of images with the given properties.
// Feature names that ImageIO plugins are expected to recognize
// include:
// "tiles" Is this format able to write tiled images?
// "rectangles" Does this plugin accept arbitrary rectangular
// pixel regions, not necessarily aligned to
// scanlines or tiles?
// "random_access" May tiles or scanlines be written in
// any order (false indicates that they MUST
// be in successive order).
// "multiimage" Does this format support multiple subimages
// within a file?
// "appendsubimage" Does this format support adding subimages one at
// a time through open(name,spec,AppendSubimage)?
// If not, then open(name,subimages,specs) must
// be used instead.
// "mipmap" Does this format support multiple resolutions
// for an image/subimage?
// "volumes" Does this format support "3D" pixel arrays?
// "rewrite" May the same scanline or tile be sent more than
// once? (Generally, this will be true for
// plugins that implement interactive display.)
// "empty" Does this plugin support passing a NULL data
// pointer to write_scanline or write_tile to
// indicate that the entire data block is zero?
// "channelformats" Does the plugin/format support per-channel
// data formats?
// "displaywindow" Does the format support display ("full") windows
// distinct from the pixel data window?
// "origin" Does the format support a nonzero x,y,z
// origin of the pixel data window?
// "negativeorigin" Does the format support negative x,y,z
// and full_{x,y,z} origin values?
// "deepdata" Deep (multi-sample per pixel) data
//
// Note that main advantage of this approach, versus having
// separate individual supports_foo() methods, is that this allows
// future expansion of the set of possible queries without changing
// the API, adding new entry points, or breaking linkage
// compatibility.
func (i *ImageOutput) Supports(feature string) bool {
c_str := C.CString(feature)
defer C.free(unsafe.Pointer(c_str))
return bool(C.ImageOutput_supports(i.ptr, c_str))
}

// Return a reference to the image format specification of the current subimage/MIPlevel.
// Note that the contents of the spec will be empty unless it is further added to it
func (i *ImageOutput) Spec() *ImageSpec {
ptr := C.ImageOutput_spec(i.ptr)
return &ImageSpec{ptr}
}

// Return the name of the format implemented by this image.
func (i *ImageOutput) FormatName() string {
return C.GoString(C.ImageOutput_format_name(i.ptr))
}
57 changes: 57 additions & 0 deletions imageoutput_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package oiio

import (
"testing"
)

func TestOpenImageOutput(t *testing.T) {
out, err := OpenImageOutput("png")
if err != nil {
t.Fatal(err.Error())
}

out.Supports("xyz")

actual := out.FormatName()
if actual != "png" {
t.Errorf("Expected FormatName 'png' but got actual %q", actual)
}

}

func TestImageOutputSupports(t *testing.T) {

// Test using .exr format as it has the widest support feature
out, err := OpenImageOutput("exr")

if err != nil {
t.Fatal(err.Error())
}

expectSupports := []string{
"tiles",
"mipmap",
"alpha",
"nchannels",
"channelformats",
"displaywindow",
"origin",
"negativeorigin",
"arbitrary_metadata",
"exif",
"iptc",
"multiimage",
"deepdata",
}

for _, expect := range expectSupports {
if !out.Supports(expect) {
t.Errorf("Expected support for feature %q (format %q)", expect, out.FormatName())
}
}

if out.Supports("invalidfeature") {
t.Error("Supports() returned true for a feature we expected to report false")
}

}

0 comments on commit 3f813fd

Please sign in to comment.