Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for read and create hdf5 true color image dataset #63

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions h5g_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ package hdf5
import "C"

import (
"errors"
"fmt"
"image"
"unsafe"
)

Expand Down Expand Up @@ -169,3 +171,19 @@ func (g *CommonFG) LinkExists(name string) bool {
defer C.free(unsafe.Pointer(c_name))
return C.H5Lexists(g.id, c_name, 0) > 0
}

// CreateTureImage create a image set with given name under a CommonFG
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
func (g *CommonFG) CreateTrueImage(name string, img image.Image) error {
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
if g.LinkExists(name) {
return errors.New("name already exist")
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}
return newImage(g.id, name, img)
}

// ReadTrueImage read a image dataset into a go Image
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
func (g *CommonFG) ReadTrueImage(name string) (image.Image, error) {
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
if !g.LinkExists(name) {
return nil, errors.New("name doesn't exist")
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}
return getImage(g.id, name)
}
51 changes: 51 additions & 0 deletions h5g_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
package hdf5

import (
"image"
"image/color"
"image/jpeg"
"os"
"testing"
)
Expand Down Expand Up @@ -128,3 +131,51 @@ func TestGroup(t *testing.T) {
}

}

func TestImage(t *testing.T) {
f, err := CreateFile(fname, F_ACC_TRUNC)
if err != nil {
t.Fatalf("CreateFile failed: %s", err)
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}
defer os.Remove(fname)
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
defer f.Close()
img := image.NewRGBA(image.Rect(0, 0, 1000, 500))
for y := 200; y < 300; y++ {
for x := 400; x < 600; x++ {
img.Set(x, y, color.RGBA{255, 0, 255, 255})
}
}
if err != nil {
t.Fatalf("image decoding failed: %s", err)
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}
g1, err := f.CreateGroup("foo")
if err != nil {
t.Fatalf("couldn't create group: %s", err)
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}
defer g1.Close()
err = g1.CreateTrueImage("image", img)
if err != nil {
t.Fatalf("image saving failed: %s", err)
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}
imgRead, err := g1.ReadTrueImage("image")
if err != nil {
t.Fatalf("image reading failed: %s", err)
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}
widthGot := imgRead.Bounds().Max.X
heightGot := imgRead.Bounds().Max.Y
if widthGot != 1000 || heightGot != 500 {
t.Fatalf("image dimension miss match: Got %d * %d, suppose to be 1000x500", widthGot, heightGot)
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}

imgfile, err := os.Create("img.jpg")
if err != nil {
t.Fatalf("image file creation failed: %s", err)
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}
defer os.Remove("img.jpg")
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
defer imgfile.Close()

err = jpeg.Encode(imgfile, imgRead, nil)
if err != nil {
t.Fatalf(" jpeg image saving err: %s", err)
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}
}
79 changes: 79 additions & 0 deletions h5i_image.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// license that can be found in the LICENSE file.

package hdf5

// #include "hdf5.h"
// #include "hdf5_hl.h"
// #include <stdlib.h>
// #include <string.h>
import "C"

import (
"errors"
"image"
"image/color"
"unsafe"
)

// newImage takes a image object and convert it to a hdf5 format and write to the id node
func newImage(id C.hid_t, name string, img image.Image) error {
if img == nil {
return errors.New("nil image!")
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}
width := img.Bounds().Max.X
height := img.Bounds().Max.Y
var c_width, c_height C.hsize_t
c_name := C.CString(name)
defer C.free(unsafe.Pointer(c_name))
var gbuf []uint8
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
r, g, b, _ := img.At(x, y).RGBA()
gbuf = append(gbuf, uint8(r>>8))
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
gbuf = append(gbuf, uint8(g>>8))
gbuf = append(gbuf, uint8(b>>8))
}
}
c_width = C.hsize_t(width)
c_height = C.hsize_t(height)
c_image := (*C.uchar)(unsafe.Pointer(&gbuf[0]))

status := C.H5IMmake_image_24bit(id, c_name, c_width, c_height, C.CString("INTERLACE_PIXEL"), c_image)
if status < 0 {
return errors.New("Failed to create HDF5 true color image")
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
}
return nil
}

//
func getImage(id C.hid_t, name string) (image.Image, error) {
//TODO Should handle interlace and npal better, yet these two are not needed for simple image read and write
zyc-sudo marked this conversation as resolved.
Show resolved Hide resolved
var width, height, planes C.hsize_t
var npals C.hssize_t
var interlace C.char
c_name := C.CString(name)
defer C.free(unsafe.Pointer(c_name))
rc := C.H5IMget_image_info(id, c_name, &width, &height, &planes, &interlace, &npals)
err := h5err(rc)
if err != nil {
return nil, err
}
gbuf := make([]uint8, width*height*planes)
c_image := (*C.uchar)(unsafe.Pointer(&gbuf[0]))
rc = C.H5IMread_image(id, c_name, c_image)

err = h5err(rc)
if err != nil {
return nil, err
}

g_width := int(width)
g_height := int(height)
img := image.NewRGBA(image.Rect(0, 0, g_width, g_height))
for y := 0; y < g_height; y++ {
for x := 0; x < g_width; x++ {
img.Set(x, y, color.RGBA{gbuf[y*g_width*3+x*3], gbuf[y*g_width*3+x*3+1], gbuf[y*g_width*3+x*3+2], 255})
}
}
return img, err
}