Conversion d'une chaîne hexadécimal d'une image brute en image bitmap en JavaScript

Introduction :

Je lis les données d'image des empreintes digitales à partir de la carte à puce et, comme vous le savez, ces données sont enregistrées sous forme d'image brute dans la carte à puce. Je développe un programme côté client qui n'utilise que le script java pour lire l'image à partir du scanner d'un lecteur de carte et montrer que dans la page client.

Maintenant, ma question:

Comment puis-je convertir une chaîne hexadécimale de mes données brutes en une chaîne hexagonale qui a été réalisée avec l'en-tête approprié de l'image bitmap? Notez que j'ai la width et la height de mon image.

Méthodes essayées:

J'ai développé ce programme dans java en obtenant une image tampon à partir de données brutes . En outre, je pourrais convertir une chaîne hexadécimal d'une image de carte bitmap en base64 par Hex2Base64 et puis je pourrais montrer la chaîne base64 dans une balise image par base64AsImage . Cependant, ces fonctions fonctionnent bien si et seulement si l'hex contient un en-tête, alors que nos données sont brutes.

Mon code (qui ne fonctionne que pour Hex String qui contient l'en-tête):

 <!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> 

Une partie du code qui résout le problème dans java:

 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; } 

Notez que, comme il n'y a pas de type BufferedImage dans JavaScript, nous ne pourrions pas équivalent à cette approche en JavaScript.

Dans votre méthode window.atob , vous window.atob une chaîne à partir d'un ensemble d'entiers 8 bits (c'est ce que bin[length] crée.) Retournez ce tableau au lieu de la chaîne.

Ensuite, si vous devez supporter d'anciens navigateurs, vous devrez écrire chaque pixel sur le canevas individuellement. Mais si vous pouvez cibler des navigateurs modernes, il suffit de créer un Uint8ClampedArray , de le mettre dans un objet putImageData() et putImageData() dans le canevas.

Voici un exemple de code d'exemple. Je remplis un tableau fictif avec des octets aléatoires ( data ), mais vous utiliserez le tableau d'octets renvoyé par 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);