# Fluent Builder

The `BoxImage` class provides a fluent, chainable API for image manipulation in BoxLang. All methods return the `BoxImage` instance, allowing you to chain multiple operations together in a single expression.

## Creating Images

### ImageNew()

Create a new image from various sources:

```js
// From file path
img = ImageNew("images/photo.jpg");

// From URL
img = ImageNew("https://example.com/image.png");

// From base64 string
img = ImageReadBase64(base64String);

// Blank canvas
img = ImageNew(800, 600);
img = ImageNew(800, 600, "rgb");
img = ImageNew(800, 600, "rgb", "white");
```

## Transformations

### resize(width, height, \[interpolation], \[blurFactor])

Resize the image to specific dimensions.

```js
img.resize(800, 600);
img.resize(400, 300, "bicubic");
img.resize(1200, 800, "highestQuality", 1);
```

**Interpolation methods:** `nearest`, `bilinear`, `bicubic`, `highestPerformance`, `highestQuality`

### scaleToFit(size, \[interpolation])

Scale image proportionally to fit within a bounding box.

```js
// Single size - fits within size x size box
img.scaleToFit(400);
img.scaleToFit(800, "bicubic");

// Width and height - fits within maxWidth x maxHeight box
img.scaleToFit(800, 600);
img.scaleToFit(1024, 768, "highestQuality");
```

### rotate(angle)

Rotate the image by degrees (clockwise).

```js
img.rotate(90);
img.rotate(45);
img.rotate(-30);
```

### crop(x, y, width, height)

Crop a rectangular region from the image.

```js
img.crop(50, 50, 200, 150);
```

### transpose(operation)

Flip or rotate the image in various ways.

```js
img.transpose("horizontal");  // Flip horizontally (mirror)
img.transpose("vertical");    // Flip vertically
img.transpose("diagonal");    // Flip along main diagonal (top-left to bottom-right)
img.transpose("antidiagonal"); // Flip along anti-diagonal (top-right to bottom-left)
img.transpose("90");          // Rotate 90° clockwise
img.transpose("180");         // Rotate 180°
img.transpose("270");         // Rotate 270° clockwise (90° counter-clockwise)
```

**Aliases:** `flip()` is an alias for `transpose()`

### translate(x, y)

Move the image content by offset.

```js
img.translate(100, 50);
```

### shear(amount, dimension)

Shear the image horizontally or vertically.

```js
img.shear(0.5, "horizontal");
img.shear(0.3, "vertical");
```

## Color Adjustments

### grayScale()

Convert the image to grayscale.

```js
img.grayScale();
```

### negative()

Invert the colors (create a negative).

```js
img.negative();
```

## Filters & Effects

### blur(\[radius])

Apply a blur effect.

```js
img.blur();       // Default blur
img.blur(5);      // Custom blur radius
```

### sharpen(gain)

Sharpen the image.

```js
img.sharpen(0.5);
img.sharpen(1.0);
```

### addBorder(thickness, color)

Add a solid border around the image.

```js
img.addBorder(5, "black");
img.addBorder(10, "#FF0000");
img.addBorder(3, "navy");
```

**Colors:** Accepts color names ("red", "blue", "black") or hex codes ("#FF0000")

## Compositing

### overlay(imageToOverlay, overlayRule, transparency)

Overlay another image on top of this one.

```js
overlay = ImageNew("watermark.png");
img.overlay(overlay, "normal", 0.5);
```

**Overlay rules:** `normal`, `add`, `subtract`, `difference`, `multiply`, `screen`, `overlay`, `hardlight`, `softlight`

### drawImage(image, x, y)

Draw another image onto this image at specific coordinates.

```js
logo = ImageNew("logo.png");
img.drawImage(logo, 10, 10);
```

## Drawing Operations

### Drawing Setup

Before drawing, configure colors, stroke, and transparency:

```js
// Set drawing color for shapes and lines
img.setDrawingColor("red");
img.setDrawingColor("#0000FF");

// Set background color
img.setBackgroundColor("white");

// Set drawing transparency (0.0 = transparent, 1.0 = opaque)
img.setDrawingTransparency(0.7);

// Enable/disable anti-aliasing for smoother edges
img.setAntiAliasing(true);

// Configure stroke (line style)
img.setDrawingStroke({
    width: 3,
    endCaps: "round",
    lineJoins: "miter",
    miterLimit: 10,
    dashArray: [5, 3],
    dashPhase: 0
});
```

