我正在尝试将图像(使用 HTML 画布)从 RGB 转换为 YCoCg 颜色空间,并将画布的输出保存为 PNG,可以根据此处的代码无损地转换回来:
https://stackoverflow.com/a/12146329/2399347
该过程是可逆的,但我的尝试目前仅在不使用中间格式时才有效。没有这个,代码的实际应用就会受到限制。
我需要让“提升”过程使用 8 位有符号整数(我相信从 -128 到 127,在伪代码中模 0x100),并转换要在画布上显示的值(从 0 到 255),然后再能够保存。如果成功,当转换后的图像放置在画布中时,重新转换值和反向提升应该会生成原始图像。当前生成的值无法正确显示在画布上(从 -255 到 255)。
上述问题超出了我目前的知识范围,目前我还没有找到基于在线搜索和查看 Javascript 文档的方法。那些知道(或感兴趣)的人,能否请您看一下代码,并建议或提供一种实用的方法或解决方法?
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="charset=UTF-8" />
<style>
img, canvas {
display: block;
padding-bottom: 1em;
}
</style>
<script>
function go() {
// Extract PNG image to Canvas
var canvas = document.getElementById('ycocg');
var ctx = canvas.getContext('2d');
var source = document.querySelector("#original");
canvas.width = source.width;
canvas.height = source.height;
ctx.drawImage(source, 0, 0);
var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// Canvas to convert image to YCoCg and back in one step
var canvasBack = document.getElementById('back2rgb');
var ctxBack = canvasBack.getContext('2d');
canvasBack.width = source.width;
canvasBack.height = source.height;
ctxBack.drawImage(canvas, 0, 0);
var canvasBackData = ctxBack.getImageData(0, 0, canvas.width, canvas.height);
// Colour space functions
function forward_lift( x1, y1 ) {
var diff = ( ( y1 - x1 ) ) % 256;
var average = ( x1 + ( diff >> 1 ) ) % 256;
return { c1: average, c2: diff };
}
function reverse_lift( average, diff ) {
var x2 = ( average - ( diff >> 1 ) ) % 256;
var y2 = ( ( x2 + diff ) ) % 256;
return { c1: x2, c2: y2 };
}
function RGB_to_YCoCg24( red, green, blue ) {
// Conversion and back
var lift1 = forward_lift( red, blue );
var lift2 = forward_lift( green, lift1.c1 );
var rlift1 = reverse_lift( lift2.c1, lift2.c2 );
var rlift2 = reverse_lift( rlift1.c2, lift1.c2 );
canvasBackData.data[idx + 0] = rlift2.c1 % 256; // R
canvasBackData.data[idx + 1] = rlift1.c1 % 256; // G
canvasBackData.data[idx + 2] = rlift2.c2 % 256; // B
// Attempt at conversion only and store
canvasData.data[idx + 0] = lift2.c1 % 256; // Y
canvasData.data[idx + 1] = lift2.c2 % 256; // Cg
canvasData.data[idx + 2] = lift1.c2 % 256; // Co
}
function YCoCg24_to_RGB( Yimg, Cg, Co ) {
// Attempt at reversing stored image
var rlift1 = reverse_lift( Yimg, Cg );
var rlift2 = reverse_lift( rlift1.c2, Co );
canvasStepData.data[idx + 0] = rlift2.c1 % 256; // R
canvasStepData.data[idx + 1] = rlift1.c1 % 256; // G
canvasStepData.data[idx + 2] = rlift2.c2 % 256; // B
}
// Conversion of RGB image to YCoCg
for (var x = 0; x < canvasData.width; x++) {
for (var y = 0; y < canvasData.height; y++) {
// Index of the pixel in the array
var idx = (x + y * canvas.width) * 4;
RGB_to_YCoCg24( canvasData.data[idx + 0], canvasData.data[idx + 1], canvasData.data[idx + 2] );
}
}
ctxBack.putImageData(canvasBackData, 0, 0);
ctx.putImageData(canvasData, 0, 0);
// Convert from YCoCg to RGB, in two steps
var canvasStep = document.getElementById('twostep');
var ctxStep = canvasStep.getContext('2d');
canvasStep.width = source.width;
canvasStep.height = source.height;
ctxStep.drawImage(canvas, 0, 0);
var canvasStepData = ctxStep.getImageData(0, 0, canvas.width, canvas.height);
for (var x = 0; x < canvasData.width; x++) {
for (var y = 0; y < canvasData.height; y++) {
// Index of the pixel in the array
var idx = (x + y * canvas.width) * 4;
YCoCg24_to_RGB( canvasStepData.data[idx + 0], canvasStepData.data[idx + 1], canvasStepData.data[idx + 2] );
}
}
ctxStep.putImageData(canvasStepData, 0, 0);
}
</script>
</head>
<body onload="go()">
<div id="container">
Original:
<img id="original" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABAAAAAQACAIAAADwf7zUAAAR00lEQVR4Xu3a0QnDAAxDQTVkAO8/bbdQKTq4Afz7kD9PnuT9Y5/X/e53/59yf5/73e9+97vf/c+bjAAAAH4ZAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAADQWQAAAAAvQAAAgAAAAAAEAAAAIAAAAAABAAAACAAAABAAAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAAEwGUDAABgAQAAAC9AAACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAA0AACAAAAAAAQAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAABAAAAAAAIAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAAAgAAAAAAEAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAAAQAAAAgAAAAAAEAAAAIAAAAAABAAAACAAAAEAAAAAAAgAAABAAAACAAAAAAAQAAAAIAAAAQAAAAAACAAAAEAAAAIAAAAAABAAAACAAAAAAAQAAAAgAAABAAAAAAAIAAAD4Aozry/w+U2+oAAAAAElFTkSuQmCC" />
Converted and back in one step:
<canvas id="back2rgb"></canvas>
Converted and stored (right click, save image as):
<canvas id="ycocg"></canvas>
Restored previous image:
<canvas id="twostep"></canvas>
</div>
</body>
</html>