在JavaScript中将原始图像的十六进制字符串转换为位图图像
引言: 我正在从智能卡读取指纹的图像数据,正如您所知,这些数据在智能卡中保存为原始图像。 我正在开发一个客户端程序,它只使用java脚本从读卡器的扫描仪读取图像,并在客户端页面中显示 现在我的问题是:在JavaScript中将原始图像的十六进制字符串转换为位图图像,javascript,string,bitmap,hex,smartcard,Javascript,String,Bitmap,Hex,Smartcard,引言: 我正在从智能卡读取指纹的图像数据,正如您所知,这些数据在智能卡中保存为原始图像。 我正在开发一个客户端程序,它只使用java脚本从读卡器的扫描仪读取图像,并在客户端页面中显示 现在我的问题是: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script>
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script>
if (!window.atob) {
var tableStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var table = tableStr.split("");
window.atob = function (base64) {
if (/(=[^=]+|={3,})$/.test(base64)) throw new Error("String contains an invalid character");
base64 = base64.replace(/=/g, "");
var n = base64.length & 3;
if (n === 1) throw new Error("String contains an invalid character");
for (var i = 0, j = 0, len = base64.length / 4, bin = []; i < len; ++i) {
var a = tableStr.indexOf(base64[j++] || "A"), b = tableStr.indexOf(base64[j++] || "A");
var c = tableStr.indexOf(base64[j++] || "A"), d = tableStr.indexOf(base64[j++] || "A");
if ((a | b | c | d) < 0) throw new Error("String contains an invalid character");
bin[bin.length] = ((a << 2) | (b >> 4)) & 255;
bin[bin.length] = ((b << 4) | (c >> 2)) & 255;
bin[bin.length] = ((c << 6) | d) & 255;
};
return String.fromCharCode.apply(null, bin).substr(0, bin.length + n - 4);
};
window.btoa = function (bin) {
for (var i = 0, j = 0, len = bin.length / 3, base64 = []; i < len; ++i) {
var a = bin.charCodeAt(j++), b = bin.charCodeAt(j++), c = bin.charCodeAt(j++);
if ((a | b | c) > 255) throw new Error("String contains an invalid character");
base64[base64.length] = table[a >> 2] + table[((a << 4) & 63) | (b >> 4)] +
(isNaN(b) ? "=" : table[((b << 2) & 63) | (c >> 6)]) +
(isNaN(b + c) ? "=" : table[c & 63]);
}
return base64.join("");
};
}
function hexToBase64(str) {
return btoa(String.fromCharCode.apply(null,
str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" "))
);
}
function base64ToHex(str) {
for (var i = 0, bin = atob(str.replace(/[ \r\n]+$/, "")), hex = []; i < bin.length; ++i) {
var tmp = bin.charCodeAt(i).toString(16);
if (tmp.length === 1) tmp = "0" + tmp;
hex[hex.length] = tmp;
}
return hex.join(" ");
}
function doConvert() {
var myHex = document.getElementById('myText').value;
var myBase64 = hexToBase64(myHex);
document.getElementById('myImage').src = "data:image/bmp;base64," + myBase64;
}
</script>
</head>
<body>
<div>
<p>
Enter Raw Hex:
<br>
<textarea rows="4" cols="50" id="myText">Enter Raw Hex String here ...</textarea>
<br>
<button id="myButton" onclick="doConvert()"> Click me </button>
<br>
<img id="myImage" alt="img1"/>
</p>
</div>
</body>
</html>
private static BufferedImage byte2Buffered(byte[] rawData, int width, int height){
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
byte[] array = ((DataBufferByte)image.getRaster().getDataBuffer()).getData();
System.arraycopy(rawData, 0, array, 0, rawData.length);
return image;
}
如何将原始数据的十六进制字符串转换为十六进制字符串,并通过位图图像的适当标题完成?请注意,我有图像的宽度
和高度
尝试过的方法:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script>
if (!window.atob) {
var tableStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var table = tableStr.split("");
window.atob = function (base64) {
if (/(=[^=]+|={3,})$/.test(base64)) throw new Error("String contains an invalid character");
base64 = base64.replace(/=/g, "");
var n = base64.length & 3;
if (n === 1) throw new Error("String contains an invalid character");
for (var i = 0, j = 0, len = base64.length / 4, bin = []; i < len; ++i) {
var a = tableStr.indexOf(base64[j++] || "A"), b = tableStr.indexOf(base64[j++] || "A");
var c = tableStr.indexOf(base64[j++] || "A"), d = tableStr.indexOf(base64[j++] || "A");
if ((a | b | c | d) < 0) throw new Error("String contains an invalid character");
bin[bin.length] = ((a << 2) | (b >> 4)) & 255;
bin[bin.length] = ((b << 4) | (c >> 2)) & 255;
bin[bin.length] = ((c << 6) | d) & 255;
};
return String.fromCharCode.apply(null, bin).substr(0, bin.length + n - 4);
};
window.btoa = function (bin) {
for (var i = 0, j = 0, len = bin.length / 3, base64 = []; i < len; ++i) {
var a = bin.charCodeAt(j++), b = bin.charCodeAt(j++), c = bin.charCodeAt(j++);
if ((a | b | c) > 255) throw new Error("String contains an invalid character");
base64[base64.length] = table[a >> 2] + table[((a << 4) & 63) | (b >> 4)] +
(isNaN(b) ? "=" : table[((b << 2) & 63) | (c >> 6)]) +
(isNaN(b + c) ? "=" : table[c & 63]);
}
return base64.join("");
};
}
function hexToBase64(str) {
return btoa(String.fromCharCode.apply(null,
str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" "))
);
}
function base64ToHex(str) {
for (var i = 0, bin = atob(str.replace(/[ \r\n]+$/, "")), hex = []; i < bin.length; ++i) {
var tmp = bin.charCodeAt(i).toString(16);
if (tmp.length === 1) tmp = "0" + tmp;
hex[hex.length] = tmp;
}
return hex.join(" ");
}
function doConvert() {
var myHex = document.getElementById('myText').value;
var myBase64 = hexToBase64(myHex);
document.getElementById('myImage').src = "data:image/bmp;base64," + myBase64;
}
</script>
</head>
<body>
<div>
<p>
Enter Raw Hex:
<br>
<textarea rows="4" cols="50" id="myText">Enter Raw Hex String here ...</textarea>
<br>
<button id="myButton" onclick="doConvert()"> Click me </button>
<br>
<img id="myImage" alt="img1"/>
</p>
</div>
</body>
</html>
private static BufferedImage byte2Buffered(byte[] rawData, int width, int height){
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
byte[] array = ((DataBufferByte)image.getRaster().getDataBuffer()).getData();
System.arraycopy(rawData, 0, array, 0, rawData.length);
return image;
}
我已经用java开发了这个程序。此外,我可以将位图图像的十六进制字符串转换为base64,然后在图像标记中显示base64字符串。然而,当且仅当十六进制包含标头,而我们的数据是原始数据时,这些函数才能正常工作
我的代码(仅适用于包含标题的十六进制字符串):
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script>
if (!window.atob) {
var tableStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var table = tableStr.split("");
window.atob = function (base64) {
if (/(=[^=]+|={3,})$/.test(base64)) throw new Error("String contains an invalid character");
base64 = base64.replace(/=/g, "");
var n = base64.length & 3;
if (n === 1) throw new Error("String contains an invalid character");
for (var i = 0, j = 0, len = base64.length / 4, bin = []; i < len; ++i) {
var a = tableStr.indexOf(base64[j++] || "A"), b = tableStr.indexOf(base64[j++] || "A");
var c = tableStr.indexOf(base64[j++] || "A"), d = tableStr.indexOf(base64[j++] || "A");
if ((a | b | c | d) < 0) throw new Error("String contains an invalid character");
bin[bin.length] = ((a << 2) | (b >> 4)) & 255;
bin[bin.length] = ((b << 4) | (c >> 2)) & 255;
bin[bin.length] = ((c << 6) | d) & 255;
};
return String.fromCharCode.apply(null, bin).substr(0, bin.length + n - 4);
};
window.btoa = function (bin) {
for (var i = 0, j = 0, len = bin.length / 3, base64 = []; i < len; ++i) {
var a = bin.charCodeAt(j++), b = bin.charCodeAt(j++), c = bin.charCodeAt(j++);
if ((a | b | c) > 255) throw new Error("String contains an invalid character");
base64[base64.length] = table[a >> 2] + table[((a << 4) & 63) | (b >> 4)] +
(isNaN(b) ? "=" : table[((b << 2) & 63) | (c >> 6)]) +
(isNaN(b + c) ? "=" : table[c & 63]);
}
return base64.join("");
};
}
function hexToBase64(str) {
return btoa(String.fromCharCode.apply(null,
str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" "))
);
}
function base64ToHex(str) {
for (var i = 0, bin = atob(str.replace(/[ \r\n]+$/, "")), hex = []; i < bin.length; ++i) {
var tmp = bin.charCodeAt(i).toString(16);
if (tmp.length === 1) tmp = "0" + tmp;
hex[hex.length] = tmp;
}
return hex.join(" ");
}
function doConvert() {
var myHex = document.getElementById('myText').value;
var myBase64 = hexToBase64(myHex);
document.getElementById('myImage').src = "data:image/bmp;base64," + myBase64;
}
</script>
</head>
<body>
<div>
<p>
Enter Raw Hex:
<br>
<textarea rows="4" cols="50" id="myText">Enter Raw Hex String here ...</textarea>
<br>
<button id="myButton" onclick="doConvert()"> Click me </button>
<br>
<img id="myImage" alt="img1"/>
</p>
</div>
</body>
</html>
private static BufferedImage byte2Buffered(byte[] rawData, int width, int height){
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
byte[] array = ((DataBufferByte)image.getRaster().getDataBuffer()).getData();
System.arraycopy(rawData, 0, array, 0, rawData.length);
return image;
}
请注意,由于JavaScript中没有
buffereImage
类型,因此我们无法在JavaScript中等效此方法。在您的窗口.atob
方法中,您已经在从一个8位整数数组构建一个字符串(这就是bin[length]
正在创建的)。只需返回该数组而不是字符串
然后,如果必须支持较旧的浏览器,则需要将每个像素分别写入画布。但是,如果您可以针对现代浏览器,只需构建一个uint8clampedaray
,将其放入ImageData
对象,然后putImageData()
放入画布
下面是一些工作示例代码。我正在用随机字节(数据
)填充一个伪数组,但您将使用从atob
返回的字节数组
var canvas = document.querySelector('canvas'),
ctx = canvas.getContext('2d'),
width = canvas.width,
height = canvas.height,
pixelLength = width * height,
data,
imageData;
// You can use any kind of array, including a
// Uint8ClampedArray, since it is just going to be
// crammed into a clamped array anyway. I'm using a
// Uint8Array just as an example.
data = new Uint8Array(pixelLength);
// Create an array of random data
data = data.map(function (btye) { return Math.floor(Math.random() * 256); });
// The source data is 8-bit grayscale, but it needs
// to be 32-bit RGBA in a Uint8ClampedArray. The
// structure is simple. For every byte of the gray-
// scale array, write out three copies of that byte
// and then `256` as 100% opaque.
data = data.reduce(function (carry, current, index) {
var baseIndex = index * 4;
carry[baseIndex] = current;
carry[baseIndex + 1] = current;
carry[baseIndex + 2] = current;
carry[baseIndex + 3] = 256;
return carry;
}, new Uint8ClampedArray(pixelLength * 4));
// The Uint8ClampedArray can now be used to build the image
imageData = new ImageData(data, width, height);
ctx.putImageData(imageData, 0, 0);
你知道颜色编码吗?例如灰度或颜色?请记住,java和javascript是完全不同的语言。亲爱的@Matthieu,我的图像是灰度的,当然java与javascript是不同的。我绝对知道这个事实:)我告诉过我用java做过这个问题,我想用Javascript做(因为你说你以前用java做过),你知道文件的确切格式。鉴于此,您可以解码/解释文件头,并且您知道每个像素在输入格式中的表示方式。如果您已经知道这一点,那么应该能够将输入读取到bufferarray中,然后作为xIntTypedArrayBuffer读取。然后读取每个位并将其渲染到画布(或其他缓冲数组,在其中您将编码为另一种格式)。如果您只对将内容写入屏幕感兴趣,则无需担心图像编码;您只需将像素数据写入
canvas
元素即可——有关详细信息,请参阅。如果需要转码存储并在以后使用,请尝试使用或尝试ImageMagick的任何包装库(我还没有找到ImageMagick无法完成的处理任务)。在你的措辞中要特别注意生物特征存储法。请参阅。我在这里使用的是reduce
,而不是for()
循环。有关如何使用它的信息,请参阅,但可以使用for()
代替。亲爱的@Andrew我在IE11中发现了此错误:“uint8clampedaray”未定义。事实上,我有一个activeX(IE扩展)从智能卡读取原始图像,所以我需要基于IE的程序。虽然我有IE11,但我希望支持不支持HTML5的旧IE。[我编辑了此评论]您可以使用字节数组。我建议找到一个ActiveX绘图库,将数据bitbash转换成图像。亲爱的@Andrew,但我认为你的回答是一个非常好的方法,因为它在chrome和Firefox中运行得非常好,而且它只有一个错误:uint8clampedaray在IE中未定义。你知道activeX中的类型是受限的
,并且很麻烦。然后,正如我所说的,如果必须支持较旧的浏览器,则需要将每个像素分别写入画布。如果无法使用uint8clampedaray
,则可能无法使用putImageData()
,因此您可能必须使用的技术是绘制1x1像素的“矩形”,而不是写入像素。听起来很慢,但可能不是。此外,您可能会发现使用图形库(如Fabric.js、EaselJS、Paper.js等)更容易,因为它可以处理跨平台问题。我不能推荐一个胜过另一个。试试看你是怎么想的。