**Stroke Attributes:**

* `width` (numeric): Line thickness in pixels (default: 1)
* `endCaps` (string): Line end style - "butt", "round", "square" (default: "square")
* `lineJoins` (string): Corner style - "miter", "round", "bevel" (default: "miter")
* `miterLimit` (numeric): Limit for miter joins (default: 10)
* `dashArray` (array): Dash pattern \[dash, gap, dash, gap...] (default: solid line)
* `dashPhase` (numeric): Offset for dash pattern (default: 0)

### Shape Drawing

#### drawRect(x, y, width, height, \[filled])

Draw a rectangle.

```js
img.drawRect(50, 50, 200, 100);          // Outline
img.drawRect(50, 50, 200, 100, true);    // Filled
img.fillRect(50, 50, 200, 100);          // Filled (convenience method)
```

#### drawRoundRect(x, y, width, height, arcWidth, arcHeight, \[filled])

Draw a rounded rectangle.

```js
img.drawRoundRect(50, 50, 200, 100, 20, 20);
img.drawRoundRect(50, 50, 200, 100, 20, 20, true);
```

#### drawOval(x, y, width, height, \[filled])

Draw an oval/ellipse.

```js
img.drawOval(100, 100, 150, 100);
img.drawOval(100, 100, 150, 100, true);
```

#### drawBeveledRect(x, y, width, height, raised, \[filled])

Draw a 3D beveled rectangle.

```js
img.drawBeveledRect(50, 50, 200, 100, true);         // Raised
img.drawBeveledRect(50, 50, 200, 100, false, true);  // Lowered, filled
```

#### drawArc(x, y, width, height, startAngle, arcAngle, \[filled])

Draw an arc or pie slice.

```js
img.drawArc(100, 100, 200, 200, 0, 90);        // Quarter circle outline
img.drawArc(100, 100, 200, 200, 45, 180, true); // Pie slice filled
```

### Line Drawing

#### drawLine(x1, y1, x2, y2)

Draw a straight line.

```js
img.drawLine(0, 0, 100, 100);
```

#### drawLines(xCoords, yCoords, isPolygon, \[filled])

Draw connected lines or polygons.

```js
// Polyline
img.drawLines([10, 50, 90], [10, 50, 10], false);

// Polygon (auto-closes)
img.drawLines([50, 150, 100], [50, 150, 100], true);

// Filled polygon
img.drawLines([50, 150, 100], [50, 150, 100], true, true);
```

### Curve Drawing

#### drawCubicCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2)

Draw a cubic Bézier curve.

```js
img.drawCubicCurve(20, 20, 100, 200, 200, 100, 300, 300);
```

#### drawQuadraticCurve(ctrlx, ctrly, x1, y1, x2, y2)

Draw a quadratic Bézier curve.

```js
img.drawQuadraticCurve(150, 200, 50, 50, 250, 50);
```

### Text Drawing

#### drawText(text, x, y, \[fontConfig])

Draw text on the image.

```js
// Simple text
img.setDrawingColor("black")
   .drawText("Hello World", 100, 100);

// Styled text
img.drawText("Styled Text", 100, 200, {
    font: "Arial",
    size: 24,
    style: "bold",
    underline: true,
    strikethrough: false
});
```

**Font config attributes:**

* `font` (string): Font family name (default: system default)
* `size` (numeric): Font size in points (default: 12)
* `style` (string): "plain", "bold", "italic", "bolditalic" (default: "plain")
* `underline` (boolean): Underline text (default: false)
* `strikethrough` (boolean): Strikethrough text (default: false)

### Utility Drawing

#### clearRect(x, y, width, height)

Clear a rectangular region (makes it transparent).

```js
img.clearRect(50, 50, 100, 100);
```

## Drawing Axis Transformations

Apply transformations to the drawing coordinate system:

### rotateDrawingAxis(angle, x, y)

Rotate the drawing axis around a point.

```js
img.rotateDrawingAxis(45, 100, 100);
```

