Klip is a Kotlin-based image and canvas processing server that dynamically transforms images stored in AWS S3. Powered by GraphicsMagick, it delivers fast, scalable, and customizable image manipulation through HTTP GET requests.
- Image Transformations – Resize, crop, rotate, grayscale, blur, sharpen, and more.
- Canvas Generation – Create custom canvases with gradients, patterns, text overlays, borders, and rounded corners.
- Flexible Rules Engine – Enforce size, quality, and filter constraints with configurable rules for enhanced security and optimization.
- Caching Support – Seamlessly caches transformed images to reduce processing overhead and improve performance.
- AWS S3 Integration – Pulls source images directly from S3 and supports caching to a separate bucket.
- Admin APIs – Monitor performance and track cache statistics with secure, API-key-protected admin endpoints.
- Highly Configurable – Customize behavior using environment variables for features, limits, and resource constraints.
/klip
– Transform existing images stored in AWS S3./canvas
– Generate custom graphics and placeholders with flexible styling options.
GET /klip/{path/to/image}
Fetch the original image stored in the S3 bucket without any transformations.
Example:
GET http://localhost:8080/klip/properties/1/04c08449e126.png
GET /klip/{path/to/image}?w={width}&h={height}
# Set width and height independently.
GET /klip/{path/to/image}?w={width}
GET /klip/{path/to/image}?h={height}
# Dimension syntax
GET /klip/{path/to/image}?d={width}x{height}
Resize the image to the specified width and height.
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
width |
Int | Optional | - | Width of the output image |
height |
Int | Optional | - | Height of the output image |
Example:
GET http://localhost:8080/klip/properties/1/04c08449e126.png?d=640x480
GET http://localhost:8080/klip/properties/1/04c08449e126.png?w=640&h480
Control how the image fits within the specified dimensions.
GET /klip/{path/to/image}?w={width}&h={height}&fit={mode}
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
fit |
String | Optional | - | How the image should fit within dimensions. Values: contain , cover , fill |
Fit Modes Explained:
contain: Preserves aspect ratio while ensuring image fits within specified dimensions
GET /klip/photo.jpg?w=800&h=600&fit=contain
cover: Fills entire dimensions while preserving aspect ratio, cropping excess
GET /klip/photo.jpg?w=800&h=600&fit=cover
fill: Stretches or squishes image to exactly fit dimensions
GET /klip/photo.jpg?w=800&h=600&fit=fill
Default Behavior:
- With both width and height: Acts as fill
- With single dimension: Acts as contain
GET /klip/{path/to/image}?quality=75
Adjust the image quality for compression and size optimization. Useful for reducing image size without significant loss of visual fidelity.
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
quality |
Int | No | 100 | Adjusts image quality (1–100). Lower values reduce size but may lose detail. |
Supported Formats: JPEG, PNG, WebP (other formats may default to lossless encoding).
Examples:
# High Quality (Default)
GET http://localhost:8080/klip/properties/1/04c08449e126.png?quality=100
# Medium-High Quality
GET http://localhost:8080/klip/properties/102/05013ad4469e00a7aed9596bc37af74e.jpg?quality=75
# Medium Quality
GET http://localhost:8080/klip/properties/102/05013ad4469e00a7aed9596bc37af74e.jpg?quality=50
# Low Quality
GET http://localhost:8080/klip/properties/102/05013ad4469e00a7aed9596bc37af74e.jpg?quality=25
# Lower Quality
GET http://localhost:8080/klip/properties/102/05013ad4469e00a7aed9596bc37af74e.jpg?quality=10
# Combined with resizing
GET http://localhost:8080/klip/properties/102/05013ad4469e00a7aed9596bc37af74e.jpg?quality=10&w1301h781
High (100) (default) | Medium-High (75) | Medium (50) |
---|---|---|
991,091 bytes | 205,236 bytes | 132,963 bytes |
Low (25) | Lower (10) |
---|---|
83,156 bytes | 43,615 bytes |
GET /klip/{path/to/image}?crop?w={width}&h={height}
Crop the image from the center to the specified width and height.
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
crop |
Boolean | No | false | Crops the image to fit the size. |
Example:
GET http://localhost:8080/klip/properties/1/04c08449e126.png?crop&w=250&h=250
GET /klip/{path/to/image}?grayscale
Convert the image to grayscale while resizing to the specified dimensions.
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
grayscale |
Boolean | No | false | Applies a grayscale filter to the image. |
Example:
GET http://localhost:8080/klip/250x250/properties/1/04c08449e126.png?grayscale
GET /klip/{path/to/image}?flipH
Flip the image horizontally (left-to-right).
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
flipH |
Boolean | No | false | Flips the image horizontally (left-to-right). |
Example:
GET http://localhost:8080/klip/properties/1/04c08449e126.png?flipH
GET /klip/{path/to/image}?flipV
Flip the image vertically (top-to-bottom).
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
flipV |
Boolean | No | false | Flips the image vertically (top-to-bottom). |
Example - Flip vertically:
GET http://localhost:8080/klip/properties/1/04c08449e126.png?flipV
Example - Flip both horizontally and vertically:
GET http://localhost:8080/klip/properties/1/04c08449e126.png?flipH&flipV
GET /klip/{path/to/image}?rotate=45
Rotate the image by the specified degrees (clockwise).
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
rotate |
Float | No | 0 | Rotates the image by the specified angle. |
Example - Rotate image 45 degrees:
GET http://localhost:8080/klip/properties/1/04c08449e126.png?rotate=45
GET /klip/{path/to/image}?blur={radius}x{sigma}
GET /klip/{path/to/image}?blur={blur}
Apply a Gaussian blur to the image to soften details.
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
blur |
Int | No | 0 | Simple blur with a single integer, range: [1, 10] . |
blur |
String | No | 0 | Fine-tune Gaussian blur, format: {radius}x{sigma} . |
blur
format mappings:
Blur | Radius | Sigma | Description |
---|---|---|---|
1 | 1 | 0.5 | Very light blur |
2 | 2 | 1.0 | Light blur |
3 | 3 | 1.5 | Moderate blur |
4 | 4 | 2.0 | Strong blur |
5 | 5 | 2.5 | Very strong blur |
10 | 10 | 5.0 | Extreme blur (background effects) |
radius
: Defines the area of the blur effect (higher = wider blur).sigma
: Controls the strength of the blur (higher = softer edges).
Example - Mild blur:
GET http://localhost:8080/klip/properties/1/04c08449e126.png?blur=0x2
Example: Simple, heavy blur
GET http://localhost:8080/klip/properties/1/04c08449e126.png?blur=7
GET /klip/{path/to/image}?sharpen=2.0
Sharpen the image to enhance details and make edges clearer.
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
sharpen |
Float | No | 0 |
Applies sharpening in the format radiusxsigma . |
radius
: Defines the area of the blur effect (higher = wider blur).sigma
: Controls the strength of the blur (higher = softer edges).
Example - Mild blur:
GET http://localhost:8080/klip/properties/1/04c08449e126.png?sharpen=2.0
GET /klip/{path/to/image}?colors=16
Reduce the number of colors in the image to simplify or stylize it.
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
colors |
Int | No | 256 |
Reduces the image to the specified color count. |
Example - 10 colors:
GET http://localhost:8080/klip/properties/1/04c08449e126.png?colors=10
GET /klip/{path/to/image}?dither
Enable or disable dithering to improve color approximation when reducing colors.
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
dither |
Boolean | No | false | Enable dithering. |
Example - 10 colors:
GET http://localhost:8080/klip/properties/1/04c08449e126.png?dither
GET /klip/{path/to/image}?grayscale&crop&rotate=90
Apply multiple transformations in a single request.
Example:
GET http://localhost:8080/klip/properties/1/04c08449e126.png?w=250&h=250&grayscale&crop&rotate=90
GET /health
Check if the server is up and running.
Response:
{
"status": "UP"
}
GET /version
Get the current version of the Klip server.
Response:
1.0.0
Get detailed status information about Klip
GET /admin/status
with Authorization: ApiKey <YOUR_API_KEY>
Response:
{
"totalRequests": 504,
"cacheHits": 252,
"cacheHitRate": 0.5,
"pool": {
"maxConcurrent": 2,
"currentAvailable": 2,
"totalProcessed": 281,
"averageWaitMs": 20049
}
}
GET /canvas/{width}x{height}
Generate a placeholder image with custom dimensions, background color, and optional text overlay.
Query Parameters:
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
bgColor |
String | Optional | gray | Background color (name or hex code) |
textColor |
String | Optional | white | Text color (name or hex code) |
textSize |
Int | Optional | 20 | Font size for the text |
text |
String | Optional | - | Text to display on the canvas |
pattern |
String | Optional | - | Pattern type: "check", "grid", "stripe" |
patternSize |
Int | Optional | 20-40 | Size of pattern elements |
gradient |
String | Optional | - | Gradient spec: "blue,red" or "45,#ff0000,blue" |
font |
String | Optional | Arial | Font family for text |
textAlign |
String | Optional | center | Text alignment: "center", "north", "southwest" |
border |
Int | Optional | - | Border width in pixels |
borderColor |
String | Optional | - | Border color (name or hex code) |
radius |
Int | Optional | 0 | Corner radius for rounded corners |
grayscale |
Bool | Optional | false | Convert to grayscale |
quality |
Int | Optional | - | Output image quality (1-100) |
blur |
String | Optional | - | Blur effect: "2.5" or "2.5x1.2" |
sharpen |
Float | Optional | - | Sharpen effect intensity |
rotate |
Float | Optional | - | Rotation angle in degrees |
flipH |
Bool | Optional | false | Flip horizontally |
flipV |
Bool | Optional | false | Flip vertically |
Examples:
More Examples:
# Basic gray placeholder
GET /canvas/640x480
# Blue placeholder with text
GET /canvas/200x100?bgColor=blue&text=Hello
# Custom colors and font size
GET /canvas/400x300?bgColor=%23FF0000&textColor=white&text=Preview&textSize=30
# Using hex colors
GET /canvas/300x200?bgColor=%23336699&text=Loading
# More
GET /canvas/300x200?bg=blue&text=Hello
GET /canvas/300x200?gradient=45,blue,red&text=Gradient
GET /canvas/300x200?pattern=check&patternSize=30
GET /canvas/300x200?pattern=grid&patternSize=50&text=Grid
GET /canvas/300x200?bg=white&border=5&borderColor=black&radius=10
GET /canvas/300x200?text=Hello&font=Helvetica&align=north&grayscale=1
Klip allows you to configure transformation rules for image processing using either environment variables or a rules file. These rules enforce constraints on transformations, ensuring only allowed operations are applied.
Set rules using the KLIP_RULES
and KLIP_CANVAS_RULES
environment variable as a semicolon-separated string:
Example:
KLIP_RULES="+flipV;-flipH;dim 32x32 64x64 128x128;blur 1 2 3 4;quality 75 85 90;rotate 0 90 180"
KLIP_CANVAS_RULES="+flipV;-flipH;dim 32x32 64x64 128x128;rotate 0 90 180"
Alternatively, rules can be stored in a rules.txt file and referenced via the KLIP_RULES_FILE
environment variable.
Example:
KLIP_RULES_FILE=/app/config/rules.txt
KLIP_CANVAS_RULES_FILE=/app/config/canvas_rules.txt
+flipV
-flipH
dim 32x32 64x64 128x128
blur 1 2 3 4
quality 75 85 90
rotate 0 90 180
Rule | Description | Example |
---|---|---|
+flipV |
Allow vertical flipping. | +flipV |
-flipV |
Disallow vertical flipping. | -flipV |
+flipH |
Allow horizontal flipping. | +flipH |
-flipH |
Disallow horizontal flipping. | -flipH |
+grayscale |
Allow grayscale conversion. | +grayscale |
-grayscale |
Disallow grayscale conversion. | -grayscale |
dim {WxH} |
Allow specific dimensions (width x height). | dim 32x32 64x64 128x128 |
blur {values} |
Allow specific blur radii. | blur 1 2 3 4 |
quality {values} |
Allow specific quality settings. | quality 75 85 90 |
rotate {values} |
Allow specific rotation angles in degrees. | rotate 0 90 180 |
sharpen {values} |
Allow specific sharpen values. | sharpen 0.5 1.0 2.0 |
colors {values} |
Allow specific color palette sizes. | colors 16 32 64 128 |
fit {values} |
Allow specific fit values . | fit cover contain |
Environment Variable Example:
docker run -e KLIP_RULES="+flipV;-flipH;dim 32x32 64x64 128x128" klip-app
File Example:
docker run -e KLIP_RULES_FILE=/config/rules.txt -v /local/config:/config klip-app
To test rules without deployment:
Create a rules.txt file:
+flipV
-flipH
dim 32x32 64x64 128x128
blur 1 2 3 4
quality 75 85 90
rotate 0 90 180
Use the following shell script:
KLIP_RULES_FILE=./klip_rules.txt ./gradlew run
Alternatively, set directly as an environment variable:
KLIP_RULES="+flipV;-flipH;dim 32x32 64x64 128x128" ./gradlew run
GET /klip/properties/1/04c08449e1261fedc2eb1a6a99245531.png?w=10&h=9
GET /klip/properties/1/04c08449e1261fedc2eb1a6a99245531.png?d=10x9
422 - Unprocessable Entity
{
"error": "Dimensions must be > 10. Got: 10x9"
}
- Java 21+
- Gradle
- GraphicsMagick
brew install graphicsmagick
./gradlew clean build
Section | Variable | Type | Default | Required | Description |
---|---|---|---|---|---|
Features | KLIP_ENABLED |
Boolean | true |
No | Enable/disable the /klip/ endpoint for image transformations. |
Features | KLIP_CANVAS_ENABLED |
Boolean | true |
No | Enable/disable the /canvas/ endpoint for image generation. |
Features | KLIP_ADMIN_ENABLED |
Boolean | false |
No | Enable/disable the admin endpoints. |
Security | KLIP_ADMIN_API_KEY |
String | - | Yes* | API key required for admin endpoints when admin is enabled. |
LOG | KLIP_LOG_LEVEL |
Enum | INFO |
No | TRACE , INFO , DEBUG , WARN , ERROR |
HTTP | KLIP_HTTP_PORT |
Int | 8080 |
No | The HTTP port the server listens on. |
AWS | KLIP_AWS_REGION |
String | - | Yes | AWS region for S3 bucket (e.g., us-west-2 ). |
AWS | KLIP_S3_BUCKET |
String | - | Yes | The S3 bucket name where source images are stored. |
Cache | KLIP_CACHE_ENABLED |
Boolean | True | No | If false, disable image cache. |
Cache | KLIP_CACHE_BUCKET |
String | Same as KLIP_S3_BUCKET |
No | Used if using different S3 bucket for caching. |
Cache | KLIP_CACHE_FOLDER |
String | _cache/ |
No | Prefix for cached files. Stored within the cache bucket. |
Rules | KLIP_RULES |
String | "" (empty) | No | Inline rule definitions separated by ; (e.g., +flipV;-flipH;dim 32x32 64x64). |
Rules | KLIP_RULES_FILE |
String | - | No | Path to a rules file with one rule per line. Overrides KLIP_RULES. |
GraphicsMagick | KLIP_GM_TIMEOUT_SECONDS |
Long | 30 |
No | Maximum time in seconds for a GraphicsMagick operation. |
GraphicsMagick | KLIP_GM_MEMORY_LIMIT |
String | 256MB |
No | Memory limit for GraphicsMagick operations. |
GraphicsMagick | KLIP_GM_MAP_LIMIT |
String | 512MB |
No | Memory map limit for GraphicsMagick operations. |
GraphicsMagick | KLIP_GM_DISK_LIMIT |
String | 1GB |
No | Disk space limit for GraphicsMagick operations. |
GraphicsMagick | KLIP_GM_POOL_SIZE |
Int | Available Processors | No | Maximum number of concurrent GraphicsMagick operations. |
KLIP_ENABLED=true \
KLIP_CANVAS_ENABLED=true \
KLIP_ADMIN_ENABLED=true \
KLIP_ADMIN_API_KEY="your.secret.key" \
KLIP_LOG_LEVEL=INFO \
KLIP_HTTP_PORT=8080 \
KLIP_AWS_REGION=us-west-2 \
KLIP_S3_BUCKET=cdn.klip.com \
KLIP_CACHE_ENABLED=true \
KLIP_CACHE_BUCKET=cdn.klip.com \
KLIP_CACHE_FOLDER=.cache/ \
KLIP_RULES="+flipV;-flipH;dim 32x32 64x64 256x256" \
KLIP_GM_TIMEOUT_SECONDS=30 \
KLIP_GM_MEMORY_LIMIT=256MB \
KLIP_GM_MAP_LIMIT=512MB \
KLIP_GM_DISK_LIMIT=1GB \
KLIP_GM_POOL_SIZE=4 \
java -jar build/libs/klip-all.jar
Default local endpoint: http://0.0.0.0:8080
./gradlew clean build
cp Dockerfile.template Dockerfile
Afterward set the ENV
variables as needed.
docker build --platform linux/amd64 -t klip-prod:latest .
docker tag klip-prod:latest <AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/klip-prod:latest
docker push <AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/klip-prod:latest
aws ecs update-service \
--cluster klip-prod-cluster \
--service klip-prod-service \
--force-new-deployment
aws logs tail /ecs/klip-prod --follow
ALB, ECS, Fargate, ECR
Note that you'll likely need to adjust this terraform to fit your project. This is meant as a starting point.
cd terraform/stacks/
cp prod-template prod
Make whatever edits you need to the terraform/variables.
cd terraform/stacks/prod/
terraform init
terraform apply
- Configurable Secret Key to protect admin endpoints (clear cache, get stats)
- Migrate to Kotlin Native after (aws s3 client is for kotlin jvm)
- Configurable backend storage (S3 vs File)