@uploadista/flow-images-photon 0.0.18-beta.8 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.cjs CHANGED
@@ -1 +1 @@
1
- const e=require(`./common-ChdjHan4.cjs`);let t=require(`@cf-wasm/photon/node`),n=require(`@uploadista/core/errors`),r=require(`@uploadista/core/flow`),i=require(`effect`);const a=e=>{let n=e.toRgb();return new t.Rgba(n.r,n.g,n.b,n.a)},o=(n,r,i,o)=>{let s=n.get_width(),c=n.get_height();if(!r&&!i)throw Error(`At least one of width or height is required`);if(r&&!i?i=Math.floor(r/s*c):i&&!r&&(r=Math.floor(i/c*s)),!r||!i)throw Error(`Invalid width or height`);if(r===s&&i===c)return n;let l=o?.fit||`cover`,u=e.t(l,s,c,r,i);n=(0,t.resize)(n,u.width,u.height,1);let[d,f]=[n.get_width(),n.get_height()];if(l===`contain`&&o?.fit_cover_letterbox_color){let e=Math.floor((r-d)/2),s=Math.floor((i-f)/2);s>0&&(n=(0,t.padding_top)(n,s,a(o.fit_cover_letterbox_color)),n=(0,t.padding_bottom)(n,s,a(o.fit_cover_letterbox_color))),e>0&&(n=(0,t.padding_left)(n,e,a(o.fit_cover_letterbox_color)),n=(0,t.padding_right)(n,e,a(o.fit_cover_letterbox_color)))}else if(l===`cover`){let e=Math.floor(d-r)/2,a=Math.floor(f-i)/2;n=(0,t.crop)(n,e,a,r+e,i+a)}return n},s=(e,t,n)=>{let r;switch(t){case`webp`:r=e.get_bytes_webp();break;case`jpeg`:r=e.get_bytes_jpeg(n?.jpeg_quality||100);break;case`png`:r=e.get_bytes();break;default:r=e.get_bytes_jpeg(n?.jpeg_quality||100)}return r},c=i.Layer.succeed(r.ImagePlugin,r.ImagePlugin.of({optimize:(e,{quality:n})=>{let r=t.PhotonImage.new_from_byteslice(e),a=r.get_bytes_jpeg(n);return r.free(),i.Effect.succeed(a)},resize:(e,{width:n,height:r,fit:a})=>{if(!n&&!r)throw Error(`Either width or height must be specified for resize`);let s=t.PhotonImage.new_from_byteslice(e),c=o(s,n??s.get_width(),r??s.get_height(),{fit:a}),l=c.get_bytes_webp();return s.free(),c.free(),i.Effect.succeed(l)},transform:(e,r)=>i.Effect.gen(function*(){if([`watermark`,`logo`,`text`].includes(r.type))return yield*i.Effect.fail(n.UploadistaError.fromCode(`UNKNOWN_ERROR`,{body:`Photon plugin does not support '${r.type}'. Use sharp plugin or remove this transformation.`}));let a=t.PhotonImage.new_from_byteslice(e);try{switch(r.type){case`resize`:a=o(a,r.width,r.height,{fit:r.fit});break;case`blur`:{let e=Math.round(r.sigma);(0,t.gaussian_blur)(a,e);break}case`rotate`:return yield*i.Effect.fail(n.UploadistaError.fromCode(`UNKNOWN_ERROR`,{body:`Rotate transformation is not fully supported in photon plugin. Use sharp plugin instead.`}));case`flip`:r.direction===`horizontal`?(0,t.fliph)(a):(0,t.flipv)(a);break;case`grayscale`:(0,t.grayscale)(a);break;case`sepia`:(0,t.sepia)(a);break;case`brightness`:{let e=Math.round(r.value*2.55);(0,t.adjust_brightness)(a,e);break}case`contrast`:{let e=r.value;(0,t.adjust_contrast)(a,e);break}case`sharpen`:(0,t.sharpen)(a);break;default:return yield*i.Effect.fail(n.UploadistaError.fromCode(`UNKNOWN_ERROR`,{body:`Unknown transformation type: ${r.type}`}))}return a.get_bytes_webp()}finally{a.free()}})}));exports.autoResize=o,exports.imagePluginNode=c,exports.imageToFormat=s,exports.tinyColorToPhotonRGBA=a;
1
+ const e=require(`./common-ChdjHan4.cjs`);let t=require(`@cf-wasm/photon/node`),n=require(`@uploadista/core/errors`),r=require(`@uploadista/core/flow`),i=require(`@uploadista/observability`),a=require(`effect`);const o=e=>{let n=e.toRgb();return new t.Rgba(n.r,n.g,n.b,n.a)},s=(n,r,i,a)=>{let s=n.get_width(),c=n.get_height();if(!r&&!i)throw Error(`At least one of width or height is required`);if(r&&!i?i=Math.floor(r/s*c):i&&!r&&(r=Math.floor(i/c*s)),!r||!i)throw Error(`Invalid width or height`);if(r===s&&i===c)return n;let l=a?.fit||`cover`,u=e.t(l,s,c,r,i);n=(0,t.resize)(n,u.width,u.height,1);let[d,f]=[n.get_width(),n.get_height()];if(l===`contain`&&a?.fit_cover_letterbox_color){let e=Math.floor((r-d)/2),s=Math.floor((i-f)/2);s>0&&(n=(0,t.padding_top)(n,s,o(a.fit_cover_letterbox_color)),n=(0,t.padding_bottom)(n,s,o(a.fit_cover_letterbox_color))),e>0&&(n=(0,t.padding_left)(n,e,o(a.fit_cover_letterbox_color)),n=(0,t.padding_right)(n,e,o(a.fit_cover_letterbox_color)))}else if(l===`cover`){let e=Math.floor(d-r)/2,a=Math.floor(f-i)/2;n=(0,t.crop)(n,e,a,r+e,i+a)}return n},c=(e,t,n)=>{let r;switch(t){case`webp`:r=e.get_bytes_webp();break;case`jpeg`:r=e.get_bytes_jpeg(n?.jpeg_quality||100);break;case`png`:r=e.get_bytes();break;default:r=e.get_bytes_jpeg(n?.jpeg_quality||100)}return r},l=a.Layer.succeed(r.ImagePlugin,r.ImagePlugin.of({optimize:(e,{quality:n})=>{let r=t.PhotonImage.new_from_byteslice(e),o=r.get_bytes_jpeg(n);return r.free(),a.Effect.succeed(o).pipe((0,i.withOperationSpan)(`image`,`optimize`,{"image.quality":n,"image.input_size":e.byteLength}))},resize:(e,{width:n,height:r,fit:o})=>{if(!n&&!r)throw Error(`Either width or height must be specified for resize`);let c=t.PhotonImage.new_from_byteslice(e),l=s(c,n??c.get_width(),r??c.get_height(),{fit:o}),u=l.get_bytes_webp();return c.free(),l.free(),a.Effect.succeed(u).pipe((0,i.withOperationSpan)(`image`,`resize`,{"image.width":n,"image.height":r,"image.fit":o,"image.input_size":e.byteLength}))},transform:(e,r)=>a.Effect.gen(function*(){if([`watermark`,`logo`,`text`].includes(r.type))return yield*a.Effect.fail(n.UploadistaError.fromCode(`UNKNOWN_ERROR`,{body:`Photon plugin does not support '${r.type}'. Use sharp plugin or remove this transformation.`}));let i=t.PhotonImage.new_from_byteslice(e);try{switch(r.type){case`resize`:i=s(i,r.width,r.height,{fit:r.fit});break;case`blur`:{let e=Math.round(r.sigma);(0,t.gaussian_blur)(i,e);break}case`rotate`:return yield*a.Effect.fail(n.UploadistaError.fromCode(`UNKNOWN_ERROR`,{body:`Rotate transformation is not fully supported in photon plugin. Use sharp plugin instead.`}));case`flip`:r.direction===`horizontal`?(0,t.fliph)(i):(0,t.flipv)(i);break;case`grayscale`:(0,t.grayscale)(i);break;case`sepia`:(0,t.sepia)(i);break;case`brightness`:{let e=Math.round(r.value*2.55);(0,t.adjust_brightness)(i,e);break}case`contrast`:{let e=r.value;(0,t.adjust_contrast)(i,e);break}case`sharpen`:(0,t.sharpen)(i);break;default:return yield*a.Effect.fail(n.UploadistaError.fromCode(`UNKNOWN_ERROR`,{body:`Unknown transformation type: ${r.type}`}))}return i.get_bytes_webp()}finally{i.free()}}).pipe((0,i.withOperationSpan)(`image`,`transform`,{"image.transformation_type":r.type,"image.input_size":e.byteLength}))}));exports.autoResize=s,exports.imagePluginNode=l,exports.imageToFormat=c,exports.tinyColorToPhotonRGBA=o;
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.cts","names":[],"sources":["../src/image-plugin-node.ts"],"sourcesContent":[],"mappings":";;;;;;cAwBa,+BAAgC,SAAA,CAAU,aAAQ;cAKlD,oBACJ,2DAAA;EANI,GAAA,CAAA,EAAA,SAAA,GAAA,OAGZ,GAAA,MAAA;EAEY,yBAmFZ,CAAA,EA7E+B,SAAA,CAAU,QA6EzC;CAlFQ,EAAA,GAMN,WANM;AAKuB,cA+EnB,aA/E6B,EAAA,CAAA,KAAA,EAgFjC,WAhFiC,EAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,KAAA,EAAA,OA6EzC,CA7EyC,EAAA;EACvC,YAAA,CAAA,EAAA,MAAA;CA4EF,EAAA,GAOE,UAPF,CAOE,eAPF,CAAA;AAEY,cA0BA,eAFZ,EAE2B,KAAA,CAAA,KAF3B,CAE2B,WAF3B,EAAA,KAAA,EAAA,KAAA,CAAA"}
1
+ {"version":3,"file":"node.d.cts","names":[],"sources":["../src/image-plugin-node.ts"],"sourcesContent":[],"mappings":";;;;;;cAyBa,+BAAgC,SAAA,CAAU,aAAQ;cAKlD,oBACJ,2DAAA;EANI,GAAA,CAAA,EAAA,SAAA,GAAA,OAGZ,GAAA,MAAA;EAEY,yBAmFZ,CAAA,EA7E+B,SAAA,CAAU,QA6EzC;CAlFQ,EAAA,GAMN,WANM;AAKuB,cA+EnB,aA/E6B,EAAA,CAAA,KAAA,EAgFjC,WAhFiC,EAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,KAAA,EAAA,OA6EzC,CA7EyC,EAAA;EACvC,YAAA,CAAA,EAAA,MAAA;CA4EF,EAAA,GAOE,UAPF,CAOE,eAPF,CAAA;AAEY,cA0BA,eAFZ,EAE2B,KAAA,CAAA,KAF3B,CAE2B,WAF3B,EAAA,KAAA,EAAA,KAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.mts","names":[],"sources":["../src/image-plugin-node.ts"],"sourcesContent":[],"mappings":";;;;;;cAwBa,+BAAgC,SAAA,CAAU,aAAQ;cAKlD,oBACJ,2DAAA;EANI,GAAA,CAAA,EAAA,SAAA,GAAA,OAGZ,GAAA,MAAA;EAEY,yBAmFZ,CAAA,EA7E+B,SAAA,CAAU,QA6EzC;CAlFQ,EAAA,GAMN,WANM;AAKuB,cA+EnB,aA/E6B,EAAA,CAAA,KAAA,EAgFjC,WAhFiC,EAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,KAAA,EAAA,OA6EzC,CA7EyC,EAAA;EACvC,YAAA,CAAA,EAAA,MAAA;CA4EF,EAAA,GAOE,UAPF,CAOE,eAPF,CAAA;AAEY,cA0BA,eAFZ,EAE2B,KAAA,CAAA,KAF3B,CAE2B,WAF3B,EAAA,KAAA,EAAA,KAAA,CAAA"}
1
+ {"version":3,"file":"node.d.mts","names":[],"sources":["../src/image-plugin-node.ts"],"sourcesContent":[],"mappings":";;;;;;cAyBa,+BAAgC,SAAA,CAAU,aAAQ;cAKlD,oBACJ,2DAAA;EANI,GAAA,CAAA,EAAA,SAAA,GAAA,OAGZ,GAAA,MAAA;EAEY,yBAmFZ,CAAA,EA7E+B,SAAA,CAAU,QA6EzC;CAlFQ,EAAA,GAMN,WANM;AAKuB,cA+EnB,aA/E6B,EAAA,CAAA,KAAA,EAgFjC,WAhFiC,EAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,KAAA,EAAA,OA6EzC,CA7EyC,EAAA;EACvC,YAAA,CAAA,EAAA,MAAA;CA4EF,EAAA,GAOE,UAPF,CAOE,eAPF,CAAA;AAEY,cA0BA,eAFZ,EAE2B,KAAA,CAAA,KAF3B,CAE2B,WAF3B,EAAA,KAAA,EAAA,KAAA,CAAA"}
package/dist/node.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{t as e}from"./common-ChU3HbEt.mjs";import{PhotonImage as t,Rgba as n,adjust_brightness as r,adjust_contrast as i,crop as a,fliph as o,flipv as s,gaussian_blur as c,grayscale as l,padding_bottom as u,padding_left as d,padding_right as f,padding_top as p,resize as m,sepia as h,sharpen as g}from"@cf-wasm/photon/node";import{UploadistaError as _}from"@uploadista/core/errors";import{ImagePlugin as v}from"@uploadista/core/flow";import{Effect as y,Layer as b}from"effect";const x=e=>{let t=e.toRgb();return new n(t.r,t.g,t.b,t.a)},S=(t,n,r,i)=>{let o=t.get_width(),s=t.get_height();if(!n&&!r)throw Error(`At least one of width or height is required`);if(n&&!r?r=Math.floor(n/o*s):r&&!n&&(n=Math.floor(r/s*o)),!n||!r)throw Error(`Invalid width or height`);if(n===o&&r===s)return t;let c=i?.fit||`cover`,l=e(c,o,s,n,r);t=m(t,l.width,l.height,1);let[h,g]=[t.get_width(),t.get_height()];if(c===`contain`&&i?.fit_cover_letterbox_color){let e=Math.floor((n-h)/2),a=Math.floor((r-g)/2);a>0&&(t=p(t,a,x(i.fit_cover_letterbox_color)),t=u(t,a,x(i.fit_cover_letterbox_color))),e>0&&(t=d(t,e,x(i.fit_cover_letterbox_color)),t=f(t,e,x(i.fit_cover_letterbox_color)))}else if(c===`cover`){let e=Math.floor(h-n)/2,i=Math.floor(g-r)/2;t=a(t,e,i,n+e,r+i)}return t},C=(e,t,n)=>{let r;switch(t){case`webp`:r=e.get_bytes_webp();break;case`jpeg`:r=e.get_bytes_jpeg(n?.jpeg_quality||100);break;case`png`:r=e.get_bytes();break;default:r=e.get_bytes_jpeg(n?.jpeg_quality||100)}return r},w=b.succeed(v,v.of({optimize:(e,{quality:n})=>{let r=t.new_from_byteslice(e),i=r.get_bytes_jpeg(n);return r.free(),y.succeed(i)},resize:(e,{width:n,height:r,fit:i})=>{if(!n&&!r)throw Error(`Either width or height must be specified for resize`);let a=t.new_from_byteslice(e),o=S(a,n??a.get_width(),r??a.get_height(),{fit:i}),s=o.get_bytes_webp();return a.free(),o.free(),y.succeed(s)},transform:(e,n)=>y.gen(function*(){if([`watermark`,`logo`,`text`].includes(n.type))return yield*y.fail(_.fromCode(`UNKNOWN_ERROR`,{body:`Photon plugin does not support '${n.type}'. Use sharp plugin or remove this transformation.`}));let a=t.new_from_byteslice(e);try{switch(n.type){case`resize`:a=S(a,n.width,n.height,{fit:n.fit});break;case`blur`:{let e=Math.round(n.sigma);c(a,e);break}case`rotate`:return yield*y.fail(_.fromCode(`UNKNOWN_ERROR`,{body:`Rotate transformation is not fully supported in photon plugin. Use sharp plugin instead.`}));case`flip`:n.direction===`horizontal`?o(a):s(a);break;case`grayscale`:l(a);break;case`sepia`:h(a);break;case`brightness`:{let e=Math.round(n.value*2.55);r(a,e);break}case`contrast`:{let e=n.value;i(a,e);break}case`sharpen`:g(a);break;default:return yield*y.fail(_.fromCode(`UNKNOWN_ERROR`,{body:`Unknown transformation type: ${n.type}`}))}return a.get_bytes_webp()}finally{a.free()}})}));export{S as autoResize,w as imagePluginNode,C as imageToFormat,x as tinyColorToPhotonRGBA};
1
+ import{t as e}from"./common-ChU3HbEt.mjs";import{PhotonImage as t,Rgba as n,adjust_brightness as r,adjust_contrast as i,crop as a,fliph as o,flipv as s,gaussian_blur as c,grayscale as l,padding_bottom as u,padding_left as d,padding_right as f,padding_top as p,resize as m,sepia as h,sharpen as g}from"@cf-wasm/photon/node";import{UploadistaError as _}from"@uploadista/core/errors";import{ImagePlugin as v}from"@uploadista/core/flow";import{withOperationSpan as y}from"@uploadista/observability";import{Effect as b,Layer as x}from"effect";const S=e=>{let t=e.toRgb();return new n(t.r,t.g,t.b,t.a)},C=(t,n,r,i)=>{let o=t.get_width(),s=t.get_height();if(!n&&!r)throw Error(`At least one of width or height is required`);if(n&&!r?r=Math.floor(n/o*s):r&&!n&&(n=Math.floor(r/s*o)),!n||!r)throw Error(`Invalid width or height`);if(n===o&&r===s)return t;let c=i?.fit||`cover`,l=e(c,o,s,n,r);t=m(t,l.width,l.height,1);let[h,g]=[t.get_width(),t.get_height()];if(c===`contain`&&i?.fit_cover_letterbox_color){let e=Math.floor((n-h)/2),a=Math.floor((r-g)/2);a>0&&(t=p(t,a,S(i.fit_cover_letterbox_color)),t=u(t,a,S(i.fit_cover_letterbox_color))),e>0&&(t=d(t,e,S(i.fit_cover_letterbox_color)),t=f(t,e,S(i.fit_cover_letterbox_color)))}else if(c===`cover`){let e=Math.floor(h-n)/2,i=Math.floor(g-r)/2;t=a(t,e,i,n+e,r+i)}return t},w=(e,t,n)=>{let r;switch(t){case`webp`:r=e.get_bytes_webp();break;case`jpeg`:r=e.get_bytes_jpeg(n?.jpeg_quality||100);break;case`png`:r=e.get_bytes();break;default:r=e.get_bytes_jpeg(n?.jpeg_quality||100)}return r},T=x.succeed(v,v.of({optimize:(e,{quality:n})=>{let r=t.new_from_byteslice(e),i=r.get_bytes_jpeg(n);return r.free(),b.succeed(i).pipe(y(`image`,`optimize`,{"image.quality":n,"image.input_size":e.byteLength}))},resize:(e,{width:n,height:r,fit:i})=>{if(!n&&!r)throw Error(`Either width or height must be specified for resize`);let a=t.new_from_byteslice(e),o=C(a,n??a.get_width(),r??a.get_height(),{fit:i}),s=o.get_bytes_webp();return a.free(),o.free(),b.succeed(s).pipe(y(`image`,`resize`,{"image.width":n,"image.height":r,"image.fit":i,"image.input_size":e.byteLength}))},transform:(e,n)=>b.gen(function*(){if([`watermark`,`logo`,`text`].includes(n.type))return yield*b.fail(_.fromCode(`UNKNOWN_ERROR`,{body:`Photon plugin does not support '${n.type}'. Use sharp plugin or remove this transformation.`}));let a=t.new_from_byteslice(e);try{switch(n.type){case`resize`:a=C(a,n.width,n.height,{fit:n.fit});break;case`blur`:{let e=Math.round(n.sigma);c(a,e);break}case`rotate`:return yield*b.fail(_.fromCode(`UNKNOWN_ERROR`,{body:`Rotate transformation is not fully supported in photon plugin. Use sharp plugin instead.`}));case`flip`:n.direction===`horizontal`?o(a):s(a);break;case`grayscale`:l(a);break;case`sepia`:h(a);break;case`brightness`:{let e=Math.round(n.value*2.55);r(a,e);break}case`contrast`:{let e=n.value;i(a,e);break}case`sharpen`:g(a);break;default:return yield*b.fail(_.fromCode(`UNKNOWN_ERROR`,{body:`Unknown transformation type: ${n.type}`}))}return a.get_bytes_webp()}finally{a.free()}}).pipe(y(`image`,`transform`,{"image.transformation_type":n.type,"image.input_size":e.byteLength}))}));export{C as autoResize,T as imagePluginNode,w as imageToFormat,S as tinyColorToPhotonRGBA};
2
2
  //# sourceMappingURL=node.mjs.map
