Esempio n. 1
0
    def execute_transforms(self, output_encoding=PNG):
        """Perform transformations on given image.

    Args:
      output_encoding: A value from OUTPUT_ENCODING_TYPES.

    Returns:
      str, image data after the transformations have been performed on it.

    Raises:
      BadRequestError when there is something wrong with the request
        specifications.
      NotImageError when the image data given is not an image.
      BadImageError when the image data given is corrupt.
      LargeImageError when the image data given is too large to process.
      InvalidBlobKeyError when the blob key provided is invalid.
      TransformtionError when something errors during image manipulation.
      Error when something unknown, but bad, happens.
    """
        if output_encoding not in OUTPUT_ENCODING_TYPES:
            raise BadRequestError("Output encoding type not in recognized set "
                                  "%s" % OUTPUT_ENCODING_TYPES)

        if not self._transforms:
            raise BadRequestError("Must specify at least one transformation.")

        request = images_service_pb.ImagesTransformRequest()
        response = images_service_pb.ImagesTransformResponse()

        self._set_imagedata(request.mutable_image())

        for transform in self._transforms:
            request.add_transform().CopyFrom(transform)

        request.mutable_output().set_mime_type(output_encoding)

        try:
            apiproxy_stub_map.MakeSyncCall("images", "Transform", request,
                                           response)
        except apiproxy_errors.ApplicationError, e:
            if (e.application_error ==
                    images_service_pb.ImagesServiceError.BAD_TRANSFORM_DATA):
                raise BadRequestError()
            elif (e.application_error ==
                  images_service_pb.ImagesServiceError.NOT_IMAGE):
                raise NotImageError()
            elif (e.application_error ==
                  images_service_pb.ImagesServiceError.BAD_IMAGE_DATA):
                raise BadImageError()
            elif (e.application_error ==
                  images_service_pb.ImagesServiceError.IMAGE_TOO_LARGE):
                raise LargeImageError()
            elif (e.application_error ==
                  images_service_pb.ImagesServiceError.INVALID_BLOB_KEY):
                raise InvalidBlobKeyError()
            elif (e.application_error ==
                  images_service_pb.ImagesServiceError.UNSPECIFIED_ERROR):
                raise TransformationError()
            else:
                raise Error()
Esempio n. 2
0
  def execute_transforms(self, output_encoding=PNG, quality=None,
                         parse_source_metadata=False):
    """Perform transformations on a given image.

    Args:
      output_encoding: A value from OUTPUT_ENCODING_TYPES.
      quality: A value between 1 and 100 to specify the quality of the
        encoding.  This value is only used for JPEG & WEBP quality control.
      parse_source_metadata: when True the metadata (EXIF) of the source image
        is parsed before any transformations. The results can be retrieved
        via Image.get_original_metadata.

    Returns:
      str, image data after the transformations have been performed on it.

    Raises:
      BadRequestError when there is something wrong with the request
        specifications.
      NotImageError when the image data given is not an image.
      BadImageError when the image data given is corrupt.
      LargeImageError when the image data given is too large to process.
      InvalidBlobKeyError when the blob key provided is invalid.
      TransformtionError when something errors during image manipulation.
      Error when something unknown, but bad, happens.
    """
    if output_encoding not in OUTPUT_ENCODING_TYPES:
      raise BadRequestError("Output encoding type not in recognized set "
                            "%s" % OUTPUT_ENCODING_TYPES)

    if not self._transforms:
      raise BadRequestError("Must specify at least one transformation.")

    self.CheckValidIntParameter(quality, 1, 100, "quality")

    request = images_service_pb.ImagesTransformRequest()
    response = images_service_pb.ImagesTransformResponse()

    input_settings = request.mutable_input()
    input_settings.set_correct_exif_orientation(
        self._correct_orientation)

    if parse_source_metadata:
      input_settings.set_parse_metadata(True)

    self._set_imagedata(request.mutable_image())

    for transform in self._transforms:
      request.add_transform().CopyFrom(transform)

    request.mutable_output().set_mime_type(output_encoding)

    if ((output_encoding == JPEG or output_encoding == WEBP) and
        (quality is not None)):
      request.mutable_output().set_quality(quality)

    try:
      apiproxy_stub_map.MakeSyncCall("images",
                                     "Transform",
                                     request,
                                     response)
    except apiproxy_errors.ApplicationError, e:
      if (e.application_error ==
          images_service_pb.ImagesServiceError.BAD_TRANSFORM_DATA):
        raise BadRequestError()
      elif (e.application_error ==
            images_service_pb.ImagesServiceError.NOT_IMAGE):
        raise NotImageError()
      elif (e.application_error ==
            images_service_pb.ImagesServiceError.BAD_IMAGE_DATA):
        raise BadImageError()
      elif (e.application_error ==
            images_service_pb.ImagesServiceError.IMAGE_TOO_LARGE):
        raise LargeImageError()
      elif (e.application_error ==
            images_service_pb.ImagesServiceError.INVALID_BLOB_KEY):
        raise InvalidBlobKeyError()
      elif (e.application_error ==
            images_service_pb.ImagesServiceError.UNSPECIFIED_ERROR):
        raise TransformationError()
      else:
        raise Error()
