// ServeTile returns a tile with appropriate Content-Type set. func (d *Data) ServeTile(uuid dvid.UUID, ctx storage.Context, w http.ResponseWriter, r *http.Request, parts []string) error { if d.Levels == nil || len(d.Levels) == 0 { return ErrNoMetadataSet } tileReq, err := d.parseTileReq(r, parts) queryValues := r.URL.Query() noblanksStr := dvid.InstanceName(queryValues.Get("noblanks")) var noblanks bool if noblanksStr == "true" { noblanks = true } var formatStr string if len(parts) >= 8 { formatStr = parts[7] } data, err := d.getTileData(ctx, tileReq) if err != nil { server.BadRequest(w, r, err) return err } if data == nil { if noblanks { http.NotFound(w, r) return nil } img, err := d.getBlankTileImage(uuid, tileReq) if err != nil { return err } return dvid.WriteImageHttp(w, img, formatStr) } switch d.Encoding { case LZ4: var img dvid.Image if err := img.Deserialize(data); err != nil { return err } data, err = img.GetPNG() w.Header().Set("Content-type", "image/png") case PNG: w.Header().Set("Content-type", "image/png") case JPG: w.Header().Set("Content-type", "image/jpeg") } if err != nil { server.BadRequest(w, r, err) return err } if _, err = w.Write(data); err != nil { return err } return nil }
// make sure the given labels match what would be expected from the test volume. func (s sliceTester) testLabel(t *testing.T, vol labelVol, img *dvid.Image) { data := img.Data() var x, y, z int32 i := 0 switch s.orient { case "xy": for y = 0; y < s.height; y++ { for x = 0; x < s.width; x++ { label := binary.LittleEndian.Uint64(data[i*8 : (i+1)*8]) i++ vx := x + s.offset[0] vy := y + s.offset[1] vz := s.offset[2] expected := vol.label(vx, vy, vz) if label != expected { t.Errorf("Bad label @ (%d,%d,%d): expected %d, got %d\n", vx, vy, vz, expected, label) return } } } return case "xz": for z = 0; z < s.height; z++ { for x = 0; x < s.width; x++ { label := binary.LittleEndian.Uint64(data[i*8 : (i+1)*8]) i++ vx := x + s.offset[0] vy := s.offset[1] vz := z + s.offset[2] expected := vol.label(vx, vy, vz) if label != expected { t.Errorf("Bad label @ (%d,%d,%d): expected %d, got %d\n", vx, vy, vz, expected, label) return } } } return case "yz": for z = 0; z < s.height; z++ { for y = 0; x < s.width; x++ { label := binary.LittleEndian.Uint64(data[i*8 : (i+1)*8]) i++ vx := s.offset[0] vy := y * s.offset[1] vz := z + s.offset[2] expected := vol.label(vx, vy, vz) if label != expected { t.Errorf("Bad label @ (%d,%d,%d): expected %d, got %d\n", vx, vy, vz, expected, label) return } } } return default: t.Fatalf("Unknown slice orientation %q\n", s.orient) } }
// getTileImage returns a 2d tile image or a placeholder, useful for further stitching before // delivery of a final image. func (d *Data) getTileImage(ctx storage.Context, req TileReq) (image.Image, error) { if d.Levels == nil || len(d.Levels) == 0 { return nil, ErrNoMetadataSet } data, err := d.getTileData(ctx, req) if err != nil { return nil, err } if len(data) == 0 { if d.Placeholder { if req.scale < 0 || req.scale >= Scaling(len(d.Levels)) { return nil, fmt.Errorf("Could not find tile specification at given scale %d", req.scale) } message := fmt.Sprintf("%s Tile coord %s @ scale %d", req.plane, req.tile, req.scale) return dvid.PlaceholderImage(req.plane, d.Levels[req.scale].TileSize, message) } return nil, nil // Not found } var goImg image.Image switch d.Encoding { case LZ4: var img dvid.Image err = img.Deserialize(data) if err != nil { return nil, err } goImg = img.Get() case PNG: pngBuffer := bytes.NewBuffer(data) goImg, err = png.Decode(pngBuffer) case JPG: jpgBuffer := bytes.NewBuffer(data) goImg, err = jpeg.Decode(jpgBuffer) default: return nil, fmt.Errorf("Unknown tile encoding: %s", d.Encoding) } return goImg, err }
// GetTile returns a 2d tile image or a placeholder func (d *Data) GetTile(ctx storage.Context, shape dvid.DataShape, scaling Scaling, index dvid.IndexZYX) (image.Image, error) { data, err := d.getTileData(ctx, shape, scaling, index) if err != nil { return nil, err } tileIndex := &IndexTile{&index, shape, scaling} if data == nil { if d.Placeholder { if d.Levels == nil || scaling < 0 || scaling >= Scaling(len(d.Levels)) { return nil, fmt.Errorf("Could not find tile specification at given scale %d", scaling) } message := fmt.Sprintf("%s Tile coord %s @ scale %d", shape, tileIndex, scaling) return dvid.PlaceholderImage(shape, d.Levels[scaling].TileSize, message) } return nil, nil // Not found } var goImg image.Image switch d.Encoding { case LZ4: var img dvid.Image err = img.Deserialize(data) if err != nil { return nil, err } goImg = img.Get() case PNG: pngBuffer := bytes.NewBuffer(data) goImg, err = png.Decode(pngBuffer) case JPG: jpgBuffer := bytes.NewBuffer(data) goImg, err = jpeg.Decode(jpgBuffer) default: return nil, fmt.Errorf("Unknown tile encoding: %s", d.Encoding) } return goImg, err }
// ServeTile returns a tile with appropriate Content-Type set. func (d *Data) ServeTile(uuid dvid.UUID, ctx storage.Context, w http.ResponseWriter, r *http.Request, parts []string) error { if len(parts) < 7 { return fmt.Errorf("'tile' request must be following by plane, scale level, and tile coordinate") } planeStr, scalingStr, coordStr := parts[4], parts[5], parts[6] queryValues := r.URL.Query() noblanksStr := dvid.InstanceName(queryValues.Get("noblanks")) var noblanks bool if noblanksStr == "true" { noblanks = true } var formatStr string if len(parts) >= 8 { formatStr = parts[7] } // Construct the index for this tile plane := dvid.DataShapeString(planeStr) shape, err := plane.DataShape() if err != nil { err = fmt.Errorf("Illegal tile plane: %s (%v)", planeStr, err) server.BadRequest(w, r, err) return err } scaling, err := strconv.ParseUint(scalingStr, 10, 8) if err != nil { err = fmt.Errorf("Illegal tile scale: %s (%v)", scalingStr, err) server.BadRequest(w, r, err) return err } tileCoord, err := dvid.StringToPoint(coordStr, "_") if err != nil { err = fmt.Errorf("Illegal tile coordinate: %s (%v)", coordStr, err) server.BadRequest(w, r, err) return err } if tileCoord.NumDims() != 3 { err = fmt.Errorf("Expected 3d tile coordinate, got %s", coordStr) server.BadRequest(w, r, err) return err } indexZYX := dvid.IndexZYX{tileCoord.Value(0), tileCoord.Value(1), tileCoord.Value(2)} data, err := d.getTileData(ctx, shape, Scaling(scaling), indexZYX) if err != nil { server.BadRequest(w, r, err) return err } if data == nil { if noblanks { http.NotFound(w, r) return nil } img, err := d.getBlankTileImage(uuid, shape, Scaling(scaling)) if err != nil { return err } return dvid.WriteImageHttp(w, img, formatStr) } switch d.Encoding { case LZ4: var img dvid.Image if err := img.Deserialize(data); err != nil { return err } data, err = img.GetPNG() w.Header().Set("Content-type", "image/png") case PNG: w.Header().Set("Content-type", "image/png") case JPG: w.Header().Set("Content-type", "image/jpeg") } if err != nil { server.BadRequest(w, r, err) return err } if _, err = w.Write(data); err != nil { return err } return nil }