package/dist/node.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"node.mjs","names":["outputBytes: Uint8Array"],"sources":["../src/image-plugin-node.ts"],"sourcesContent":["import {\n adjust_brightness,\n adjust_contrast,\n crop,\n fliph,\n flipv,\n gaussian_blur,\n grayscale,\n PhotonImage,\n padding_bottom,\n padding_left,\n padding_right,\n padding_top,\n Rgba,\n resize,\n sepia,\n sharpen,\n} from \"@cf-wasm/photon/node\";\nimport { UploadistaError } from \"@uploadista/core/errors\";\nimport { ImagePlugin } from \"@uploadista/core/flow\";\nimport { Effect, Layer } from \"effect\";\nimport type tinycolor from \"tinycolor2\";\nimport { calculateImageSize } from \"./common\";\n\nexport const tinyColorToPhotonRGBA = (color: tinycolor.Instance) => {\n const rgba = color.toRgb();\n return new Rgba(rgba.r, rgba.g, rgba.b, rgba.a);\n};\n\nexport const autoResize = (\n image: PhotonImage,\n newWidth?: number,\n newHeight?: number,\n options?: {\n fit?: \"contain\" | \"cover\" | \"fill\";\n fit_cover_letterbox_color?: tinycolor.Instance;\n },\n) => {\n const currentWidth = image.get_width();\n const currentHeight = image.get_height();\n\n if (!newWidth && !newHeight) {\n throw new Error(\"At least one of width or height is required\");\n }\n\n if (newWidth && !newHeight) {\n newHeight = Math.floor((newWidth / currentWidth) * currentHeight);\n } else if (newHeight && !newWidth) {\n newWidth = Math.floor((newHeight / currentHeight) * currentWidth);\n }\n\n if (!newWidth || !newHeight) {\n throw new Error(\"Invalid width or height\");\n }\n\n if (newWidth === currentWidth && newHeight === currentHeight) {\n return image;\n }\n\n const fit = options?.fit || \"cover\";\n\n const dem = calculateImageSize(\n fit,\n currentWidth,\n currentHeight,\n newWidth,\n newHeight,\n );\n\n image = resize(image, dem.width, dem.height, 1);\n\n const [updatedWidth, updatedHeight] = [image.get_width(), image.get_height()];\n\n if (fit === \"contain\" && options?.fit_cover_letterbox_color) {\n const paddingX = Math.floor((newWidth - updatedWidth) / 2);\n const paddingY = Math.floor((newHeight - updatedHeight) / 2);\n\n if (paddingY > 0) {\n image = padding_top(\n image,\n paddingY,\n tinyColorToPhotonRGBA(options.fit_cover_letterbox_color),\n );\n image = padding_bottom(\n image,\n paddingY,\n tinyColorToPhotonRGBA(options.fit_cover_letterbox_color),\n );\n }\n\n if (paddingX > 0) {\n image = padding_left(\n image,\n paddingX,\n tinyColorToPhotonRGBA(options.fit_cover_letterbox_color),\n );\n image = padding_right(\n image,\n paddingX,\n tinyColorToPhotonRGBA(options.fit_cover_letterbox_color),\n );\n }\n } else if (fit === \"cover\") {\n //crop to center\n const cropX = Math.floor(updatedWidth - newWidth) / 2;\n const cropY = Math.floor(updatedHeight - newHeight) / 2;\n\n //top left to down right\n image = crop(image, cropX, cropY, newWidth + cropX, newHeight + cropY);\n }\n\n return image;\n};\n\nexport const imageToFormat = (\n image: PhotonImage,\n format: \"webp\" | \"jpeg\" | \"png\",\n options?: {\n jpeg_quality?: number;\n },\n) => {\n let outputBytes: Uint8Array;\n\n switch (format) {\n case \"webp\":\n outputBytes = image.get_bytes_webp();\n break;\n case \"jpeg\":\n outputBytes = image.get_bytes_jpeg(options?.jpeg_quality || 100);\n break;\n case \"png\":\n outputBytes = image.get_bytes();\n break;\n default:\n outputBytes = image.get_bytes_jpeg(options?.jpeg_quality || 100);\n }\n\n return outputBytes;\n};\n\nexport const imagePluginNode = Layer.succeed(\n ImagePlugin,\n ImagePlugin.of({\n optimize: (inputBytes, { quality }) => {\n // create a PhotonImage instance\n const inputImage = PhotonImage.new_from_byteslice(inputBytes);\n\n // get jpeg bytes\n const outputBytes = inputImage.get_bytes_jpeg(quality);\n\n // call free() method to free memory\n inputImage.free();\n\n return Effect.succeed(outputBytes);\n },\n resize: (inputBytes, { width, height, fit }) => {\n if (!width && !height) {\n throw new Error(\"Either width or height must be specified for resize\");\n }\n // create a PhotonImage instance\n const inputImage = PhotonImage.new_from_byteslice(inputBytes);\n\n // resize image using photon\n const outputImage = autoResize(\n inputImage,\n width ?? inputImage.get_width(),\n height ?? inputImage.get_height(),\n { fit },\n );\n\n // get webp bytes\n const outputBytes = outputImage.get_bytes_webp();\n\n // for other formats\n // png : outputImage.get_bytes();\n // jpeg : outputImage.get_bytes_jpeg(quality);\n\n // call free() method to free memory\n inputImage.free();\n outputImage.free();\n\n return Effect.succeed(outputBytes);\n },\n transform: (inputBytes, transformation) => {\n return Effect.gen(function* () {\n // List of unsupported transformations in photon\n const unsupportedTransformations: string[] = [\n \"watermark\",\n \"logo\",\n \"text\",\n ];\n\n if (unsupportedTransformations.includes(transformation.type)) {\n return yield* Effect.fail(\n UploadistaError.fromCode(\"UNKNOWN_ERROR\", {\n body: `Photon plugin does not support '${transformation.type}'. Use sharp plugin or remove this transformation.`,\n }),\n );\n }\n\n // Create a PhotonImage instance\n let image = PhotonImage.new_from_byteslice(inputBytes);\n\n try {\n switch (transformation.type) {\n case \"resize\": {\n image = autoResize(\n image,\n transformation.width,\n transformation.height,\n { fit: transformation.fit },\n );\n break;\n }\n\n case \"blur\": {\n // Photon uses a radius parameter for gaussian blur\n // Convert sigma to a rough radius approximation\n const radius = Math.round(transformation.sigma);\n gaussian_blur(image, radius);\n break;\n }\n\n case \"rotate\": {\n // Photon doesn't have a straightforward rotate with angle function\n // We'll need to implement this using available functions or mark as unsupported\n return yield* Effect.fail(\n UploadistaError.fromCode(\"UNKNOWN_ERROR\", {\n body: \"Rotate transformation is not fully supported in photon plugin. Use sharp plugin instead.\",\n }),\n );\n }\n\n case \"flip\": {\n // Photon has fliph() and flipv() functions\n if (transformation.direction === \"horizontal\") {\n fliph(image);\n } else {\n flipv(image);\n }\n break;\n }\n\n case \"grayscale\": {\n grayscale(image);\n break;\n }\n\n case \"sepia\": {\n sepia(image);\n break;\n }\n\n case \"brightness\": {\n // Photon's adjust_brightness function takes a value to add to each pixel\n // Convert our -100 to +100 range to photon's expected range\n const adjustValue = Math.round(transformation.value * 2.55);\n adjust_brightness(image, adjustValue);\n break;\n }\n\n case \"contrast\": {\n // Photon's adjust_contrast takes a contrast value\n // Convert our -100 to +100 range to a suitable value\n const contrastValue = transformation.value;\n adjust_contrast(image, contrastValue);\n break;\n }\n\n case \"sharpen\": {\n sharpen(image);\n break;\n }\n\n default: {\n // TypeScript exhaustiveness check\n return yield* Effect.fail(\n UploadistaError.fromCode(\"UNKNOWN_ERROR\", {\n body: `Unknown transformation type: ${(transformation as { type: string }).type}`,\n }),\n );\n }\n }\n\n // Get output bytes (using webp format)\n const outputBytes = image.get_bytes_webp();\n\n return outputBytes;\n } finally {\n // Always free the image to prevent memory leaks\n image.free();\n }\n });\n },\n }),\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"node.mjs","names":["outputBytes: Uint8Array"],"sources":["../src/image-plugin-node.ts"],"sourcesContent":["import {\n adjust_brightness,\n adjust_contrast,\n crop,\n fliph,\n flipv,\n gaussian_blur,\n grayscale,\n PhotonImage,\n padding_bottom,\n padding_left,\n padding_right,\n padding_top,\n Rgba,\n resize,\n sepia,\n sharpen,\n} from \"@cf-wasm/photon/node\";\nimport { UploadistaError } from \"@uploadista/core/errors\";\nimport { ImagePlugin } from \"@uploadista/core/flow\";\nimport { withOperationSpan } from \"@uploadista/observability\";\nimport { Effect, Layer } from \"effect\";\nimport type tinycolor from \"tinycolor2\";\nimport { calculateImageSize } from \"./common\";\n\nexport const tinyColorToPhotonRGBA = (color: tinycolor.Instance) => {\n const rgba = color.toRgb();\n return new Rgba(rgba.r, rgba.g, rgba.b, rgba.a);\n};\n\nexport const autoResize = (\n image: PhotonImage,\n newWidth?: number,\n newHeight?: number,\n options?: {\n fit?: \"contain\" | \"cover\" | \"fill\";\n fit_cover_letterbox_color?: tinycolor.Instance;\n },\n) => {\n const currentWidth = image.get_width();\n const currentHeight = image.get_height();\n\n if (!newWidth && !newHeight) {\n throw new Error(\"At least one of width or height is required\");\n }\n\n if (newWidth && !newHeight) {\n newHeight = Math.floor((newWidth / currentWidth) * currentHeight);\n } else if (newHeight && !newWidth) {\n newWidth = Math.floor((newHeight / currentHeight) * currentWidth);\n }\n\n if (!newWidth || !newHeight) {\n throw new Error(\"Invalid width or height\");\n }\n\n if (newWidth === currentWidth && newHeight === currentHeight) {\n return image;\n }\n\n const fit = options?.fit || \"cover\";\n\n const dem = calculateImageSize(\n fit,\n currentWidth,\n currentHeight,\n newWidth,\n newHeight,\n );\n\n image = resize(image, dem.width, dem.height, 1);\n\n const [updatedWidth, updatedHeight] = [image.get_width(), image.get_height()];\n\n if (fit === \"contain\" && options?.fit_cover_letterbox_color) {\n const paddingX = Math.floor((newWidth - updatedWidth) / 2);\n const paddingY = Math.floor((newHeight - updatedHeight) / 2);\n\n if (paddingY > 0) {\n image = padding_top(\n image,\n paddingY,\n tinyColorToPhotonRGBA(options.fit_cover_letterbox_color),\n );\n image = padding_bottom(\n image,\n paddingY,\n tinyColorToPhotonRGBA(options.fit_cover_letterbox_color),\n );\n }\n\n if (paddingX > 0) {\n image = padding_left(\n image,\n paddingX,\n tinyColorToPhotonRGBA(options.fit_cover_letterbox_color),\n );\n image = padding_right(\n image,\n paddingX,\n tinyColorToPhotonRGBA(options.fit_cover_letterbox_color),\n );\n }\n } else if (fit === \"cover\") {\n //crop to center\n const cropX = Math.floor(updatedWidth - newWidth) / 2;\n const cropY = Math.floor(updatedHeight - newHeight) / 2;\n\n //top left to down right\n image = crop(image, cropX, cropY, newWidth + cropX, newHeight + cropY);\n }\n\n return image;\n};\n\nexport const imageToFormat = (\n image: PhotonImage,\n format: \"webp\" | \"jpeg\" | \"png\",\n options?: {\n jpeg_quality?: number;\n },\n) => {\n let outputBytes: Uint8Array;\n\n switch (format) {\n case \"webp\":\n outputBytes = image.get_bytes_webp();\n break;\n case \"jpeg\":\n outputBytes = image.get_bytes_jpeg(options?.jpeg_quality || 100);\n break;\n case \"png\":\n outputBytes = image.get_bytes();\n break;\n default:\n outputBytes = image.get_bytes_jpeg(options?.jpeg_quality || 100);\n }\n\n return outputBytes;\n};\n\nexport const imagePluginNode = Layer.succeed(\n ImagePlugin,\n ImagePlugin.of({\n optimize: (inputBytes, { quality }) => {\n // create a PhotonImage instance\n const inputImage = PhotonImage.new_from_byteslice(inputBytes);\n\n // get jpeg bytes\n const outputBytes = inputImage.get_bytes_jpeg(quality);\n\n // call free() method to free memory\n inputImage.free();\n\n return Effect.succeed(outputBytes).pipe(\n withOperationSpan(\"image\", \"optimize\", {\n \"image.quality\": quality,\n \"image.input_size\": inputBytes.byteLength,\n }),\n );\n },\n resize: (inputBytes, { width, height, fit }) => {\n if (!width && !height) {\n throw new Error(\"Either width or height must be specified for resize\");\n }\n // create a PhotonImage instance\n const inputImage = PhotonImage.new_from_byteslice(inputBytes);\n\n // resize image using photon\n const outputImage = autoResize(\n inputImage,\n width ?? inputImage.get_width(),\n height ?? inputImage.get_height(),\n { fit },\n );\n\n // get webp bytes\n const outputBytes = outputImage.get_bytes_webp();\n\n // for other formats\n // png : outputImage.get_bytes();\n // jpeg : outputImage.get_bytes_jpeg(quality);\n\n // call free() method to free memory\n inputImage.free();\n outputImage.free();\n\n return Effect.succeed(outputBytes).pipe(\n withOperationSpan(\"image\", \"resize\", {\n \"image.width\": width,\n \"image.height\": height,\n \"image.fit\": fit,\n \"image.input_size\": inputBytes.byteLength,\n }),\n );\n },\n transform: (inputBytes, transformation) => {\n return Effect.gen(function* () {\n // List of unsupported transformations in photon\n const unsupportedTransformations: string[] = [\n \"watermark\",\n \"logo\",\n \"text\",\n ];\n\n if (unsupportedTransformations.includes(transformation.type)) {\n return yield* Effect.fail(\n UploadistaError.fromCode(\"UNKNOWN_ERROR\", {\n body: `Photon plugin does not support '${transformation.type}'. Use sharp plugin or remove this transformation.`,\n }),\n );\n }\n\n // Create a PhotonImage instance\n let image = PhotonImage.new_from_byteslice(inputBytes);\n\n try {\n switch (transformation.type) {\n case \"resize\": {\n image = autoResize(\n image,\n transformation.width,\n transformation.height,\n { fit: transformation.fit },\n );\n break;\n }\n\n case \"blur\": {\n // Photon uses a radius parameter for gaussian blur\n // Convert sigma to a rough radius approximation\n const radius = Math.round(transformation.sigma);\n gaussian_blur(image, radius);\n break;\n }\n\n case \"rotate\": {\n // Photon doesn't have a straightforward rotate with angle function\n // We'll need to implement this using available functions or mark as unsupported\n return yield* Effect.fail(\n UploadistaError.fromCode(\"UNKNOWN_ERROR\", {\n body: \"Rotate transformation is not fully supported in photon plugin. Use sharp plugin instead.\",\n }),\n );\n }\n\n case \"flip\": {\n // Photon has fliph() and flipv() functions\n if (transformation.direction === \"horizontal\") {\n fliph(image);\n } else {\n flipv(image);\n }\n break;\n }\n\n case \"grayscale\": {\n grayscale(image);\n break;\n }\n\n case \"sepia\": {\n sepia(image);\n break;\n }\n\n case \"brightness\": {\n // Photon's adjust_brightness function takes a value to add to each pixel\n // Convert our -100 to +100 range to photon's expected range\n const adjustValue = Math.round(transformation.value * 2.55);\n adjust_brightness(image, adjustValue);\n break;\n }\n\n case \"contrast\": {\n // Photon's adjust_contrast takes a contrast value\n // Convert our -100 to +100 range to a suitable value\n const contrastValue = transformation.value;\n adjust_contrast(image, contrastValue);\n break;\n }\n\n case \"sharpen\": {\n sharpen(image);\n break;\n }\n\n default: {\n // TypeScript exhaustiveness check\n return yield* Effect.fail(\n UploadistaError.fromCode(\"UNKNOWN_ERROR\", {\n body: `Unknown transformation type: ${(transformation as { type: string }).type}`,\n }),\n );\n }\n }\n\n // Get output bytes (using webp format)\n const outputBytes = image.get_bytes_webp();\n\n return outputBytes;\n } finally {\n // Always free the image to prevent memory leaks\n image.free();\n }\n }).pipe(\n withOperationSpan(\"image\", \"transform\", {\n \"image.transformation_type\": transformation.type,\n \"image.input_size\": inputBytes.byteLength,\n }),\n );\n },\n }),\n);\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uploadista/flow-images-photon",
3
3
  "type": "module",
4
- "version": "0.0.18-beta.8",
4
+ "version": "0.0.18",
5
5
  "description": "Photon image processing service for Uploadista Flow",
6
6
  "license": "MIT",
7
7
  "author": "Uploadista",
@@ -20,9 +20,10 @@
20
20
  }
