[英]encrypt and decrypt image using javascript
我的服務器使用這個 python function 以字節數組格式加密和解密圖像。 我想在前端進行相同的加密並在后端發送到這個 function。 如何將此方法轉換為 JavaScript
def encrypted_decrypted_image(image):
key = 48
count = 0
for index, value in enumerate(image):
count += 1
image[index] = value ^ key
if count == 10:
break
return image
這是使用Array.reduce()
的方法,
// def encrypted_decrypted_image(image): // key = 48 // count = 0 // for index, value in enumerate(image): // count += 1 // image[index] = value ^ key // if count == 10: // break // return image function xorImage(imageBuffer, key=48){ return imageBuffer.reduce((acc, value, index) => { if(index == 10) return acc; acc.push(value ^ key); return acc; }, []) } console.log(xorImage([1, 20, 3, 4, 5, 6, 7, 8, 9]))
要從圖像中獲取單個像素分量,首先將該圖像繪制到 canvas:
const image = document.getElementById('image');
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const width = image.width;
const height = image.height;
canvas.width = width;
canvas.height = height;
// Draw original image:
context.drawImage(image, 0, 0, width, height);
然后,獲取要更新的像素的值:
const data = context.getImageData(0, 0, width, height).data;
注意CanvasRenderingContext2D.getImageData()
function 返回的數據的形狀和類型:
ImageData ctx.getImageData(sx, sy, sw, sh);
sx
:從中提取 ImageData 的矩形左上角的 x 坐標。sy
: 矩形左上角的 y 坐標,從中提取 ImageData。sw
:從中提取 ImageData 的矩形的寬度。sh
:從中提取 ImageData 的矩形的高度。 你可以看到它返回一個ImageData
object,不管它是什么。 這里重要的部分是 object 有一個.data
屬性,其中包含我們所有的像素值。
但是,請注意.data
屬性是一維Uint8ClampedArray
,這意味着所有像素的組件都已展平,因此您會得到如下所示的內容:
假設您有一個像這樣的 2x2 圖像:
RED PIXEL | GREEN PIXEL
BLUE PIXEL | TRANSPARENT PIXEL
然后,你會像這樣得到它們:
[ 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255, 0, 0, 0, 0 ]
| RED PIXEL | GREEN PIXEL | BLUE PIXEL | TRANSPAERENT PIXEL |
| 1ST PIXEL | 2ND PIXEL | 3RD PIXEL | 4TH PIXEL |
然后,您可以根據需要轉換這些值,並且在您的特定用例中,這就是您在將轉換后的數據發送到服務器之前需要在前端做的所有事情:
const transformedData = encryptedDecryptedImage(data);
fetch('httsp://', { ... });
如果要將轉換后的數據重新繪制到頁面上,首先需要使用CanvasRenderingContext2D.createImageData()
和CanvasRenderingContext2D.putImageData()
將其轉換回ImageData
:
const imageData = context.createImageData(width, height);
imageData.data.set(new Uint8ClampedArray(transformedData));
context.putImageData(transformedData, 0, 0);
工作示例:
const image = document.getElementById('image'); const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); const width = image.width; const height = image.height; canvas.width = width; canvas.height = height; // Draw original image: context.drawImage(image, 0, 0, width, height); // Transform the top half of the image (each pixel has 4 coordinates, RGB and alpha): const maxTransformedCoords = width * Math.round(height / 2) * 4; // Avoid processing more than needed: const requiredRows = Math.ceil(maxTransformedCoords / (width * 4)); // Get the pixel component values as an array: const data = context.getImageData(0, 0, width, requiredRows).data; // Your transform logic (with some changes): const key = 48; let count = 0; const transformedData = data.map((value, i) => { if (++count > maxTransformedCoords) return value; // Turn alpha coordinates opaque: // if ((i + 1) % 4 === 0) return 255; // Your logic: return value ** key; }); // Turn the transformed data into an ImageData object: const imageData = context.createImageData(width, requiredRows); imageData.data.set(new Uint8ClampedArray(transformedData)); // Draw the transformed pixels: context.putImageData(imageData, 0, 0); // Display it on the page: canvas.id = 'canvas'; document.body.append(canvas);
body { margin: 0; height: 100vh; display: flex; flex-direction: row; align-items: center; justify-content: center; font-family: monospace; overflow: hidden; } #image, #canvas { border: 4px solid white; border-radius: 2px; box-shadow: 0 0 32px 0 rgba(0, 0, 0, .25); width: 150px; box-sizing: border-box; display: block; background: cyan; } #canvas { margin-left: 32px; }
<img id="image" src="data:image/gif;base64,R0lGODlhSwBLAPEAACMfIO0cJAAAAAAAACH/C0ltYWdlTWFnaWNrDWdhbW1hPTAuNDU0NTUAIf4jUmVzaXplZCBvbiBodHRwczovL2V6Z2lmLmNvbS9yZXNpemUAIfkEBQAAAgAsAAAAAEsASwAAAv+Uj6mb4A+QY7TaKxvch+MPKpC0eeUUptdomOzJqnLUvnFcl7J6Pzn9I+l2IdfII8DZiCnYsYdK4qRTptAZwQKRVK71CusOgx2nFRrlhMu+33o2NEalC6S9zQvfi3Mlnm9WxeQ396F2+HcQsMjYGEBRVbhy5yOp6OgIeVIHpEnZyYCZ6cklKBJX+Kgg2riqKoayOWl2+VrLmtDqBptIOjZ6K4qAeSrL8PcmHExsgMs2dpyIxPpKvdhM/YxaTMW2PGr9GP76BN3VHTMurh7eoU14jsc+P845Vn6OTb/P/I68iYOfwGv+JOmRNHBfsV5ujA1LqM4eKDoNvXyDqItTxYX/DC9irKBlIhkKGPtFw1JDiMeS7CqWqySPZcKGHH/JHGgIpb6bCl1O0LmT57yCOqoI5UcU0YKjPXmFjMm0ZQ4NIVdGBdZRi9WrjLxJNMY1Yr4dYeuNxWApl1ALHb+KDHrTV1owlriedJgSr4Cybu/9dFiWYAagsqAGVkkzaZTAuqD9ywKWMUG9dCO3u2zWpVzIhpW122utZlrHnTN+Bq2Mqrlnqh8CQ+0Mrq3Kc++q7eo6dlB3rLuh3abPVbbbI2mxBdhWdsZhid8cr0oy9F08q0k5FXSadiyL1mF5z51a8VsQOp3/LlodkBfzmzWf2bOrtfzr48k/1hupDaLa9rUbO+zlwndfaOCURAXRNaCBqBT2BncJakWfTzSYkmCEFr60RX0V8sKaHOltCBJ1tAAFYhHaVVbig3jxp0IBADs=" >
⚠️ 請注意,如果我嘗試使用更長的數據 URI,如果我包含外部圖像或大於允許的答案,我將使用小數據 URI 來避免Cross-Origin
問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.