MCPcopy
hub / github.com/ZHO-ZHO-ZHO/Nano-Bananary / embedWatermark

Function embedWatermark

utils/fileUtils.ts:87–129  ·  view source on GitHub ↗
(imageUrl: string, text: string)

Source from the content-addressed store, hash-verified

85 * @returns A Promise that resolves with the data URL of the watermarked image.
86 */
87export const embedWatermark = (imageUrl: string, text: string): Promise<string> => {
88 return new Promise((resolve, reject) => {
89 const canvas = document.createElement('canvas');
90 const ctx = canvas.getContext('2d');
91 if (!ctx) {
92 return reject(new Error("Could not get canvas context."));
93 }
94
95 const img = new Image();
96 img.crossOrigin = "anonymous";
97 img.onload = () => {
98 canvas.width = img.width;
99 canvas.height = img.height;
100 ctx.drawImage(img, 0, 0);
101
102 const watermarkText = text + "::END"; // Add a delimiter
103 const binaryMessage = textToBinary(watermarkText);
104 const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
105 const data = imageData.data;
106
107 if (binaryMessage.length > data.length / 4 * 3) {
108 console.warn("Watermark is too long for the image. Skipping.");
109 return resolve(imageUrl); // Return original if too long
110 }
111
112 let messageIndex = 0;
113 for (let i = 0; i < data.length && messageIndex < binaryMessage.length; i += 4) {
114 // Embed in R, G, B channels
115 for (let j = 0; j < 3 && messageIndex < binaryMessage.length; j++) {
116 const bit = parseInt(binaryMessage[messageIndex], 2);
117 // Clear the LSB and then set it
118 data[i + j] = (data[i + j] & 0xFE) | bit;
119 messageIndex++;
120 }
121 }
122
123 ctx.putImageData(imageData, 0, 0);
124 resolve(canvas.toDataURL('image/png'));
125 };
126 img.onerror = () => reject(new Error("Failed to load image for watermarking."));
127 img.src = imageUrl;
128 });
129};
130
131/**
132 * Programmatically triggers a file download for a given data URL.

Callers 1

AppFunction · 0.90

Calls 1

textToBinaryFunction · 0.85

Tested by

no test coverage detected