github.com/sbinet/go-cfitsio@v0.0.0-20140625105338-0307f985659e/image.go (about)

     1  package cfitsio
     2  
     3  // #include "go-cfitsio.h"
     4  // #include "go-cfitsio-utils.h"
     5  import "C"
     6  import (
     7  	"fmt"
     8  	"reflect"
     9  	"unsafe"
    10  )
    11  
    12  // ImageHDU is a Header-Data-Unit extension holding an image as data payload.
    13  type ImageHDU struct {
    14  	f      *File
    15  	header Header
    16  }
    17  
    18  // Close closes this HDU, cleaning up cycles for the proper garbage collection.
    19  func (hdu *ImageHDU) Close() error {
    20  	hdu.f = nil
    21  	return nil
    22  }
    23  
    24  // Header returns the Header part of this "Header Data-Unit" block.
    25  func (hdu *ImageHDU) Header() Header {
    26  	return hdu.header
    27  }
    28  
    29  // Type returns the HDUType for this HDU.
    30  func (hdu *ImageHDU) Type() HDUType {
    31  	return hdu.header.htype
    32  }
    33  
    34  // Name returns the value of the 'EXTNAME' Card (or "" if none)
    35  func (hdu *ImageHDU) Name() string {
    36  	card := hdu.header.Get("EXTNAME")
    37  	if card == nil {
    38  		return ""
    39  	}
    40  	return card.Value.(string)
    41  }
    42  
    43  // Version returns the value of the 'EXTVER' Card (or 1 if none)
    44  func (hdu *ImageHDU) Version() int {
    45  	card := hdu.header.Get("EXTVER")
    46  	if card == nil {
    47  		return 1
    48  	}
    49  	return card.Value.(int)
    50  }
    51  
    52  // Data loads the image data associated with this HDU into data, which should
    53  // be a pointer to a slice []T.
    54  // cfitsio will return an error if the image payload can not be converted into Ts.
    55  // It panics if data isn't addressable.
    56  func (hdu *ImageHDU) Data(data interface{}) error {
    57  
    58  	rv := reflect.ValueOf(data).Elem()
    59  	if !rv.CanAddr() {
    60  		return fmt.Errorf("%T is not addressable", data)
    61  	}
    62  
    63  	err := hdu.load(rv)
    64  	return err
    65  }
    66  
    67  // load loads the image data associated with this HDU into v.
    68  func (hdu *ImageHDU) load(v reflect.Value) error {
    69  	var err error
    70  	hdr := hdu.Header()
    71  	naxes := len(hdr.Axes())
    72  	if naxes == 0 {
    73  		return nil
    74  	}
    75  	nelmts := 1
    76  	for _, dim := range hdr.Axes() {
    77  		nelmts *= int(dim)
    78  	}
    79  	rv := reflect.MakeSlice(v.Type(), nelmts, nelmts)
    80  
    81  	c_start := C.LONGLONG(0)
    82  	c_nelmts := C.LONGLONG(nelmts)
    83  	c_anynull := C.int(0)
    84  	c_status := C.int(0)
    85  	c_imgtype := C.int(0)
    86  	var c_ptr unsafe.Pointer
    87  	switch rv.Interface().(type) {
    88  	case []byte:
    89  		c_imgtype = C.TBYTE
    90  		data := rv.Interface().([]byte)
    91  		c_ptr = unsafe.Pointer(&data[0])
    92  
    93  	case []int8:
    94  		c_imgtype = C.TBYTE
    95  		data := rv.Interface().([]int8)
    96  		c_ptr = unsafe.Pointer(&data[0])
    97  
    98  	case []int16:
    99  		c_imgtype = C.TSHORT
   100  		data := rv.Interface().([]int16)
   101  		c_ptr = unsafe.Pointer(&data[0])
   102  
   103  	case []int32:
   104  		c_imgtype = C.TINT
   105  		data := rv.Interface().([]int32)
   106  		c_ptr = unsafe.Pointer(&data[0])
   107  
   108  	case []int64:
   109  		c_imgtype = C.TLONGLONG
   110  		data := rv.Interface().([]int64)
   111  		c_ptr = unsafe.Pointer(&data[0])
   112  
   113  	case []float32:
   114  		c_imgtype = C.TFLOAT
   115  		data := rv.Interface().([]float32)
   116  		c_ptr = unsafe.Pointer(&data[0])
   117  
   118  	case []float64:
   119  		c_imgtype = C.TDOUBLE
   120  		data := rv.Interface().([]float64)
   121  		c_ptr = unsafe.Pointer(&data[0])
   122  
   123  	default:
   124  		panic(fmt.Errorf("invalid image type [%T]", rv.Interface()))
   125  	}
   126  	C.fits_read_img(hdu.f.c, c_imgtype, c_start+1, c_nelmts, c_ptr, c_ptr, &c_anynull, &c_status)
   127  	if c_status > 0 {
   128  		return to_err(c_status)
   129  	}
   130  
   131  	n := reflect.Copy(v, rv)
   132  	if n != nelmts {
   133  		err = fmt.Errorf("cfitsio: copied [%v] elements. expected [%v]", n, nelmts)
   134  	}
   135  	return err
   136  }
   137  
   138  // Write writes the image to disk
   139  // data should be a pointer to a slice []T.
   140  func (hdu *ImageHDU) Write(data interface{}) error {
   141  	var err error
   142  	rv := reflect.ValueOf(data).Elem()
   143  	if !rv.CanAddr() {
   144  		return fmt.Errorf("%T is not addressable", data)
   145  	}
   146  
   147  	hdr := hdu.Header()
   148  	naxes := len(hdr.Axes())
   149  	if naxes == 0 {
   150  		return nil
   151  	}
   152  	nelmts := 1
   153  	for _, dim := range hdr.Axes() {
   154  		nelmts *= int(dim)
   155  	}
   156  
   157  	c_start := C.LONGLONG(0)
   158  	c_nelmts := C.LONGLONG(nelmts)
   159  	c_status := C.int(0)
   160  	c_imgtype := C.int(0)
   161  	var c_ptr unsafe.Pointer
   162  
   163  	switch rv.Interface().(type) {
   164  	case []byte:
   165  		c_imgtype = C.TBYTE
   166  		data := rv.Interface().([]byte)
   167  		c_ptr = unsafe.Pointer(&data[0])
   168  
   169  	case []int8:
   170  		c_imgtype = C.TBYTE
   171  		data := rv.Interface().([]int8)
   172  		c_ptr = unsafe.Pointer(&data[0])
   173  
   174  	case []int16:
   175  		c_imgtype = C.TSHORT
   176  		data := rv.Interface().([]int16)
   177  		c_ptr = unsafe.Pointer(&data[0])
   178  
   179  	case []int32:
   180  		c_imgtype = C.TINT
   181  		data := rv.Interface().([]int32)
   182  		c_ptr = unsafe.Pointer(&data[0])
   183  
   184  	case []int64:
   185  		c_imgtype = C.TLONGLONG
   186  		data := rv.Interface().([]int64)
   187  		c_ptr = unsafe.Pointer(&data[0])
   188  
   189  	case []float32:
   190  		c_imgtype = C.TFLOAT
   191  		data := rv.Interface().([]float32)
   192  		c_ptr = unsafe.Pointer(&data[0])
   193  
   194  	case []float64:
   195  		c_imgtype = C.TDOUBLE
   196  		data := rv.Interface().([]float64)
   197  		c_ptr = unsafe.Pointer(&data[0])
   198  
   199  	default:
   200  		panic(fmt.Errorf("invalid image type [%T]", rv.Interface()))
   201  	}
   202  
   203  	C.fits_write_img(hdu.f.c, c_imgtype, c_start+1, c_nelmts, c_ptr, &c_status)
   204  	if c_status > 0 {
   205  		return to_err(c_status)
   206  	}
   207  
   208  	return err
   209  }
   210  
   211  // newImageHDU returns the i-th HDU from file f.
   212  // if i==0, the returned ImageHDU is actually the primary HDU.
   213  func newImageHDU(f *File, hdr Header, i int) (hdu HDU, err error) {
   214  	switch i {
   215  	case 0:
   216  		hdu, err = newPrimaryHDU(f, hdr)
   217  	default:
   218  		hdu = &ImageHDU{
   219  			f:      f,
   220  			header: hdr,
   221  		}
   222  	}
   223  	return hdu, err
   224  }
   225  
   226  func init() {
   227  	g_hdus[IMAGE_HDU] = newImageHDU
   228  }
   229  
   230  // EOF