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