Skip to content

Commit bc2da35

Browse files
committed
feat: add border and sharpen transformations to image processing schema with validation and integration
1 parent d7fdd83 commit bc2da35

File tree

1 file changed

+251
-5
lines changed
  • packages/imagekit-editor-dev/src/schema

1 file changed

+251
-5
lines changed

packages/imagekit-editor-dev/src/schema/index.ts

Lines changed: 251 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,70 @@ export const transformationSchema: TransformationSchema[] = [
15751575
},
15761576
],
15771577
},
1578+
{
1579+
key: "adjust-border",
1580+
name: "Border",
1581+
description:
1582+
"Add a border to the image. Specify a border width and color.",
1583+
docsLink: "https://imagekit.io/docs/effects-and-enhancements#border---b",
1584+
defaultTransformation: {},
1585+
schema: z
1586+
.object({
1587+
borderWidth: z.coerce
1588+
.number({
1589+
invalid_type_error: "Should be a number.",
1590+
})
1591+
.int()
1592+
.min(1)
1593+
.optional(),
1594+
borderColor: colorValidator
1595+
})
1596+
.refine(
1597+
(val) => {
1598+
if (
1599+
Object.values(val).some((v) => v !== undefined && v !== null)
1600+
) {
1601+
return true
1602+
}
1603+
return false
1604+
},
1605+
{
1606+
message: "Border width and color are required",
1607+
path: [],
1608+
},
1609+
),
1610+
transformations: [
1611+
{
1612+
label: "Border Width",
1613+
name: "borderWidth",
1614+
fieldType: "input",
1615+
isTransformation: false,
1616+
transformationGroup: "border",
1617+
helpText:
1618+
"Enter a border width",
1619+
fieldProps: {
1620+
defaultValue: 1,
1621+
min: 1,
1622+
max: 99,
1623+
step: 1,
1624+
},
1625+
},
1626+
{
1627+
label: "Border Color",
1628+
name: "borderColor",
1629+
fieldType: "color-picker",
1630+
isTransformation: false,
1631+
transformationGroup: "border",
1632+
helpText:
1633+
"Select the color of the border.",
1634+
fieldProps:{
1635+
hideOpacity: true,
1636+
showHexAlpha: false,
1637+
defaultValue: "#000000",
1638+
},
1639+
},
1640+
],
1641+
},
15781642
{
15791643
key: "adjust-trim",
15801644
name: "Trim",
@@ -1713,21 +1777,87 @@ export const transformationSchema: TransformationSchema[] = [
17131777
transformationGroup: "colorReplace",
17141778
helpText:
17151779
"Select the source color you want to replace (optional - if not specified, dominant color will be replaced).",
1780+
},
1781+
],
1782+
},
1783+
{
1784+
key: "adjust-sharpen",
1785+
name: "Sharpen",
1786+
description:
1787+
"Sharpen the image to highlight the edges and finer details within an image.",
1788+
docsLink: "https://imagekit.io/docs/effects-and-enhancements#sharpen---e-sharpen",
1789+
defaultTransformation: {},
1790+
schema: z
1791+
.object({
1792+
sharpenEnabled: z.coerce
1793+
.boolean({
1794+
invalid_type_error: "Should be a boolean.",
1795+
})
1796+
.optional(),
1797+
sharpen:
1798+
z.union([
1799+
z.literal("auto"),
1800+
z.coerce
1801+
.number({
1802+
invalid_type_error: "Should be a number.",
1803+
})
1804+
.int()
1805+
.min(1)
1806+
.max(99)
1807+
])
1808+
.optional(),
1809+
})
1810+
.refine(
1811+
(val) => {
1812+
if (
1813+
Object.values(val).some((v) => v !== undefined && v !== null)
1814+
) {
1815+
return true
1816+
}
1817+
return false
1818+
},
1819+
{
1820+
message: "At least one value is required",
1821+
path: [],
1822+
},
1823+
),
1824+
transformations: [
1825+
{
1826+
label: "Sharpen Image",
1827+
name: "sharpenEnabled",
1828+
fieldType: "switch",
1829+
isTransformation: false,
1830+
transformationGroup: "sharpen",
1831+
helpText:
1832+
"Toggle to sharpen the image to highlight the edges and finer details within an image.",
1833+
},
1834+
{
1835+
label: "Threshold",
1836+
name: "sharpen",
1837+
fieldType: "slider",
1838+
isTransformation: false,
1839+
transformationGroup: "sharpen",
1840+
helpText:
1841+
"Sharpen the image to highlight the edges and finer details within an image. Use a threshold between 1 and 99.",
1842+
fieldProps: {
1843+
autoOption: true,
1844+
defaultValue: "auto",
1845+
min: 1,
1846+
max: 99,
1847+
step: 1,
1848+
},
1849+
isVisible: ({ sharpenEnabled }) => sharpenEnabled === true,
17161850
},
1717-
1718-
17191851
],
17201852
},
17211853
],
17221854
},
17231855
{
17241856
key: "ai",
17251857
name: "AI Transformations",
1726-
items: [
1727-
{
1858+
items: [ {
17281859
key: "ai-removedotbg",
17291860
name: "Remove Background using Remove.bg",
1730-
// This option removes the background using the third-party remove.bg service.
17311861
description:
17321862
"Remove the background of the image using Remove.bg (external service). This isolates the subject and makes the background transparent.",
17331863
docsLink:
@@ -2589,6 +2719,29 @@ export const transformationSchema: TransformationSchema[] = [
25892719
invalid_type_error: "Should be a number.",
25902720
})
25912721
.optional(),
2722+
borderWidth: z.coerce
2723+
.number({
2724+
invalid_type_error: "Should be a number.",
2725+
})
2726+
.optional(),
2727+
borderColor: colorValidator.optional(),
2728+
sharpenEnabled: z.coerce
2729+
.boolean({
2730+
invalid_type_error: "Should be a boolean.",
2731+
})
2732+
.optional(),
2733+
sharpen: z
2734+
.union([
2735+
z.literal("auto"),
2736+
z.coerce
2737+
.number({
2738+
invalid_type_error: "Should be a number.",
2739+
})
2740+
.int()
2741+
.min(1)
2742+
.max(99),
2743+
])
2744+
.optional(),
25922745
})
25932746
.refine(
25942747
(val) => {
@@ -2789,6 +2942,66 @@ export const transformationSchema: TransformationSchema[] = [
27892942
defaultValue: "0",
27902943
},
27912944
},
2945+
{
2946+
label: "Border Width",
2947+
name: "borderWidth",
2948+
fieldType: "input",
2949+
isTransformation: false,
2950+
transformationKey: "borderWidth",
2951+
transformationGroup: "imageLayer",
2952+
fieldProps: {
2953+
defaultValue: 0,
2954+
},
2955+
helpText:
2956+
"Enter the width of the border of the overlay image.",
2957+
},
2958+
{
2959+
label: "Border Color",
2960+
name: "borderColor",
2961+
fieldType: "color-picker",
2962+
isTransformation: false,
2963+
transformationKey: "borderColor",
2964+
transformationGroup: "imageLayer",
2965+
isVisible: ({ borderWidth }) => borderWidth as number > 0,
2966+
helpText:
2967+
"Select the color of the border of the overlay image.",
2968+
fieldProps: {
2969+
hideOpacity: true,
2970+
showHexAlpha: false,
2971+
defaultValue: "#000000",
2972+
},
2973+
},
2974+
{
2975+
label: "Sharpen Overlay",
2976+
name: "sharpenEnabled",
2977+
fieldType: "switch",
2978+
isTransformation: true,
2979+
transformationKey: "sharpenEnabled",
2980+
transformationGroup: "imageLayer",
2981+
helpText:
2982+
"Toggle to sharpen the overlay image to highlight edges and fine details.",
2983+
fieldProps: {
2984+
defaultValue: false,
2985+
},
2986+
},
2987+
{
2988+
label: "Sharpen Threshold",
2989+
name: "sharpen",
2990+
fieldType: "slider",
2991+
isTransformation: true,
2992+
transformationKey: "sharpen",
2993+
transformationGroup: "imageLayer",
2994+
helpText:
2995+
"Sharpen the overlay image. Use a threshold between 1 and 99 (or auto).",
2996+
fieldProps: {
2997+
autoOption: true,
2998+
defaultValue: "auto",
2999+
min: 1,
3000+
max: 99,
3001+
step: 1,
3002+
},
3003+
isVisible: ({ sharpenEnabled }) => sharpenEnabled === true,
3004+
}
27923005
],
27933006
},
27943007
],
@@ -3170,6 +3383,18 @@ export const transformationFormatters: Record<
31703383
overlayTransform.blur = values.blur
31713384
}
31723385

