diff --git a/README.md b/README.md index 08da5b85..b9c18e09 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ ## Key Features -- **50 image tools** - Resize, crop, compress, convert, watermark, color adjust, beautify screenshots, vectorize, create GIFs, find duplicates, generate passport photos, and more. Supports 55+ input formats (including 23 camera RAW formats) and 14 output formats +- **51 image tools** - Resize, crop, compress, convert, watermark, color adjust, beautify screenshots, generate memes, vectorize, create GIFs, find duplicates, generate passport photos, and more. Supports 55+ input formats (including 23 camera RAW formats) and 14 output formats - **Local AI** - Remove backgrounds, upscale images, restore and colorize old photos, erase objects, blur faces, enhance faces, extract text (OCR). All on your hardware - no internet required - **Pipelines** - Chain tools into reusable workflows with unlimited steps. Batch process unlimited images at once - **REST API** - Every tool available via API with API key auth. Interactive docs at `/api/docs` diff --git a/apps/api/src/openapi.yaml b/apps/api/src/openapi.yaml index bd856bdc..aad5995e 100644 --- a/apps/api/src/openapi.yaml +++ b/apps/api/src/openapi.yaml @@ -1,9 +1,9 @@ openapi: 3.1.0 info: title: SnapOtter API - version: 1.15.9 + version: 1.16.0 description: | - REST API for SnapOtter, a self-hosted image processing platform with 50 tools. + REST API for SnapOtter, a self-hosted image processing platform with 51 tools. ## Authentication @@ -685,12 +685,10 @@ paths: post: tags: [Tools] summary: Color adjustments - description: | + description: > Consolidated color adjustment tool. Adjusts brightness, contrast, exposure, saturation, temperature, tint, hue, sharpness, color channels, and effects - in a single pass. This is the primary color adjustment endpoint; the - brightness-contrast, saturation, color-channels, and color-effects endpoints - are aliases that accept the same settings schema. + in a single pass. security: - bearerAuth: [] requestBody: @@ -741,226 +739,6 @@ paths: schema: $ref: "#/components/schemas/UnauthorizedError" - /api/v1/tools/brightness-contrast: - post: - tags: [Tools] - summary: Brightness and contrast - description: Adjust brightness, contrast, saturation, color channels, and effects. Alias for adjust-colors. - security: - - bearerAuth: [] - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - required: [file] - properties: - file: - type: string - format: binary - description: Image file to process - settings: - type: string - description: | - JSON string with options: - - `brightness` (number -100 to 100, default 0) — Brightness adjustment - - `contrast` (number -100 to 100, default 0) — Contrast adjustment - - `saturation` (number -100 to 100, default 0) — Saturation adjustment - - `exposure` (number -100 to 100, default 0) — Exposure adjustment - - `temperature` (number -100 to 100, default 0) — Color temperature - - `tint` (number -100 to 100, default 0) — Tint adjustment - - `hue` (number -180 to 180, default 0) — Hue rotation - - `sharpness` (number 0 to 100, default 0) — Sharpness - - `red` (number 0-200, default 100) — Red channel multiplier - - `green` (number 0-200, default 100) — Green channel multiplier - - `blue` (number 0-200, default 100) — Blue channel multiplier - - `effect` (string, default "none") — One of: none, grayscale, sepia, invert - responses: - "200": - description: Processed image - content: - application/json: - schema: - $ref: "#/components/schemas/ToolResponse" - "400": - description: Invalid input - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/UnauthorizedError" - - /api/v1/tools/saturation: - post: - tags: [Tools] - summary: Saturation and exposure - description: Adjust color saturation and exposure settings. - security: - - bearerAuth: [] - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - required: [file] - properties: - file: - type: string - format: binary - description: Image file to process - settings: - type: string - description: | - JSON string with options: - - `brightness` (number -100 to 100, default 0) — Brightness adjustment - - `contrast` (number -100 to 100, default 0) — Contrast adjustment - - `saturation` (number -100 to 100, default 0) — Saturation adjustment - - `exposure` (number -100 to 100, default 0) — Exposure adjustment - - `temperature` (number -100 to 100, default 0) — Color temperature - - `tint` (number -100 to 100, default 0) — Tint adjustment - - `hue` (number -180 to 180, default 0) — Hue rotation - - `sharpness` (number 0 to 100, default 0) — Sharpness - - `red` (number 0-200, default 100) — Red channel multiplier - - `green` (number 0-200, default 100) — Green channel multiplier - - `blue` (number 0-200, default 100) — Blue channel multiplier - - `effect` (string, default "none") — One of: none, grayscale, sepia, invert - responses: - "200": - description: Processed image - content: - application/json: - schema: - $ref: "#/components/schemas/ToolResponse" - "400": - description: Invalid input - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/UnauthorizedError" - - /api/v1/tools/color-channels: - post: - tags: [Tools] - summary: Color channels - description: Adjust individual RGB color channels. - security: - - bearerAuth: [] - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - required: [file] - properties: - file: - type: string - format: binary - description: Image file to process - settings: - type: string - description: | - JSON string with options: - - `brightness` (number -100 to 100, default 0) — Brightness adjustment - - `contrast` (number -100 to 100, default 0) — Contrast adjustment - - `saturation` (number -100 to 100, default 0) — Saturation adjustment - - `exposure` (number -100 to 100, default 0) — Exposure adjustment - - `temperature` (number -100 to 100, default 0) — Color temperature - - `tint` (number -100 to 100, default 0) — Tint adjustment - - `hue` (number -180 to 180, default 0) — Hue rotation - - `sharpness` (number 0 to 100, default 0) — Sharpness - - `red` (number 0-200, default 100) — Red channel multiplier - - `green` (number 0-200, default 100) — Green channel multiplier - - `blue` (number 0-200, default 100) — Blue channel multiplier - - `effect` (string, default "none") — One of: none, grayscale, sepia, invert - responses: - "200": - description: Processed image - content: - application/json: - schema: - $ref: "#/components/schemas/ToolResponse" - "400": - description: Invalid input - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/UnauthorizedError" - - /api/v1/tools/color-effects: - post: - tags: [Tools] - summary: Color effects - description: Apply color effects like grayscale, sepia, or invert. - security: - - bearerAuth: [] - requestBody: - required: true - content: - multipart/form-data: - schema: - type: object - required: [file] - properties: - file: - type: string - format: binary - description: Image file to process - settings: - type: string - description: | - JSON string with options: - - `brightness` (number -100 to 100, default 0) — Brightness adjustment - - `contrast` (number -100 to 100, default 0) — Contrast adjustment - - `saturation` (number -100 to 100, default 0) — Saturation adjustment - - `exposure` (number -100 to 100, default 0) — Exposure adjustment - - `temperature` (number -100 to 100, default 0) — Color temperature - - `tint` (number -100 to 100, default 0) — Tint adjustment - - `hue` (number -180 to 180, default 0) — Hue rotation - - `sharpness` (number 0 to 100, default 0) — Sharpness - - `red` (number 0-200, default 100) — Red channel multiplier - - `green` (number 0-200, default 100) — Green channel multiplier - - `blue` (number 0-200, default 100) — Blue channel multiplier - - `effect` (string, default "none") — One of: none, grayscale, sepia, invert - responses: - "200": - description: Processed image - content: - application/json: - schema: - $ref: "#/components/schemas/ToolResponse" - "400": - description: Invalid input - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/UnauthorizedError" - /api/v1/tools/sharpening: post: tags: [Tools] @@ -2958,6 +2736,189 @@ paths: schema: $ref: "#/components/schemas/UnauthorizedError" + /api/v1/tools/meme-generator: + post: + tags: [Tools] + summary: Meme generator + description: > + Create memes using templates or custom images. Supports two modes: + (1) Template mode - send JSON body with `templateId` and `textBoxes`. + (2) Custom image mode - send multipart with `file` and `settings`. + security: + - bearerAuth: [] + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + description: Custom image file (optional if using templateId) + settings: + type: string + description: | + JSON string with options: + - `templateId` (string, optional) - ID of a meme template from /api/v1/meme-templates + - `textLayout` (string, default "top-bottom") - One of: top-bottom, top-only, bottom-only, center, side-by-side + - `textBoxes` (array of {id, text}) - Text content for each position + - `fontFamily` (string, default "anton") - One of: anton, arial-black, comic-sans, montserrat, bebas-neue, permanent-marker, roboto + - `fontSize` (number 8-200, optional) - Font size in pixels + - `textColor` (hex string, default "#ffffff") - Text color + - `strokeColor` (hex string, default "#000000") - Text outline color + - `textAlign` (string, default "center") - One of: left, center, right + - `allCaps` (boolean, default true) - Convert text to uppercase + application/json: + schema: + type: object + description: Template mode - send templateId and textBoxes as JSON body + properties: + templateId: + type: string + description: ID of a meme template + textBoxes: + type: array + items: + type: object + properties: + id: + type: string + text: + type: string + responses: + "200": + description: Processed meme image + content: + application/json: + schema: + $ref: "#/components/schemas/ToolResponse" + "400": + description: Invalid input or template not found + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "401": + description: Authentication required + content: + application/json: + schema: + $ref: "#/components/schemas/UnauthorizedError" + "422": + description: Processing failed + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + + /api/v1/meme-templates: + get: + tags: [Tools] + summary: List meme templates + description: Returns the full manifest of available meme templates including text box positions. + security: + - bearerAuth: [] + responses: + "200": + description: Meme template manifest + content: + application/json: + schema: + type: object + properties: + templates: + type: array + items: + type: object + properties: + id: + type: string + filename: + type: string + width: + type: integer + height: + type: integer + textBoxes: + type: array + items: + type: object + properties: + id: + type: string + x: + type: number + y: + type: number + width: + type: number + height: + type: number + defaultText: + type: string + "401": + description: Authentication required + content: + application/json: + schema: + $ref: "#/components/schemas/UnauthorizedError" + + /api/v1/meme-templates/full/{filename}: + get: + tags: [Tools] + summary: Get meme template image + description: Serve a full-size meme template image. + security: + - bearerAuth: [] + parameters: + - name: filename + in: path + required: true + schema: + type: string + description: Template image filename + responses: + "200": + description: Template image + content: + image/*: + schema: + type: string + format: binary + "400": + description: Invalid filename + "404": + description: Template not found + + /api/v1/meme-templates/thumbs/{filename}: + get: + tags: [Tools] + summary: Get meme template thumbnail + description: Serve a thumbnail of a meme template. + security: + - bearerAuth: [] + parameters: + - name: filename + in: path + required: true + schema: + type: string + description: Template thumbnail filename + responses: + "200": + description: Thumbnail image + content: + image/*: + schema: + type: string + format: binary + "400": + description: Invalid filename + "404": + description: Thumbnail not found + /api/v1/tools/compare: post: tags: [Tools] diff --git a/apps/docs/api/rest.md b/apps/docs/api/rest.md index 3fa40cbe..f10bfbb9 100644 --- a/apps/docs/api/rest.md +++ b/apps/docs/api/rest.md @@ -163,6 +163,7 @@ All AI tools run on your hardware (CPU or NVIDIA GPU). No internet required. | `watermark-image` | Image Watermark | `opacity`, `position`, `scale` - second file is the watermark | | `text-overlay` | Text Overlay | `text`, `font`, `fontSize`, `color`, `x`, `y`, `background`, `padding`, `borderRadius` | | `compose` | Image Composition | `x`, `y`, `opacity`, `blend` - second file is layered on top | +| `meme-generator` | Meme Generator | `templateId`, `textLayout` (top-bottom/top-only/bottom-only/center/side-by-side), `textBoxes` ([{id, text}]), `fontFamily` (anton/arial-black/comic-sans/montserrat/bebas-neue/permanent-marker/roboto), `fontSize`, `textColor`, `strokeColor`, `textAlign`, `allCaps`. Supports template mode (JSON body with `templateId`) or custom image mode (multipart with file). | ### Utilities @@ -375,6 +376,17 @@ Manage AI feature bundles (install/uninstall AI model packages in the Docker env | `POST` | `/api/v1/admin/features/:bundleId/uninstall` | Admin (`features:manage`) | Uninstall a feature bundle and clean up model files | | `GET` | `/api/v1/admin/features/disk-usage` | Admin (`features:manage`) | Get total disk usage of AI models | +## Meme Templates + +Supporting API for the meme generator tool. + +| Method | Path | Access | Description | +|--------|------|--------|-------------| +| `GET` | `/api/v1/meme-templates` | Auth | List all available meme templates with text box positions | +| `GET` | `/api/v1/meme-templates/full/:filename` | Auth | Serve full-size template image | +| `GET` | `/api/v1/meme-templates/thumbs/:filename` | Auth | Serve template thumbnail | +| `GET` | `/api/v1/meme-templates/fonts/:filename` | Auth | Serve font file used for meme text rendering | + ## Error Responses All errors return JSON: