docs: def warp(self, target_bbox, target_size=None):
          """Returns a copy of this image warped to a target size and bounding box"""
  
          # Determine target size based on pixels per unit of the source image and the target bounding box reprojected
          # to the source projection.
          if not target_size:
              px_per_unit = (float(self.image.size[0])/self.bbox.width, float(self.image.size[1])/self.bbox.height)
              src_bbox = target_bbox.project(self.bbox.projection)
              target_size = (int(round(src_bbox.width*px_per_unit[0])), int(round(src_bbox.height*px_per_unit[1])))
  
          canvas_size = (
              max(target_size[0], self.image.size[0]),
              max(target_size[1], self.image.size[1])
          )
  
          # If target and source bounds are the same and source and target sizes are the same, return a reference to
          # this image.
          if self.bbox == target_bbox and self.image.size == target_size:
              return self
  
          # If target and source projections are the same, perform a simple resize
          elif self.bbox.projection.srs == target_bbox.projection.srs:
              to_source_image = world_to_image(self.bbox, self.image.size)
              upper_left = to_source_image(*(target_bbox.xmin, target_bbox.ymax))
              lower_right = to_source_image(*(target_bbox.xmax, target_bbox.ymin))
  
              if canvas_size == self.image.size:
                  im = self.image
              else:
                  im = Image.new("RGBA", canvas_size, (0, 0, 0, 0))
                  im.paste(self.image, (0, 0))
  
              new_image = im.transform(
                  target_size, Image.EXTENT, (upper_left[0], upper_left[1], lower_right[0], lower_right[1]),
                  Image.NEAREST
              )
  
          # Full warp
          else:
              if canvas_size == self.image.size:
                  im = self.image
              else:
                  im = Image.new("RGBA", canvas_size, (0, 0, 0, 0))
                  im.paste(self.image, (0, 0))
  
              new_image = im.transform(
                  target_size, Image.MESH, self._create_mesh(target_bbox, target_size), Image.NEAREST
              )
  
          return GeoImage(new_image, target_bbox)