public BufferedImage processTransform()

in api_dev/src/main/java/com/google/appengine/api/images/dev/LocalImagesService.java [564:686]


  public BufferedImage processTransform(BufferedImage image, Transform transform, Status status) {
    AffineTransform affine = null;
    BufferedImage constraintImage = null;
    if (transform.hasWidth() || transform.hasHeight()) {
      if (transform.getWidth() < 0 || transform.getHeight() < 0
          || transform.getWidth() > ImagesService.MAX_RESIZE_DIMENSIONS
          || transform.getHeight() > ImagesService.MAX_RESIZE_DIMENSIONS) {
        status.setSuccessful(false);
        status.setErrorCode(ErrorCode.BAD_TRANSFORM_DATA.getNumber());
        throw new ApiProxy.ApplicationException(ErrorCode.BAD_TRANSFORM_DATA.getNumber(),
            String.format("Invalid resize: width and height must be in range [0,%d]",
                ImagesService.MAX_RESIZE_DIMENSIONS));
      }
      if (transform.getWidth() == 0 && transform.getHeight() == 0) {
        status.setSuccessful(false);
        status.setErrorCode(ErrorCode.BAD_TRANSFORM_DATA.getNumber());
        throw new ApiProxy.ApplicationException(ErrorCode.BAD_TRANSFORM_DATA.getNumber(),
            "Invalid resize: width and height cannot both be 0.");
      }
      if (transform.getCropToFit() && (transform.getWidth() == 0 || transform.getHeight() == 0)) {
        status.setSuccessful(false);
        status.setErrorCode(ErrorCode.BAD_TRANSFORM_DATA.getNumber());
        throw new ApiProxy.ApplicationException(ErrorCode.BAD_TRANSFORM_DATA.getNumber(),
            "Invalid resize: neither width nor height can be 0 with crop to fit.");
      }
      if (transform.getAllowStretch()
          && (transform.getWidth() == 0 || transform.getHeight() == 0)) {
        status.setSuccessful(false);
        status.setErrorCode(ErrorCode.BAD_TRANSFORM_DATA.getNumber());
        throw new ApiProxy.ApplicationException(ErrorCode.BAD_TRANSFORM_DATA.getNumber(),
            "Invalid resize: neither width nor height can be 0 with allow stretch.");
      }
      if (transform.getCropToFit() && (!validCropArgument(transform.getCropOffsetX())
                                       || !validCropArgument(transform.getCropOffsetY()))) {
        status.setSuccessful(false);
        status.setErrorCode(ErrorCode.BAD_TRANSFORM_DATA.getNumber());
        throw new ApiProxy.ApplicationException(ErrorCode.BAD_TRANSFORM_DATA.getNumber(),
            "Invalid resize: crop offsets must be in the range 0.0 to 1.0.");
      }
      double aspectRatio = (double) image.getWidth() / (double) image.getHeight();
      double xFactor = (double) transform.getWidth() / (double) image.getWidth();
      double yFactor = (double) transform.getHeight() / (double) image.getHeight();
      double transformFactor;

      ImageTypeSpecifier imageSpecifier = ImageTypeSpecifier.createFromRenderedImage(image);
      if (transform.getAllowStretch()) {
        constraintImage = imageSpecifier.createBufferedImage(transform.getWidth(),
                                                             transform.getHeight());
        affine = AffineTransform.getScaleInstance(xFactor, yFactor);
      } else if (transform.getCropToFit()) {
        transformFactor = Math.max(xFactor, yFactor);
        constraintImage = imageSpecifier.createBufferedImage(transform.getWidth(),
                                                             transform.getHeight());
        double uncroppedWidth = image.getWidth() * transformFactor;
        double uncroppedHeight = image.getHeight() * transformFactor;
        affine = new AffineTransform(
            transformFactor, 0, 0, transformFactor,
            (transform.getWidth() - uncroppedWidth) * transform.getCropOffsetX(),
            (transform.getHeight() - uncroppedHeight) * transform.getCropOffsetY());
      } else {
        if (xFactor < yFactor && xFactor != 0) {
          transformFactor = xFactor;
          constraintImage = imageSpecifier.createBufferedImage(
              transform.getWidth(),
              (int) Math.round(transform.getWidth() / aspectRatio));
        } else {
          transformFactor = yFactor;
          constraintImage = imageSpecifier.createBufferedImage(
              (int) Math.round(transform.getHeight() * aspectRatio),
              transform.getHeight());
        }
        affine = AffineTransform.getScaleInstance(transformFactor, transformFactor);
      }
    } else if (transform.hasRotate()) {
      if ((transform.getRotate() % 90) != 0 || transform.getRotate() >= 360
          || transform.getRotate() < 0) {
        status.setSuccessful(false);
        status.setErrorCode(ErrorCode.BAD_TRANSFORM_DATA.getNumber());
        throw new ApiProxy.ApplicationException(
            ErrorCode.BAD_TRANSFORM_DATA.getNumber(), "Invalid rotate.");
      }
      affine = AffineTransform.getRotateInstance(Math.toRadians(transform.getRotate()));
      if (transform.getRotate() == 90) {
        affine.translate(0, -image.getHeight());
      } else if (transform.getRotate() == 180) {
        affine.translate(-image.getWidth(), -image.getHeight());
      } else if (transform.getRotate() == 270) {
        affine.translate(-image.getWidth(), 0);
      }
    } else if (transform.hasHorizontalFlip()) {
      affine = new AffineTransform(-1.0, 0.0, 0.0, 1.0, image.getWidth(), 0.0);
    } else if (transform.hasVerticalFlip()) {
      affine = new AffineTransform(1.0, 0.0, 0.0, -1.0, 0.0, image.getHeight());
    } else if (transform.hasCropLeftX() || transform.hasCropTopY() || transform.hasCropRightX()
        || transform.hasCropBottomY()) {
      if (!validCropArgs(transform)) {
        status.setSuccessful(false);
        status.setErrorCode(ErrorCode.BAD_TRANSFORM_DATA.getNumber());
        throw new ApiProxy.ApplicationException(
            ErrorCode.BAD_TRANSFORM_DATA.getNumber(), "Invalid crop.");
      }
      int startX = Math.round(transform.getCropLeftX() * image.getWidth());
      int startY = Math.round(transform.getCropTopY() * image.getHeight());
      int width = Math.min(
          Math.round((transform.getCropRightX() - transform.getCropLeftX()) * image.getWidth()),
          image.getWidth() - startX);
      int height = Math.min(
          Math.round((transform.getCropBottomY() - transform.getCropTopY()) * image.getHeight()),
          image.getHeight() - startY);
      return image.getSubimage(startX, startY, width, height);
    } else if (transform.hasAutolevels()) {
      log.warning("I'm Feeling Lucky is not available in the SDK.");
    } else {
      status.setSuccessful(false);
      status.setErrorCode(ErrorCode.BAD_TRANSFORM_DATA.getNumber());
      throw new ApiProxy.ApplicationException(ErrorCode.BAD_TRANSFORM_DATA.getNumber());
    }
    if (affine != null) {
      AffineTransformOp op = new AffineTransformOp(affine, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
      return op.filter(image, constraintImage);
    }
    return image;
  }