21
21
  },
22
22
  "dependencies": {
23
- "@cf-wasm/photon": "0.3.1",
23
+ "@cf-wasm/photon": "0.3.4",
24
24
  "tinycolor2": "1.6.0",
25
- "@uploadista/core": "0.0.18-beta.8"
25
+ "@uploadista/core": "0.0.18",
26
+ "@uploadista/observability": "0.0.18"
26
27
  },
27
28
  "peerDependencies": {
28
29
  "effect": "^3.0.0",
@@ -34,9 +35,9 @@
34
35
  "@types/tinycolor2": "1.4.6",
35
36
  "effect": "3.19.8",
36
37
  "tsdown": "0.16.8",
37
- "vitest": "4.0.14",
38
+ "vitest": "4.0.15",
38
39
  "zod": "4.1.13",
39
- "@uploadista/typescript-config": "0.0.18-beta.8"
40
+ "@uploadista/typescript-config": "0.0.18"
40
41
  },
41
42
  "scripts": {
42
43
  "build": "tsdown",
@@ -18,6 +18,7 @@ import {
18
18
  } from "@cf-wasm/photon/node";
19
19
  import { UploadistaError } from "@uploadista/core/errors";
20
20
  import { ImagePlugin } from "@uploadista/core/flow";
21
+ import { withOperationSpan } from "@uploadista/observability";
21
22
  import { Effect, Layer } from "effect";
22
23
  import type tinycolor from "tinycolor2";
23
24
  import { calculateImageSize } from "./common";
@@ -151,7 +152,12 @@ export const imagePluginNode = Layer.succeed(
151
152
  // call free() method to free memory
152
153
  inputImage.free();
153
154
 
154
- return Effect.succeed(outputBytes);
155
+ return Effect.succeed(outputBytes).pipe(
156
+ withOperationSpan("image", "optimize", {
157
+ "image.quality": quality,
158
+ "image.input_size": inputBytes.byteLength,
159
+ }),
160
+ );
155
161
  },
156
162
  resize: (inputBytes, { width, height, fit }) => {
157
163
  if (!width && !height) {
@@ -179,7 +185,14 @@ export const imagePluginNode = Layer.succeed(
179
185
  inputImage.free();
180
186
  outputImage.free();
181
187
 
182
- return Effect.succeed(outputBytes);
188
+ return Effect.succeed(outputBytes).pipe(
189
+ withOperationSpan("image", "resize", {
190
+ "image.width": width,
191
+ "image.height": height,
192
+ "image.fit": fit,
193
+ "image.input_size": inputBytes.byteLength,
194
+ }),
195
+ );
183
196
  },
184
197
  transform: (inputBytes, transformation) => {
185
198
  return Effect.gen(function* () {
@@ -290,7 +303,12 @@ export const imagePluginNode = Layer.succeed(
290
303
  // Always free the image to prevent memory leaks
291
304
  image.free();
292
305
  }
293
- });
306
+ }).pipe(
307
+ withOperationSpan("image", "transform", {
308
+ "image.transformation_type": transformation.type,
309
+ "image.input_size": inputBytes.byteLength,
310
+ }),
311
+ );
294
312
  },
295
313
  }),
296
314
  );