|
35 | 35 | from titiler.core.resources.responses import GeoJSONResponse, XMLResponse |
36 | 36 | from titiler.core.utils import Timer, bbox_to_feature |
37 | 37 |
|
38 | | -from fastapi import APIRouter, Depends, Path, Query |
| 38 | +from fastapi import APIRouter, Body, Depends, Path, Query |
39 | 39 |
|
40 | 40 | from starlette.requests import Request |
41 | 41 | from starlette.responses import Response |
@@ -706,6 +706,72 @@ def part( |
706 | 706 |
|
707 | 707 | return Response(content, media_type=format.mediatype, headers=headers) |
708 | 708 |
|
| 709 | + @self.router.post( |
| 710 | + r"/crop", **img_endpoint_params, |
| 711 | + ) |
| 712 | + @self.router.post( |
| 713 | + r"/crop.{format}", **img_endpoint_params, |
| 714 | + ) |
| 715 | + @self.router.post( |
| 716 | + r"/crop/{width}x{height}.{format}", **img_endpoint_params, |
| 717 | + ) |
| 718 | + def geojson_crop( |
| 719 | + feature: Feature = Body(..., descriptiom="GeoJSON Feature."), |
| 720 | + format: ImageType = Query( |
| 721 | + None, description="Output image type. Default is auto." |
| 722 | + ), |
| 723 | + src_path=Depends(self.path_dependency), |
| 724 | + layer_params=Depends(self.layer_dependency), |
| 725 | + image_params=Depends(self.img_dependency), |
| 726 | + dataset_params=Depends(self.dataset_dependency), |
| 727 | + render_params=Depends(self.render_dependency), |
| 728 | + colormap=Depends(self.colormap_dependency), |
| 729 | + kwargs: Dict = Depends(self.additional_dependency), |
| 730 | + ): |
| 731 | + """Create image from a geojson feature.""" |
| 732 | + timings = [] |
| 733 | + headers: Dict[str, str] = {} |
| 734 | + |
| 735 | + with Timer() as t: |
| 736 | + with rasterio.Env(**self.gdal_config): |
| 737 | + with self.reader(src_path, **self.reader_options) as src_dst: |
| 738 | + data = src_dst.feature( |
| 739 | + feature.dict(exclude_none=True), |
| 740 | + **layer_params.kwargs, |
| 741 | + **image_params.kwargs, |
| 742 | + **dataset_params.kwargs, |
| 743 | + **kwargs, |
| 744 | + ) |
| 745 | + dst_colormap = getattr(src_dst, "colormap", None) |
| 746 | + timings.append(("dataread", round(t.elapsed * 1000, 2))) |
| 747 | + |
| 748 | + with Timer() as t: |
| 749 | + image = data.post_process( |
| 750 | + in_range=render_params.rescale_range, |
| 751 | + color_formula=render_params.color_formula, |
| 752 | + ) |
| 753 | + timings.append(("postprocess", round(t.elapsed * 1000, 2))) |
| 754 | + |
| 755 | + if not format: |
| 756 | + format = ImageType.jpeg if data.mask.all() else ImageType.png |
| 757 | + |
| 758 | + with Timer() as t: |
| 759 | + content = image.render( |
| 760 | + add_mask=render_params.return_mask, |
| 761 | + img_format=format.driver, |
| 762 | + colormap=colormap or dst_colormap, |
| 763 | + **format.profile, |
| 764 | + **render_params.kwargs, |
| 765 | + ) |
| 766 | + timings.append(("format", round(t.elapsed * 1000, 2))) |
| 767 | + |
| 768 | + if OptionalHeader.server_timing in self.optional_headers: |
| 769 | + headers["Server-Timing"] = ", ".join( |
| 770 | + [f"{name};dur={time}" for (name, time) in timings] |
| 771 | + ) |
| 772 | + |
| 773 | + return Response(content, media_type=format.mediatype, headers=headers) |
| 774 | + |
709 | 775 |
|
710 | 776 | @dataclass |
711 | 777 | class MultiBaseTilerFactory(TilerFactory): |
|
0 commit comments