Beispiel #1
0
// NewLabels returns labelblk Labels, a representation of externally usable subvolume
// or slice data, given some geometry and optional image data.
// If img is passed in, the function will initialize Voxels with data from the image.
// Otherwise, it will allocate a zero buffer of appropriate size.
//
// TODO : Unlike the standard imageblk.NewVoxels, the labelblk version can modify the
// labels based on the z-coordinate of the given geometry for Raveler labeling.
// This will be removed when Raveler-specific labels are moved outside DVID.
func (d *Data) NewLabels(geom dvid.Geometry, img interface{}) (*Labels, error) {
	bytesPerVoxel := d.Properties.Values.BytesPerElement()
	stride := geom.Size().Value(0) * bytesPerVoxel
	var data []byte

	if img == nil {
		numVoxels := geom.NumVoxels()
		if numVoxels <= 0 {
			return nil, fmt.Errorf("Illegal geometry requested: %s", geom)
		}
		requestSize := int64(bytesPerVoxel) * numVoxels
		if requestSize > server.MaxDataRequest {
			return nil, fmt.Errorf("Requested payload (%d bytes) exceeds this DVID server's set limit (%d)",
				requestSize, server.MaxDataRequest)
		}
		data = make([]byte, requestSize)
	} else {
		switch t := img.(type) {
		case image.Image:
			var inputBytesPerVoxel, actualStride int32
			var err error
			data, inputBytesPerVoxel, actualStride, err = dvid.ImageData(t)
			if err != nil {
				return nil, err
			}
			if actualStride != stride {
				// Need to do some conversion here.
				switch d.Labeling {
				case Standard64bit:
					data, err = d.convertTo64bit(geom, data, int(inputBytesPerVoxel), int(actualStride))
					if err != nil {
						return nil, err
					}
				case RavelerLabel:
					data, err = d.addLabelZ(geom, data, actualStride)
					if err != nil {
						return nil, err
					}
				default:
					return nil, fmt.Errorf("unexpected label type in labelblk: %s", d.Labeling)
				}
			}
		case []byte:
			data = t
			actualLen := int64(len(data))
			expectedLen := int64(bytesPerVoxel) * geom.NumVoxels()
			if actualLen != expectedLen {
				return nil, fmt.Errorf("labels data was %d bytes, expected %d bytes for %s",
					actualLen, expectedLen, geom)
			}
		default:
			return nil, fmt.Errorf("unexpected image type given to NewVoxels(): %T", t)
		}
	}

	labels := &Labels{
		imageblk.NewVoxels(geom, d.Properties.Values, data, stride),
	}
	return labels, nil
}
Beispiel #2
0
// Create a RGB interleaved volume.
func (d *Data) storeComposite(v dvid.VersionID, channels []*Channel) error {
	// Setup the composite Channel
	geom := channels[0].Geometry
	pixels := int(geom.NumVoxels())
	stride := geom.Size().Value(0) * 4
	composite := &Channel{
		Voxels:     imageblk.NewVoxels(geom, compositeValues, channels[0].Data(), stride),
		channelNum: channels[0].channelNum,
	}

	// Get the min/max of each channel.
	numChannels := len(channels)
	if numChannels > 3 {
		numChannels = 3
	}
	var min, max [3]uint16
	min[0] = uint16(0xFFFF)
	min[1] = uint16(0xFFFF)
	min[2] = uint16(0xFFFF)
	for c := 0; c < numChannels; c++ {
		channel := channels[c]
		data := channel.Data()
		beg := 0
		for i := 0; i < pixels; i++ {
			value := binary.LittleEndian.Uint16(data[beg : beg+2])
			if value < min[c] {
				min[c] = value
			}
			if value > max[c] {
				max[c] = value
			}
			beg += 2
		}
	}

	// Do second pass, normalizing each channel and storing it into the appropriate byte.
	compdata := composite.Voxels.Data()
	for c := 0; c < numChannels; c++ {
		channel := channels[c]
		window := int(max[c] - min[c])
		if window == 0 {
			window = 1
		}
		data := channel.Data()
		beg := 0
		begC := c // Channel 0 -> R, Channel 1 -> G, Channel 2 -> B
		for i := 0; i < pixels; i++ {
			value := binary.LittleEndian.Uint16(data[beg : beg+2])
			normalized := 255 * int(value-min[c]) / window
			if normalized > 255 {
				normalized = 255
			}
			compdata[begC] = uint8(normalized)
			beg += 2
			begC += 4
		}
	}

	// Set the alpha channel to 255.
	alphaI := 3
	for i := 0; i < pixels; i++ {
		compdata[alphaI] = 255
		alphaI += 4
	}

	// Store the result
	return d.PutVoxels(v, composite.Voxels, nil)
}
Beispiel #3
0
// ServeHTTP handles all incoming HTTP requests for this data.
func (d *Data) ServeHTTP(uuid dvid.UUID, ctx *datastore.VersionedCtx, w http.ResponseWriter, r *http.Request) {
	timedLog := dvid.NewTimeLog()

	// Get the action (GET, POST)
	action := strings.ToLower(r.Method)
	switch action {
	case "get":
	case "post":
	default:
		server.BadRequest(w, r, "Can only handle GET or POST HTTP verbs")
		return
	}

	// Break URL request into arguments
	url := r.URL.Path[len(server.WebAPIPath):]
	parts := strings.Split(url, "/")
	if len(parts[len(parts)-1]) == 0 {
		parts = parts[:len(parts)-1]
	}
	if len(parts) < 4 {
		server.BadRequest(w, r, "Incomplete API request")
		return
	}

	// Process help and info.
	switch parts[3] {
	case "help":
		w.Header().Set("Content-Type", "text/plain")
		fmt.Fprintln(w, d.Help())
		return
	case "info":
		jsonBytes, err := d.MarshalJSON()
		if err != nil {
			server.BadRequest(w, r, err)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		fmt.Fprintf(w, string(jsonBytes))
		return
	default:
	}

	// Get the data name and parse out the channel number or see if composite is required.
	var channelNum int32
	channumStr := strings.TrimPrefix(parts[2], string(d.DataName()))
	if len(channumStr) == 0 {
		channelNum = 0
	} else {
		n, err := strconv.ParseInt(channumStr, 10, 32)
		if err != nil {
			server.BadRequest(w, r, "Error parsing channel number from data name '%s': %v", parts[2], err)
			return
		}
		if int(n) > d.NumChannels {
			minChannelName := fmt.Sprintf("%s1", d.DataName())
			maxChannelName := fmt.Sprintf("%s%d", d.DataName(), d.NumChannels)
			server.BadRequest(w, r, "Data only has %d channels.  Use names '%s' -> '%s'", d.NumChannels,
				minChannelName, maxChannelName)
			return
		}
		channelNum = int32(n)
	}

	// Get the data shape.
	shapeStr := dvid.DataShapeString(parts[3])
	dataShape, err := shapeStr.DataShape()
	if err != nil {
		server.BadRequest(w, r, "Bad data shape given '%s'", shapeStr)
		return
	}

	switch dataShape.ShapeDimensions() {
	case 2:
		sizeStr, offsetStr := parts[4], parts[5]
		slice, err := dvid.NewSliceFromStrings(shapeStr, offsetStr, sizeStr, "_")
		if err != nil {
			server.BadRequest(w, r, err)
			return
		}
		if action == "post" {
			server.BadRequest(w, r, "DVID does not yet support POST of slices into multichannel data")
			return
		} else {
			if d.NumChannels == 0 || d.Data.Values == nil {
				server.BadRequest(w, r, "Cannot retrieve absent data '%d'.  Please load data.", d.DataName())
				return
			}
			values := d.Data.Values
			if len(values) <= int(channelNum) {
				server.BadRequest(w, r, "Must choose channel from 0 to %d", len(values))
				return
			}
			stride := slice.Size().Value(0) * values.BytesPerElement()
			dataValues := dvid.DataValues{values[channelNum]}
			data := make([]uint8, int(slice.NumVoxels()))
			v := imageblk.NewVoxels(slice, dataValues, data, stride)
			channel := &Channel{
				Voxels:     v,
				channelNum: channelNum,
			}
			img, err := d.GetImage(ctx.VersionID(), channel.Voxels, nil)
			var formatStr string
			if len(parts) >= 7 {
				formatStr = parts[6]
			}
			//dvid.ElapsedTime(dvid.Normal, startTime, "%s %s upto image formatting", op, slice)
			err = dvid.WriteImageHttp(w, img.Get(), formatStr)
			if err != nil {
				server.BadRequest(w, r, err)
				return
			}
		}
	case 3:
		sizeStr, offsetStr := parts[4], parts[5]
		_, err := dvid.NewSubvolumeFromStrings(offsetStr, sizeStr, "_")
		if err != nil {
			server.BadRequest(w, r, err)
			return
		}
		if action == "get" {
			server.BadRequest(w, r, "DVID does not yet support GET of volume data")
			return
		} else {
			server.BadRequest(w, r, "DVID does not yet support POST of volume data")
			return
		}
	default:
		server.BadRequest(w, r, "DVID does not yet support nD volumes")
		return
	}
	timedLog.Infof("HTTP %s: %s", r.Method, dataShape)
}
Beispiel #4
0
func (V3DRawMarshaler) UnmarshalV3DRaw(reader io.Reader) ([]*Channel, error) {
	magicString := make([]byte, 24)
	if n, err := reader.Read(magicString); n != 24 || err != nil {
		return nil, fmt.Errorf("error reading magic string in V3D Raw file: %v", err)
	}
	if string(magicString) != "raw_image_stack_by_hpeng" {
		return nil, fmt.Errorf("bad magic string in V3D Raw File: %s", string(magicString))
	}
	endianType := make([]byte, 1, 1)
	if n, err := reader.Read(endianType); n != 1 || err != nil {
		return nil, fmt.Errorf("could not read endianness of V3D Raw file: %v", err)
	}
	var byteOrder binary.ByteOrder
	switch string(endianType) {
	case "L":
		byteOrder = binary.LittleEndian
	case "B":
		return nil, fmt.Errorf("cannot handle big endian byte order in V3D Raw File")
	default:
		return nil, fmt.Errorf("illegal byte order '%s' in V3D Raw File", endianType)
	}
	var dataType uint16
	if err := binary.Read(reader, byteOrder, &dataType); err != nil {
		return nil, err
	}
	var bytesPerVoxel int32
	switch dataType {
	case 1:
		bytesPerVoxel = 1
	case 2:
		bytesPerVoxel = 2
	default:
		return nil, fmt.Errorf("cannot handle V3D Raw File with data type %d", dataType)
	}
	var width, height, depth, numChannels uint32
	if err := binary.Read(reader, byteOrder, &width); err != nil {
		return nil, fmt.Errorf("error reading width in V3D Raw File: %v", err)
	}
	if err := binary.Read(reader, byteOrder, &height); err != nil {
		return nil, fmt.Errorf("error reading height in V3D Raw File: %v", err)
	}
	if err := binary.Read(reader, byteOrder, &depth); err != nil {
		return nil, fmt.Errorf("error reading depth in V3D Raw File: %v", err)
	}
	if err := binary.Read(reader, byteOrder, &numChannels); err != nil {
		return nil, fmt.Errorf("error reading # channels in V3D Raw File: %v", err)
	}

	// Allocate the V3DRaw struct for the # channels
	totalBytes := int(bytesPerVoxel) * int(width*height*depth)
	size := dvid.Point3d{int32(width), int32(height), int32(depth)}
	volume := dvid.NewSubvolume(dvid.Point3d{0, 0, 0}, size)
	v3draw := make([]*Channel, numChannels, numChannels)
	var c int32
	for c = 0; c < int32(numChannels); c++ {
		data := make([]uint8, totalBytes, totalBytes)
		var t dvid.DataType
		switch bytesPerVoxel {
		case 1:
			t = dvid.T_uint8
		case 2:
			t = dvid.T_uint16
		}
		values := dvid.DataValues{
			{
				T:     t,
				Label: fmt.Sprintf("channel%d", c),
			},
		}
		v := imageblk.NewVoxels(volume, values, data, int32(width)*bytesPerVoxel)
		v3draw[c] = &Channel{
			Voxels:     v,
			channelNum: c + 1,
		}
	}

	// Read in the data for each channel
	for c = 0; c < int32(numChannels); c++ {
		if err := binary.Read(reader, byteOrder, v3draw[c].Data()); err != nil {
			return nil, fmt.Errorf("error reading data for channel %d: %v", c, err)
		}
	}
	return v3draw, nil
}