private void assembleOperation(IMOperation op, Parameters params, Dimension fullSize) {
    // region transformation
    Region region = params.getRegion();
    if (!region.isFull()) {
      if (region.isPercent()) {
        // im4java doesn't support cropping x/y by percentage (only
        // width/height), so we have to calculate them.
        int x = Math.round(region.getX() / 100.0f * fullSize.width);
        int y = Math.round(region.getY() / 100.0f * fullSize.height);
        int width = Math.round(region.getWidth());
        int height = Math.round(region.getHeight());
        op.crop(width, height, x, y, "%");
      } else {
        op.crop(
            Math.round(region.getWidth()), Math.round(region.getHeight()),
            Math.round(region.getX()), Math.round(region.getY()));
      }
    }

    // size transformation
    Size size = params.getSize();
    if (size.getScaleMode() != Size.ScaleMode.FULL) {
      if (size.getScaleMode() == Size.ScaleMode.ASPECT_FIT_WIDTH) {
        op.resize(size.getWidth());
      } else if (size.getScaleMode() == Size.ScaleMode.ASPECT_FIT_HEIGHT) {
        op.resize(null, size.getHeight());
      } else if (size.getScaleMode() == Size.ScaleMode.NON_ASPECT_FILL) {
        op.resize(size.getWidth(), size.getHeight(), "!".charAt(0));
      } else if (size.getScaleMode() == Size.ScaleMode.ASPECT_FIT_INSIDE) {
        op.resize(size.getWidth(), size.getHeight());
      } else if (size.getPercent() != null) {
        op.resize(Math.round(size.getPercent()), Math.round(size.getPercent()), "%".charAt(0));
      }
    }

    // rotation transformation
    Rotation rotation = params.getRotation();
    if (rotation.shouldMirror()) {
      op.flop();
    }
    if (rotation.getDegrees() != 0) {
      op.rotate(rotation.getDegrees().doubleValue());
    }

    // quality transformation
    Quality quality = params.getQuality();
    if (quality != Quality.COLOR && quality != Quality.DEFAULT) {
      switch (quality) {
        case GRAY:
          op.colorspace("Gray");
          break;
        case BITONAL:
          op.monochrome();
          break;
      }
    }
  }