github.com/janelia-flyem/dvid@v1.0.0/datatype/multichan16/v3draw.go (about) 1 // Implements reading and writing of V3D Raw File formats. 2 3 package multichan16 4 5 import ( 6 "encoding/binary" 7 "fmt" 8 "io" 9 10 "github.com/janelia-flyem/dvid/datatype/imageblk" 11 "github.com/janelia-flyem/dvid/dvid" 12 ) 13 14 type V3DRawMarshaler struct{} 15 16 func (V3DRawMarshaler) UnmarshalV3DRaw(reader io.Reader) ([]*Channel, error) { 17 magicString := make([]byte, 24) 18 if n, err := reader.Read(magicString); n != 24 || err != nil { 19 return nil, fmt.Errorf("error reading magic string in V3D Raw file: %v", err) 20 } 21 if string(magicString) != "raw_image_stack_by_hpeng" { 22 return nil, fmt.Errorf("bad magic string in V3D Raw File: %s", string(magicString)) 23 } 24 endianType := make([]byte, 1, 1) 25 if n, err := reader.Read(endianType); n != 1 || err != nil { 26 return nil, fmt.Errorf("could not read endianness of V3D Raw file: %v", err) 27 } 28 var byteOrder binary.ByteOrder 29 switch string(endianType) { 30 case "L": 31 byteOrder = binary.LittleEndian 32 case "B": 33 return nil, fmt.Errorf("cannot handle big endian byte order in V3D Raw File") 34 default: 35 return nil, fmt.Errorf("illegal byte order '%s' in V3D Raw File", endianType) 36 } 37 var dataType uint16 38 if err := binary.Read(reader, byteOrder, &dataType); err != nil { 39 return nil, err 40 } 41 var bytesPerVoxel int32 42 switch dataType { 43 case 1: 44 bytesPerVoxel = 1 45 case 2: 46 bytesPerVoxel = 2 47 default: 48 return nil, fmt.Errorf("cannot handle V3D Raw File with data type %d", dataType) 49 } 50 var width, height, depth, numChannels uint32 51 if err := binary.Read(reader, byteOrder, &width); err != nil { 52 return nil, fmt.Errorf("error reading width in V3D Raw File: %v", err) 53 } 54 if err := binary.Read(reader, byteOrder, &height); err != nil { 55 return nil, fmt.Errorf("error reading height in V3D Raw File: %v", err) 56 } 57 if err := binary.Read(reader, byteOrder, &depth); err != nil { 58 return nil, fmt.Errorf("error reading depth in V3D Raw File: %v", err) 59 } 60 if err := binary.Read(reader, byteOrder, &numChannels); err != nil { 61 return nil, fmt.Errorf("error reading # channels in V3D Raw File: %v", err) 62 } 63 64 // Allocate the V3DRaw struct for the # channels 65 totalBytes := int(bytesPerVoxel) * int(width*height*depth) 66 size := dvid.Point3d{int32(width), int32(height), int32(depth)} 67 volume := dvid.NewSubvolume(dvid.Point3d{0, 0, 0}, size) 68 v3draw := make([]*Channel, numChannels, numChannels) 69 var c int32 70 for c = 0; c < int32(numChannels); c++ { 71 data := make([]uint8, totalBytes, totalBytes) 72 var t dvid.DataType 73 switch bytesPerVoxel { 74 case 1: 75 t = dvid.T_uint8 76 case 2: 77 t = dvid.T_uint16 78 } 79 values := dvid.DataValues{ 80 { 81 T: t, 82 Label: fmt.Sprintf("channel%d", c), 83 }, 84 } 85 v := imageblk.NewVoxels(volume, values, data, int32(width)*bytesPerVoxel) 86 v3draw[c] = &Channel{ 87 Voxels: v, 88 channelNum: c + 1, 89 } 90 } 91 92 // Read in the data for each channel 93 for c = 0; c < int32(numChannels); c++ { 94 if err := binary.Read(reader, byteOrder, v3draw[c].Data()); err != nil { 95 return nil, fmt.Errorf("error reading data for channel %d: %v", c, err) 96 } 97 } 98 return v3draw, nil 99 }