// BlankImage initializes a blank image of appropriate size and depth for the // current data values. Returns an error if the geometry is not 2d. func (d *Data) BlankImage(dstW, dstH int32) (*dvid.Image, error) { // Make sure values for this data can be converted into an image. valuesPerVoxel := int32(len(d.Properties.Values)) if valuesPerVoxel < 1 || valuesPerVoxel > 4 { return nil, fmt.Errorf("Standard voxels type can't convert %d values/voxel into image.", valuesPerVoxel) } bytesPerValue, err := d.Properties.Values.BytesPerValue() if err != nil { return nil, err } unsupported := func() error { return fmt.Errorf("DVID doesn't support images for %d channels and %d bytes/channel", valuesPerVoxel, bytesPerValue) } var img image.Image stride := int(dstW * valuesPerVoxel * bytesPerValue) r := image.Rect(0, 0, int(dstW), int(dstH)) imageBytes := int(dstH) * stride data := make([]uint8, imageBytes, imageBytes) switch valuesPerVoxel { case 1: switch bytesPerValue { case 1: img = &image.Gray{ Stride: stride, Rect: r, Pix: data, } case 2: img = &image.Gray16{ Stride: stride, Rect: r, Pix: data, } case 4: img = &image.NRGBA{ Stride: stride, Rect: r, Pix: data, } case 8: img = &image.NRGBA64{ Stride: stride, Rect: r, Pix: data, } default: return nil, unsupported() } case 4: switch bytesPerValue { case 1: img = &image.NRGBA{ Stride: stride, Rect: r, Pix: data, } case 2: img = &image.NRGBA64{ Stride: stride, Rect: r, Pix: data, } default: return nil, unsupported() } default: return nil, unsupported() } return dvid.ImageFromGoImage(img, d.Properties.Values, d.Properties.Interpolable) }
// GetImage2d returns a 2d image suitable for use external to DVID. // TODO -- Create more comprehensive handling of endianness and encoding of // multibytes/voxel data into appropriate images. func (v *Voxels) GetImage2d() (*dvid.Image, error) { // Make sure each value has same # of bytes or else we can't generate a go image. // If so, we need to make another ExtData that knows how to convert the varying // values into an appropriate go image. valuesPerVoxel := int32(len(v.values)) if valuesPerVoxel < 1 || valuesPerVoxel > 4 { return nil, fmt.Errorf("Standard voxels type can't convert %d values/voxel into image.", valuesPerVoxel) } bytesPerValue := v.values.ValueBytes(0) for _, dataValue := range v.values { if dvid.DataTypeBytes(dataValue.T) != bytesPerValue { return nil, fmt.Errorf("Standard voxels type can't handle varying sized values per voxel.") } } unsupported := func() error { return fmt.Errorf("DVID doesn't support images for %d channels and %d bytes/channel", valuesPerVoxel, bytesPerValue) } var img image.Image width := v.Size().Value(0) height := v.Size().Value(1) sliceBytes := width * height * valuesPerVoxel * bytesPerValue beg := int32(0) end := beg + sliceBytes data := v.Data() if int(end) > len(data) { return nil, fmt.Errorf("Voxels %s has insufficient amount of data to return an image.", v) } r := image.Rect(0, 0, int(width), int(height)) switch valuesPerVoxel { case 1: switch bytesPerValue { case 1: img = &image.Gray{data[beg:end], 1 * r.Dx(), r} case 2: bigendian, err := v.littleToBigEndian(data[beg:end]) if err != nil { return nil, err } img = &image.Gray16{bigendian, 2 * r.Dx(), r} case 4: img = &image.NRGBA{data[beg:end], 4 * r.Dx(), r} case 8: img = &image.NRGBA64{data[beg:end], 8 * r.Dx(), r} default: return nil, unsupported() } case 4: switch bytesPerValue { case 1: img = &image.NRGBA{data[beg:end], 4 * r.Dx(), r} case 2: img = &image.NRGBA64{data[beg:end], 8 * r.Dx(), r} default: return nil, unsupported() } default: return nil, unsupported() } return dvid.ImageFromGoImage(img, v.Values(), v.Interpolable()) }