19
loading...
This website collects cookies to deliver better user experience
#f60053
, or #16ee8a
. A hex color consists of four different parts:#
as a prefix00
to FF
for each color, this means it's going from 0
to 255
in decimal. In binary, it would go from 00000000
to 11111111
.11111111
is almost twice as large as 01111111
, 11111110
on the other hand is only slightly smaller. A human eye most likely won't notice the difference betweeen #FFFFFF
and #FEFEFE
. It will notice the difference between #FFFFFF
and #7F7F7F
, though.const args = process.argv.slice(2)
const mainImagePath = args[0]
const hiddenImagePath = args[1]
const targetImagePath = args[2]
// Usage:
// node hide-image.js ./cat.png ./hidden.png ./target.png
const imageSize = require('image-size')
const { createCanvas, loadImage } = require('canvas')
const args = process.argv.slice(2)
const mainImagePath = args[0]
const hiddenImagePath = args[1]
const targetImagePath = args[2]
const sizeMain = imageSize(mainImagePath)
const sizeHidden = imageSize(hiddenImagePath)
const canvasMain = createCanvas(sizeMain.width, sizeMain.height)
const canvasHidden = createCanvas(sizeHidden.width, sizeHidden.height)
const canvasTarget = createCanvas(sizeMain.width, sizeMain.height)
const contextMain = canvasMain.getContext('2d')
const contextHidden = canvasHidden.getContext('2d')
const contextTarget = canvasTarget.getContext('2d')
;(async () => {
const mainImage = await loadImage(mainImagePath)
contextMain.drawImage(mainImage, 0, 0, sizeMain.width, sizeMain.height)
const hiddenImage = await loadImage(hiddenImagePath)
contextHidden.drawImage(hiddenImage, 0, 0, sizeHidden.width, sizeHidden.height)
})()
for (let x = 0; x < sizeHidden.width; x++) {
for (let y = 0; y < sizeHidden.height; y++) {
const colorMain = Array.from(contextMain.getImageData(x, y, 1, 1).data)
const colorHidden = Array.from(contextHidden.getImageData(x, y, 1, 1).data)
}
}
A7 A6 A5 A4 A3 A2 A1 A0 (color A)
B7 B6 B5 B4 B3 B2 B1 B0 (color B)
A7 A6 A5 A4 A3 B7 B6 B5
const combineColors = (a, b) => {
const aBinary = a.toString(2).padStart(8, '0')
const bBinary = b.toString(2).padStart(8, '0')
return parseInt('' +
aBinary[0] +
aBinary[1] +
aBinary[2] +
aBinary[3] +
aBinary[4] +
bBinary[0] +
bBinary[1] +
bBinary[2],
2)
}
const colorMain = Array.from(contextMain.getImageData(x, y, 1, 1).data)
const colorHidden = Array.from(contextHidden.getImageData(x, y, 1, 1).data)
const combinedColor = [
combineColors(colorMain[0], colorHidden[0]),
combineColors(colorMain[1], colorHidden[1]),
combineColors(colorMain[2], colorHidden[2]),
]
contextTarget.fillStyle = `rgb(${combinedColor[0]}, ${combinedColor[1]}, ${combinedColor[2]})`
contextTarget.fillRect(x, y, 1, 1)
const buffer = canvasTarget.toBuffer('image/png')
fs.writeFileSync(targetImagePath, buffer)
const extractColor = c => {
const cBinary = c.toString(2).padStart(8, '0')
return parseInt('' +
cBinary[5] +
cBinary[6] +
cBinary[7] +
'00000',
2)
}