3386+
// Sharpen overlay (same semantics as base-image sharpen: auto => empty string)
3387+
if (values.sharpenEnabled === true) {
3388+
if (values.sharpen === "auto") {
3389+
overlayTransform.sharpen = ""
3390+
} else if (typeof values.sharpen === "number") {
3391+
overlayTransform.sharpen = values.sharpen
3392+
}
3393+
}
3394+
if ((values.borderWidth && typeof values.borderWidth === "number" && values.borderWidth > 0) && (values.borderColor && typeof values.borderColor === "string")) {
3395+
overlayTransform.b = `${values.borderWidth}_${values.borderColor.replace(/^#/, "")}`
3396+
}
3397+
31733398
if (Object.keys(overlayTransform).length > 0) {
31743399
overlay.transformation = [overlayTransform]
31753400
}
@@ -3265,4 +3490,25 @@ export const transformationFormatters: Record<
32653490

32663491
transforms.cr = params.join("_")
32673492
},
3493+
border: (values, transforms) => {
3494+
const { borderWidth, borderColor } = values as {
3495+
borderWidth?: number
3496+
borderColor?: string
3497+
}
3498+
if(!borderWidth || !borderColor) return
3499+
const cleanBorderColor = borderColor.replace(/^#/, "")
3500+
transforms.b = `${borderWidth}_${cleanBorderColor}`
3501+
},
3502+
sharpen: (values, transforms) => {
3503+
const { sharpenEnabled, sharpen } = values as {
3504+
sharpenEnabled?: boolean
3505+
sharpen?: "auto" | number
3506+
}
3507+
if(!sharpenEnabled) return
3508+
if(sharpen === "auto") {
3509+
transforms.sharpen = ""
3510+
} else {
3511+
transforms.sharpen = sharpen
3512+
}
3513+
},
32683514
}

0 commit comments

Comments
 (0)