### translateDrawingAxis(x, y)

Translate (move) the drawing origin.

```js
img.translateDrawingAxis(50, 50);
```

### shearDrawingAxis(x, y)

Shear the drawing coordinate system.

```js
img.shearDrawingAxis(0.5, 0.5);
```

## Copying & Duplication

### copy()

Create a duplicate of the entire image.

```js
copy = img.copy();
```

### copy(x, y, width, height, dx, dy)

Copy a region within the image to another location.

```js
img.copy(50, 50, 100, 100, 200, 200);
```

## Writing Images

### write(\[path])

Write the image to disk.

```js
// Write to original source path (if loaded from file)
img.write();

// Write to specific path
img.write("output/processed.jpg");
img.write("output/converted.png");
```

**Notes:**

* Parent directories are automatically created
* Format is determined by file extension
* File handles are properly closed (no Windows locking issues)

## Information & Metadata

### getWidth() / getHeight()

Get image dimensions.

```js
width = img.getWidth();
height = img.getHeight();
```

### info()

Get comprehensive image information.

```js
info = img.info();
// Returns struct with: width, height, colormodel, source, transparency, EXIF, IPTC
```

### getExifMetadata() / getIPTCMetadata()

Get metadata as a struct.

```js
exif = img.getExifMetadata();
iptc = img.getIPTCMetadata();
```

### getExifTag(tag) / getIPTCTag(tag)

Get specific metadata tag value.

```js
camera = img.getExifTag("Model");
keywords = img.getIPTCTag("Keywords");
```

### getBlob()

Get the image as a byte array.

```js
bytes = img.getBlob();
```

### getBufferedImage()

Get the underlying Java BufferedImage object.

```js
bi = img.getBufferedImage();
```

## Complete Chaining Example

The fluent API allows complex image processing pipelines:

```js
result = ImageNew("photo.jpg")
    .scaleToFit(1200, 800, "bicubic")
    .crop(100, 100, 800, 600)
    .setAntiAliasing(true)
    .setDrawingColor("white")
    .setDrawingStroke({ width: 3, endCaps: "round" })
    .drawRect(10, 10, 780, 580)
    .setDrawingColor("black")
    .drawText("Copyright 2025", 20, 560, {
        font: "Arial",
        size: 16,
        style: "bold"
    })
    .sharpen(0.5)
    .write("output/processed.jpg");
```

## Working with Multiple Images

```js
// Load and process multiple images
base = ImageNew(800, 600, "rgb", "white");

logo = ImageNew("logo.png")
    .scaleToFit(100)
    .setDrawingTransparency(0.8);

watermark = ImageNew("watermark.png")
    .scaleToFit(200);

// Composite them
result = base
    .drawImage(logo, 10, 10)
    .overlay(watermark, "normal", 0.3)
    .write("output/composite.png");
```

## Important Notes

### File Handling

* Images loaded from files are immediately read into memory - no file locking issues
* Files can be deleted immediately after `ImageNew()` or `ImageRead()`
* `write()` automatically creates parent directories if they don't exist

### Lazy Loading

* Images are fully loaded upon creation - no lazy loading issues
* Safe to use immediately after `ImageNew()` without calling `info()` first

### Color Format

* Colors accept both names ("red", "blue", "navy") and hex codes ("#FF0000", "#0000FF")
* See `BoxImage.COLORS` map for supported color names

### Method Chaining

* All transformation and drawing methods return `BoxImage` for chaining
* Getters (info, getWidth, getBlob, etc.) return their respective types and break the chain

### Metadata

* EXIF and IPTC metadata extracted automatically when loading from files
* Metadata is preserved when copying images
* Use `info()` to access all metadata in a single struct

## Related Documentation

* [Built-In Functions](https://github.com/ortus-boxlang/boxlang-docs/blob/v1.x/docs/reference/built-in-functions/README.md) - Individual BIF documentation
* [Image Component](https://github.com/ortus-boxlang/boxlang-docs/blob/v1.x/docs/reference/components/image.md) - Tag-based approach
* [readme.md](/readme.md) - Module overview and quick start


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://boxlang.ortusbooks.com/boxlang-framework/modularity/image-manipulation/reference/fluent-builder.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
