github.com/astrogo/cfitsio@v0.1.0/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  	hdr := hdu.Header()
    70  	naxes := len(hdr.Axes())
    71  	if naxes == 0 {
    72  		return nil
    73  	}
    74  	nelmts := 1
    75  	for _, dim := range hdr.Axes() {
    76  		nelmts *= int(dim)
    77  	}
    78  	if v.Len() != nelmts {
    79  		return fmt.Errorf("cfitsio: slice length [%v] is not as expected [%v]", v.Len(), nelmts)
    80  	}
    81  
    82  	c_start := C.LONGLONG(0)
    83  	c_nelmts := C.LONGLONG(nelmts)
    84  	c_status := C.int(0)
    85  	c_imgtype := C.int(0)
    86  	var c_ptr unsafe.Pointer
    87  	switch data := v.Interface().(type) {
    88  	case []byte:
    89  		c_imgtype = C.TBYTE
    90  		c_ptr = unsafe.Pointer(&data[0])
    91  
    92  	case []int8:
    93  		c_imgtype = C.TBYTE
    94  		c_ptr = unsafe.Pointer(&data[0])
    95  
    96  	case []int16:
    97  		c_imgtype = C.TSHORT
    98  		c_ptr = unsafe.Pointer(&data[0])
    99  
   100  	case []uint16:
   101  		c_imgtype = C.TUSHORT
   102  		c_ptr = unsafe.Pointer(&data[0])
   103  
   104  	case []int32:
   105  		c_imgtype = C.TINT
   106  		c_ptr = unsafe.Pointer(&data[0])
   107  
   108  	case []uint32:
   109  		c_imgtype = C.TUINT
   110  		c_ptr = unsafe.Pointer(&data[0])
   111  
   112  	case []int64:
   113  		c_imgtype = C.TLONGLONG
   114  		c_ptr = unsafe.Pointer(&data[0])
   115  
   116  	case []uint64:
   117  		c_imgtype = C.TULONGLONG
   118  		c_ptr = unsafe.Pointer(&data[0])
   119  
   120  	case []float32:
   121  		c_imgtype = C.TFLOAT
   122  		c_ptr = unsafe.Pointer(&data[0])
   123  
   124  	case []float64:
   125  		c_imgtype = C.TDOUBLE
   126  		c_ptr = unsafe.Pointer(&data[0])
   127  
   128  	default:
   129  		panic(fmt.Errorf("invalid image type [%T]", v.Interface()))
   130  	}
   131  	C.fits_read_img(hdu.f.c, c_imgtype, c_start+1, c_nelmts, nil, c_ptr, nil, &c_status)
   132  	if c_status > 0 {
   133  		return to_err(c_status)
   134  	}
   135  
   136  	return nil
   137  }
   138  
   139  // Write writes the image to disk
   140  // data should be a pointer to a slice []T.
   141  func (hdu *ImageHDU) Write(data interface{}) error {
   142  	var err error
   143  	rv := reflect.ValueOf(data).Elem()
   144  	if !rv.CanAddr() {
   145  		return fmt.Errorf("%T is not addressable", data)
   146  	}
   147  
   148  	hdr := hdu.Header()
   149  	naxes := len(hdr.Axes())
   150  	if naxes == 0 {
   151  		return nil
   152  	}
   153  	nelmts := 1
   154  	for _, dim := range hdr.Axes() {
   155  		nelmts *= int(dim)
   156  	}
   157  
   158  	c_start := C.LONGLONG(0)
   159  	c_nelmts := C.LONGLONG(nelmts)
   160  	c_status := C.int(0)
   161  	c_imgtype := C.int(0)
   162  	var c_ptr unsafe.Pointer
   163  
   164  	switch data := rv.Interface().(type) {
   165  	case []byte:
   166  		c_imgtype = C.TBYTE
   167  		c_ptr = unsafe.Pointer(&data[0])
   168  
   169  	case []int8:
   170  		c_imgtype = C.TBYTE
   171  		c_ptr = unsafe.Pointer(&data[0])
   172  
   173  	case []int16:
   174  		c_imgtype = C.TSHORT
   175  		c_ptr = unsafe.Pointer(&data[0])
   176  
   177  	case []uint16:
   178  		c_imgtype = C.TUSHORT
   179  		c_ptr = unsafe.Pointer(&data[0])
   180  
   181  	case []int32:
   182  		c_imgtype = C.TINT
   183  		c_ptr = unsafe.Pointer(&data[0])
   184  
   185  	case []uint32:
   186  		c_imgtype = C.TUINT
   187  		c_ptr = unsafe.Pointer(&data[0])
   188  
   189  	case []int64:
   190  		c_imgtype = C.TLONGLONG
   191  		c_ptr = unsafe.Pointer(&data[0])
   192  
   193  	case []uint64:
   194  		c_imgtype = C.TULONGLONG
   195  		c_ptr = unsafe.Pointer(&data[0])
   196  
   197  	case []float32:
   198  		c_imgtype = C.TFLOAT
   199  		c_ptr = unsafe.Pointer(&data[0])
   200  
   201  	case []float64:
   202  		c_imgtype = C.TDOUBLE
   203  		c_ptr = unsafe.Pointer(&data[0])
   204  
   205  	default:
   206  		panic(fmt.Errorf("invalid image type [%T]", rv.Interface()))
   207  	}
   208  
   209  	C.fits_write_img(hdu.f.c, c_imgtype, c_start+1, c_nelmts, c_ptr, &c_status)
   210  	if c_status > 0 {
   211  		return to_err(c_status)
   212  	}
   213  
   214  	return err
   215  }
   216  
   217  // newImageHDU returns the i-th HDU from file f.
   218  // if i==0, the returned ImageHDU is actually the primary HDU.
   219  func newImageHDU(f *File, hdr Header, i int) (hdu HDU, err error) {
   220  	switch i {
   221  	case 0:
   222  		hdu, err = newPrimaryHDU(f, hdr)
   223  	default:
   224  		hdu = &ImageHDU{
   225  			f:      f,
   226  			header: hdr,
   227  		}
   228  	}
   229  	return hdu, err
   230  }
   231  
   232  func init() {
   233  	g_hdus[IMAGE_HDU] = newImageHDU
   234  }
   235  
   236  // EOF