github.com/jjjabc/fitsio@v0.0.0-20161215022839-d1807e9e818e/image_test.go (about)

     1  // Copyright 2015 The astrogo Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package fitsio
     6  
     7  import (
     8  	"fmt"
     9  	"image"
    10  	"image/color"
    11  	"image/draw"
    12  	"io/ioutil"
    13  	"math"
    14  	"os"
    15  	"reflect"
    16  	"testing"
    17  
    18  	"github.com/astrogo/fitsio/fltimg"
    19  )
    20  
    21  func TestImageRW(t *testing.T) {
    22  	curdir, err := os.Getwd()
    23  	if err != nil {
    24  		t.Fatalf(err.Error())
    25  	}
    26  	defer os.Chdir(curdir)
    27  
    28  	workdir, err := ioutil.TempDir("", "go-fitsio-test-")
    29  	if err != nil {
    30  		t.Fatalf(err.Error())
    31  	}
    32  	defer os.RemoveAll(workdir)
    33  
    34  	err = os.Chdir(workdir)
    35  	if err != nil {
    36  		t.Fatalf(err.Error())
    37  	}
    38  
    39  	for ii, table := range []struct {
    40  		name    string
    41  		version int
    42  		cards   []Card
    43  		bitpix  int
    44  		axes    []int
    45  		image   interface{}
    46  	}{
    47  		{
    48  			name:    "new.fits",
    49  			version: 2,
    50  			cards: []Card{
    51  				{
    52  					"EXTNAME",
    53  					"primary hdu",
    54  					"the primary HDU",
    55  				},
    56  				{
    57  					"EXTVER",
    58  					2,
    59  					"the primary hdu version",
    60  				},
    61  			},
    62  			bitpix: 8,
    63  			axes:   []int{3, 4},
    64  			image: []int8{
    65  				0, 1, 2, 3,
    66  				4, 5, 6, 7,
    67  				8, 9, 0, 1,
    68  			},
    69  		},
    70  		{
    71  			name:    "new.fits",
    72  			version: 2,
    73  			cards: []Card{
    74  				{
    75  					"EXTNAME",
    76  					"primary hdu",
    77  					"the primary HDU",
    78  				},
    79  				{
    80  					"EXTVER",
    81  					2,
    82  					"the primary hdu version",
    83  				},
    84  			},
    85  			bitpix: 16,
    86  			axes:   []int{3, 4},
    87  			image: []int16{
    88  				0, 1, 2, 3,
    89  				4, 5, 6, 7,
    90  				8, 9, 0, 1,
    91  			},
    92  		},
    93  		{
    94  			name:    "new.fits",
    95  			version: 2,
    96  			cards: []Card{
    97  				{
    98  					"EXTNAME",
    99  					"primary hdu",
   100  					"the primary HDU",
   101  				},
   102  				{
   103  					"EXTVER",
   104  					2,
   105  					"the primary hdu version",
   106  				},
   107  			},
   108  			bitpix: 32,
   109  			axes:   []int{3, 4},
   110  			image: []int32{
   111  				0, 1, 2, 3,
   112  				4, 5, 6, 7,
   113  				8, 9, 0, 1,
   114  			},
   115  		},
   116  		{
   117  			name:    "new.fits",
   118  			version: 2,
   119  			cards: []Card{
   120  				{
   121  					"EXTNAME",
   122  					"primary hdu",
   123  					"the primary HDU",
   124  				},
   125  				{
   126  					"EXTVER",
   127  					2,
   128  					"the primary hdu version",
   129  				},
   130  			},
   131  			bitpix: 64,
   132  			axes:   []int{3, 4},
   133  			image: []int64{
   134  				0, 1, 2, 3,
   135  				4, 5, 6, 7,
   136  				8, 9, 0, 1,
   137  			},
   138  		},
   139  		{
   140  			name:    "new.fits",
   141  			version: 2,
   142  			cards: []Card{
   143  				{
   144  					"EXTNAME",
   145  					"primary hdu",
   146  					"the primary HDU",
   147  				},
   148  				{
   149  					"EXTVER",
   150  					2,
   151  					"the primary hdu version",
   152  				},
   153  			},
   154  			bitpix: -32,
   155  			axes:   []int{3, 4},
   156  			image: []float32{
   157  				0, 1, 2, 3,
   158  				4, 5, 6, 7,
   159  				8, 9, 0, 1,
   160  			},
   161  		},
   162  		{
   163  			name:    "new.fits",
   164  			version: 2,
   165  			cards: []Card{
   166  				{
   167  					"EXTNAME",
   168  					"primary hdu",
   169  					"the primary HDU",
   170  				},
   171  				{
   172  					"EXTVER",
   173  					2,
   174  					"the primary hdu version",
   175  				},
   176  			},
   177  			bitpix: -64,
   178  			axes:   []int{3, 4},
   179  			image: []float64{
   180  				0, 1, 2, 3,
   181  				4, 5, 6, 7,
   182  				8, 9, 0, 1,
   183  			},
   184  		},
   185  	} {
   186  		fname := fmt.Sprintf("%03d_%s", ii, table.name)
   187  		for i := 0; i < 2; i++ {
   188  			func(i int) {
   189  				var f *File
   190  				var w *os.File
   191  				var r *os.File
   192  				var err error
   193  				var hdu HDU
   194  
   195  				switch i {
   196  
   197  				case 0: // create
   198  					//fmt.Printf("========= create [%s]....\n", fname)
   199  					w, err = os.Create(fname)
   200  					if err != nil {
   201  						t.Fatalf("error creating new file [%v]: %v", fname, err)
   202  					}
   203  					defer w.Close()
   204  
   205  					f, err = Create(w)
   206  					if err != nil {
   207  						t.Fatalf("error creating new file [%v]: %v", fname, err)
   208  					}
   209  					defer f.Close()
   210  
   211  					img := NewImage(table.bitpix, table.axes)
   212  					defer img.Close()
   213  
   214  					err = img.Header().Append(table.cards...)
   215  					if err != nil {
   216  						t.Fatalf("error appending cards: %v", err)
   217  					}
   218  					hdu = img
   219  
   220  					err = img.Write(&table.image)
   221  					if err != nil {
   222  						t.Fatalf("error writing image: %v", err)
   223  					}
   224  
   225  					err = f.Write(img)
   226  					if err != nil {
   227  						t.Fatalf("error writing image: %v", err)
   228  					}
   229  
   230  				case 1: // read
   231  					//fmt.Printf("========= read [%s]....\n", fname)
   232  					r, err = os.Open(fname)
   233  					if err != nil {
   234  						t.Fatalf("error opening file [%v]: %v", fname, err)
   235  					}
   236  					defer r.Close()
   237  					f, err = Open(r)
   238  					if err != nil {
   239  						t.Fatalf("error opening file [%v]: %v", fname, err)
   240  					}
   241  					defer f.Close()
   242  
   243  					hdu = f.HDU(0)
   244  					hdr := hdu.Header()
   245  					img := hdu.(Image)
   246  					nelmts := 1
   247  					for _, axe := range hdr.Axes() {
   248  						nelmts *= int(axe)
   249  					}
   250  
   251  					var data interface{}
   252  					switch hdr.Bitpix() {
   253  					case 8:
   254  						v := make([]int8, 0, nelmts)
   255  						err = img.Read(&v)
   256  						data = v
   257  
   258  					case 16:
   259  						v := make([]int16, 0, nelmts)
   260  						err = img.Read(&v)
   261  						data = v
   262  
   263  					case 32:
   264  						v := make([]int32, 0, nelmts)
   265  						err = img.Read(&v)
   266  						data = v
   267  
   268  					case 64:
   269  						v := make([]int64, 0, nelmts)
   270  						err = img.Read(&v)
   271  						data = v
   272  
   273  					case -32:
   274  						v := make([]float32, 0, nelmts)
   275  						err = img.Read(&v)
   276  						data = v
   277  
   278  					case -64:
   279  						v := make([]float64, 0, nelmts)
   280  						err = img.Read(&v)
   281  						data = v
   282  					}
   283  
   284  					if err != nil {
   285  						t.Fatalf("error reading image: %v", err)
   286  					}
   287  
   288  					if !reflect.DeepEqual(data, table.image) {
   289  						t.Fatalf("expected image:\nref=%v\ngot=%v", table.image, data)
   290  					}
   291  				}
   292  
   293  				hdr := hdu.Header()
   294  				if hdr.bitpix != table.bitpix {
   295  					t.Fatalf("expected BITPIX=%v. got %v", table.bitpix, hdr.bitpix)
   296  				}
   297  
   298  				if !reflect.DeepEqual(hdr.Axes(), table.axes) {
   299  					t.Fatalf("expected AXES==%v. got %v (i=%v)", table.axes, hdr.Axes(), i)
   300  				}
   301  
   302  				name := hdu.Name()
   303  				if name != "primary hdu" {
   304  					t.Fatalf("expected EXTNAME==%q. got %q", "primary hdu", name)
   305  				}
   306  
   307  				vers := hdu.Version()
   308  				if vers != table.version {
   309  					t.Fatalf("expected EXTVER==%v. got %v", table.version, vers)
   310  				}
   311  
   312  				card := hdr.Get("EXTNAME")
   313  				if card == nil {
   314  					t.Fatalf("error retrieving card [EXTNAME]")
   315  				}
   316  				if card.Comment != "the primary HDU" {
   317  					t.Fatalf("expected EXTNAME.Comment==%q. got %q", "the primary HDU", card.Comment)
   318  				}
   319  
   320  				card = hdr.Get("EXTVER")
   321  				if card == nil {
   322  					t.Fatalf("error retrieving card [EXTVER]")
   323  				}
   324  				if card.Comment != "the primary hdu version" {
   325  					t.Fatalf("expected EXTVER.Comment==%q. got %q", "the primary hdu version", card.Comment)
   326  
   327  				}
   328  
   329  				for _, ref := range table.cards {
   330  					card := hdr.Get(ref.Name)
   331  					if card == nil {
   332  						t.Fatalf("error retrieving card [%v]", ref.Name)
   333  					}
   334  					rv := reflect.ValueOf(ref.Value)
   335  					var val interface{}
   336  					switch rv.Type().Kind() {
   337  					case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   338  						val = int(rv.Int())
   339  					case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   340  						val = int(rv.Uint())
   341  					case reflect.Float32, reflect.Float64:
   342  						val = rv.Float()
   343  					case reflect.Complex64, reflect.Complex128:
   344  						val = rv.Complex()
   345  					case reflect.String:
   346  						val = ref.Value.(string)
   347  					}
   348  					if !reflect.DeepEqual(card.Value, val) {
   349  						t.Fatalf(
   350  							"card %q. expected [%v](%T). got [%v](%T)",
   351  							ref.Name,
   352  							val, val,
   353  							card.Value, card.Value,
   354  						)
   355  					}
   356  					if card.Comment != ref.Comment {
   357  						t.Fatalf("card %q. comment differ. expected %q. got %q", ref.Name, ref.Comment, card.Comment)
   358  					}
   359  				}
   360  
   361  				card = hdr.Get("NOT THERE")
   362  				if card != nil {
   363  					t.Fatalf("expected no card. got [%v]", card)
   364  				}
   365  			}(i)
   366  		}
   367  	}
   368  }
   369  
   370  func TestImageImage(t *testing.T) {
   371  	const (
   372  		w = 20
   373  		h = 20
   374  	)
   375  	var (
   376  		rect = image.Rect(0, 0, w, h)
   377  	)
   378  	set := func(img draw.Image) {
   379  		img.Set(0, 0, color.RGBA{255, 0, 0, 255})
   380  		img.Set(10, 10, color.RGBA{0, 255, 0, 255})
   381  		img.Set(15, 15, color.RGBA{0, 0, 255, 255})
   382  	}
   383  
   384  	for i, test := range []struct {
   385  		want   image.Image
   386  		bitpix int
   387  	}{
   388  		{
   389  			want: func() image.Image {
   390  				img := image.NewGray(rect)
   391  				set(img)
   392  				return img
   393  			}(),
   394  			bitpix: 8,
   395  		},
   396  		{
   397  			want: func() image.Image {
   398  				img := image.NewGray16(rect)
   399  				set(img)
   400  				return img
   401  			}(),
   402  			bitpix: 16,
   403  		},
   404  		{
   405  			want: func() image.Image {
   406  				img := image.NewRGBA(rect)
   407  				set(img)
   408  				return img
   409  			}(),
   410  			bitpix: 32,
   411  		},
   412  		{
   413  			want: func() image.Image {
   414  				img := image.NewRGBA64(rect)
   415  				set(img)
   416  				return img
   417  			}(),
   418  			bitpix: 64,
   419  		},
   420  		{
   421  			want: func() image.Image {
   422  				pix := image.NewRGBA(rect)
   423  				set(pix)
   424  				img := fltimg.NewGray32(rect, pix.Pix)
   425  				return img
   426  			}(),
   427  			bitpix: -32,
   428  		},
   429  		{
   430  			want: func() image.Image {
   431  				pix := image.NewRGBA64(rect)
   432  				set(pix)
   433  				img := fltimg.NewGray64(rect, pix.Pix)
   434  				return img
   435  			}(),
   436  			bitpix: -64,
   437  		},
   438  	} {
   439  		hdu := NewImage(test.bitpix, []int{w, h})
   440  		switch test.bitpix {
   441  		case 8:
   442  			img := test.want.(*image.Gray)
   443  			err := hdu.Write(&img.Pix)
   444  			if err != nil {
   445  				t.Errorf("image #%d: error writing raw pixels: %v\n", i, err)
   446  				continue
   447  			}
   448  		case 16:
   449  			img := test.want.(*image.Gray16)
   450  			pix := make([]int16, len(img.Pix)/2)
   451  			for i := 0; i < len(img.Pix); i += 2 {
   452  				buf := img.Pix[i : i+2]
   453  				pix[i/2] = int16(uint16(buf[1]) | uint16(buf[0])<<8)
   454  			}
   455  			err := hdu.Write(&pix)
   456  			if err != nil {
   457  				t.Errorf("image #%d: error writing raw pixels: %v\n", i, err)
   458  				continue
   459  			}
   460  		case 32:
   461  			img := test.want.(*image.RGBA)
   462  			pix := make([]int32, len(img.Pix)/4)
   463  			for i := 0; i < len(img.Pix); i += 4 {
   464  				buf := img.Pix[i : i+4]
   465  				pix[i/4] = int32(uint32(buf[3]) | uint32(buf[2])<<8 | uint32(buf[1])<<16 | uint32(buf[0])<<24)
   466  			}
   467  			err := hdu.Write(&pix)
   468  			if err != nil {
   469  				t.Errorf("image #%d: error writing raw pixels: %v\n", i, err)
   470  				continue
   471  			}
   472  		case 64:
   473  			img := test.want.(*image.RGBA64)
   474  			pix := make([]int64, len(img.Pix)/8)
   475  			for i := 0; i < len(img.Pix); i += 8 {
   476  				buf := img.Pix[i : i+8]
   477  				pix[i/8] = int64(uint64(buf[7]) | uint64(buf[6])<<8 | uint64(buf[5])<<16 | uint64(buf[4])<<24 |
   478  					uint64(buf[3])<<32 | uint64(buf[2])<<40 | uint64(buf[1])<<48 | uint64(buf[0])<<56)
   479  			}
   480  			err := hdu.Write(&pix)
   481  			if err != nil {
   482  				t.Errorf("image #%d: error writing raw pixels: %v\n", i, err)
   483  				continue
   484  			}
   485  		case -32:
   486  			img := test.want.(*fltimg.Gray32)
   487  			pix := make([]float32, len(img.Pix)/4)
   488  			for i := 0; i < len(img.Pix); i += 4 {
   489  				buf := img.Pix[i : i+4]
   490  				pix[i/4] = math.Float32frombits(uint32(buf[3]) | uint32(buf[2])<<8 | uint32(buf[1])<<16 | uint32(buf[0])<<24)
   491  			}
   492  			err := hdu.Write(&pix)
   493  			if err != nil {
   494  				t.Errorf("image #%d: error writing raw pixels: %v\n", i, err)
   495  				continue
   496  			}
   497  		case -64:
   498  			img := test.want.(*fltimg.Gray64)
   499  			pix := make([]float64, len(img.Pix)/8)
   500  			for i := 0; i < len(img.Pix); i += 8 {
   501  				buf := img.Pix[i : i+8]
   502  				pix[i/8] = math.Float64frombits(uint64(buf[7]) | uint64(buf[6])<<8 | uint64(buf[5])<<16 | uint64(buf[4])<<24 |
   503  					uint64(buf[3])<<32 | uint64(buf[2])<<40 | uint64(buf[1])<<48 | uint64(buf[0])<<56)
   504  			}
   505  			err := hdu.Write(&pix)
   506  			if err != nil {
   507  				t.Errorf("image #%d: error writing raw pixels: %v\n", i, err)
   508  				continue
   509  			}
   510  		default:
   511  			t.Errorf("image #%d: invalid bitpix=%d", i, test.bitpix)
   512  			continue
   513  		}
   514  		if !reflect.DeepEqual(hdu.Image(), test.want) {
   515  			t.Errorf("image #%d:\n got: %v\nwant: %v\n", i, hdu.Image(), test.want)
   516  			continue
   517  		}
   518  	}
   519  
   520  	for i, test := range []struct {
   521  		bitpix int
   522  		axes   []int
   523  		want   image.Image
   524  	}{
   525  		{
   526  			bitpix: 0,
   527  			axes:   nil,
   528  		},
   529  		{
   530  			bitpix: 0,
   531  			axes:   []int{},
   532  		},
   533  		{
   534  			bitpix: 0,
   535  			axes:   []int{1},
   536  		},
   537  		{
   538  			bitpix: 0,
   539  			axes:   []int{0, 0},
   540  		},
   541  		{
   542  			bitpix: 8,
   543  			axes:   nil,
   544  		},
   545  		{
   546  			bitpix: 8,
   547  			axes:   []int{},
   548  		},
   549  		{
   550  			bitpix: 8,
   551  			axes:   []int{1},
   552  		},
   553  		{
   554  			bitpix: 8,
   555  			axes:   []int{0, 0},
   556  		},
   557  	} {
   558  		hdu := NewImage(test.bitpix, test.axes)
   559  		img := hdu.Image()
   560  		if img != test.want {
   561  			t.Errorf("image #%d:\n got: %v\nwant: %v\n", i, img, test.want)
   562  			continue
   563  		}
   564  	}
   565  
   566  	func() {
   567  		defer func() {
   568  			if e := recover(); e == nil {
   569  				t.Errorf("error: expected a BITPIX-related panic")
   570  			}
   571  		}()
   572  
   573  		hdu := NewImage(0, []int{1, 1})
   574  		_ = hdu.Image()
   575  	}()
   576  }