Esempio n. 3
0
def composite(inputs, width, height, color=0, output_encoding=PNG, quality=None):
  """Composite one or more images onto a canvas.

  Args:
    inputs: a list of tuples (image_data, x_offset, y_offset, opacity, anchor)
    where
      image_data: str, source image data.
      x_offset: x offset in pixels from the anchor position
      y_offset: y offset in piyels from the anchor position
      opacity: opacity of the image specified as a float in range [0.0, 1.0]
      anchor: anchoring point from ANCHOR_POINTS. The anchor point of the image
      is aligned with the same anchor point of the canvas. e.g. TOP_RIGHT would
      place the top right corner of the image at the top right corner of the
      canvas then apply the x and y offsets.
    width: canvas width in pixels.
    height: canvas height in pixels.
    color: canvas background color encoded as a 32 bit unsigned int where each
      color channel is represented by one byte in order ARGB.
    output_encoding: a value from OUTPUT_ENCODING_TYPES.
    quality: A value between 1 and 100 to specify the quality of the
      encoding. This value is only used for JPEG quality control.

  Returns:
      str, image data of the composited image.

  Raises:
    TypeError If width, height, color, x_offset or y_offset are not of type
    int or long or if opacity is not a float
    BadRequestError If more than MAX_TRANSFORMS_PER_REQUEST compositions have
    been requested, if the canvas width or height is greater than 4000 or less
    than or equal to 0, if the color is invalid or if for any composition
    option, the opacity is outside the range [0,1] or the anchor is invalid.
  """
  if (not isinstance(width, (int, long)) or
      not isinstance(height, (int, long)) or
      not isinstance(color, (int, long))):
    raise TypeError("Width, height and color must be integers.")
  if output_encoding not in OUTPUT_ENCODING_TYPES:
    raise BadRequestError("Output encoding type '%s' not in recognized set "
                          "%s" % (output_encoding, OUTPUT_ENCODING_TYPES))

  if quality is not None:
    if not isinstance(quality, (int, long)):
      raise TypeError("Quality must be an integer.")
    if quality > 100 or quality < 1:
      raise BadRequestError("Quality must be between 1 and 100.")

  if not inputs:
    raise BadRequestError("Must provide at least one input")
  if len(inputs) > MAX_COMPOSITES_PER_REQUEST:
    raise BadRequestError("A maximum of %d composition operations can be"
                          "performed in a single request" %
                          MAX_COMPOSITES_PER_REQUEST)

  if width <= 0 or height <= 0:
    raise BadRequestError("Width and height must be > 0.")
  if width > 4000 or height > 4000:
    raise BadRequestError("Width and height must be <= 4000.")

  if color > 0xffffffff or color < 0:
    raise BadRequestError("Invalid color")

  if color >= 0x80000000:
    color -= 0x100000000

  image_map = {}

  request = images_service_pb.ImagesCompositeRequest()
  response = images_service_pb.ImagesTransformResponse()
  for (image, x, y, opacity, anchor) in inputs:
    if not image:
      raise BadRequestError("Each input must include an image")
    if (not isinstance(x, (int, long)) or
        not isinstance(y, (int, long)) or
        not isinstance(opacity, (float))):
      raise TypeError("x_offset, y_offset must be integers and opacity must"
                      "be a float")
    if x > 4000 or x < -4000:
      raise BadRequestError("xOffsets must be in range [-4000, 4000]")
    if y > 4000 or y < -4000:
      raise BadRequestError("yOffsets must be in range [-4000, 4000]")
    if opacity < 0 or opacity > 1:
      raise BadRequestError("Opacity must be in the range 0.0 to 1.0")
    if anchor not in ANCHOR_TYPES:
      raise BadRequestError("Anchor type '%s' not in recognized set %s" %
                            (anchor, ANCHOR_TYPES))
    if image not in image_map:
      image_map[image] = request.image_size()

      if isinstance(image, Image):
        image._set_imagedata(request.add_image())
      else:
        request.add_image().set_content(image)

    option = request.add_options()
    option.set_x_offset(x)
    option.set_y_offset(y)
    option.set_opacity(opacity)
    option.set_anchor(anchor)
    option.set_source_index(image_map[image])

  request.mutable_canvas().mutable_output().set_mime_type(output_encoding)
  request.mutable_canvas().set_width(width)
  request.mutable_canvas().set_height(height)
  request.mutable_canvas().set_color(color)

  if ((output_encoding == JPEG or output_encoding == WEBP) and
      (quality is not None)):
      request.mutable_canvas().mutable_output().set_quality(quality)

  try:
    apiproxy_stub_map.MakeSyncCall("images",
                                   "Composite",
                                   request,
                                   response)
  except apiproxy_errors.ApplicationError, e:
    if (e.application_error ==
        images_service_pb.ImagesServiceError.BAD_TRANSFORM_DATA):
      raise BadRequestError()
    elif (e.application_error ==
          images_service_pb.ImagesServiceError.NOT_IMAGE):
      raise NotImageError()
    elif (e.application_error ==
          images_service_pb.ImagesServiceError.BAD_IMAGE_DATA):
      raise BadImageError()
    elif (e.application_error ==
          images_service_pb.ImagesServiceError.IMAGE_TOO_LARGE):
      raise LargeImageError()
    elif (e.application_error ==
          images_service_pb.ImagesServiceError.INVALID_BLOB_KEY):
      raise InvalidBlobKeyError()
    elif (e.application_error ==
          images_service_pb.ImagesServiceError.UNSPECIFIED_ERROR):
      raise TransformationError()
    else:
      raise Error()