1
\$\begingroup\$

I wrote a tool to store text as colors in a image around the border. I then saved the resulting image to file. To use the resulting file I set it's path to a the src attribute of a tag and call DrawImage and colorToText OnLoad to read the contents and remove the messy data around the edges of the image, thereby presenting a image that doesn't show the data that is embedded in it. I do this by modifying the alpha to 0 when reading each pixel and only calling putImageData 1 time to write the resulting change to desired location. Presented here is this code:

<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="200" height="200" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<p id="Start"></p>
<p id="End"></p>
<script>
var ColorizeData = function(canvas) {
    this.canvas = canvas;
    this.charToHexTable = {};
    this.hexToCharTable = {};
}
ColorizeData.prototype.initTables = function(){
    var charHexPairs = [
        ["a" , "#000010"],
        ["b" , "#000020"],
        ["c" , "#000030"],
        ["d" , "#000040"],
        ["e" , "#000050"],
        ["f" , "#000060"],
        ["g" , "#000070"],
        ["h" , "#000080"],
        ["i" , "#000090"],
        ["j" , "#0000a0"],
        ["k" , "#0000b0"],
        ["l" , "#0000c0"],
        ["m" , "#0000d0"],
        ["n" , "#0000e0"],
        ["o" , "#0000f0"],
        ["p" , "#001000"],
        ["q" , "#002000"],
        ["r" , "#003000"],
        ["s" , "#004000"],
        ["t" , "#005000"],
        ["u" , "#006000"],
        ["v" , "#007000"],
        ["w" , "#008000"],
        ["x" , "#009000"],
        ["y" , "#00a000"],
        ["z" , "#00b000"],
        [" " , "#00c000"],
        ["  " , "#00c0f0"],
        ["-" , "#00d000"],
        ["," , "#00d0f0"],
        ["=" , "#00e000"],
        ["." , "#00f000"],
        ["0" , "#100000"],
        ["1" , "#200000"],
        ["2" , "#300000"],
        ["3" , "#400000"],
        ["4" , "#500000"],
        ["5" , "#600000"],
        ["6" , "#700000"],
        ["7" , "#800000"],
        ["8" , "#900000"],
        ["9" , "#a00000"]
    ];
    var i, pair, char, hex;
    for(i=0; i < charHexPairs.length; i++)
    {
            pair = charHexPairs[i];
            char = pair[0];
            hex = pair[1];
            this.charToHexTable[char] = hex;
            this.hexToCharTable[hex] = char;
    }
}

ColorizeData.prototype.textToColor = function(arg){
    var context = this.canvas.getContext("2d");
    context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    var index;
    var upDown = 1;
    var upDown1 = 1;
    var leftRight = 0;
    arg = arg.toLowerCase();
    for(index = 0;index<arg.length;index++)
    {
        var prop = arg.charAt(index);
        if(this.charToHexTable.hasOwnProperty(prop))
        {
            context.fillStyle = this.charToHexTable[prop] ; 
        }
        else
        {
            context.fillStyle = "#000000";
        }
        if(index < this.canvas.width) {
            context.fillRect(index, 0, 1, 1);
            leftRight = index;
        }
        else
        {   
            if(upDown < this.canvas.height) {
                context.fillRect(leftRight,upDown,1,1);
                upDown += 1;
            }
            else
            {
                if(upDown1 < this.canvas.height) {
                    leftRight = 0
                    context.fillRect(leftRight,upDown1,1,1);
                    upDown1 +=1
                }
                else
                {
                    if(leftRight < this.canvas.width -2) {
                        leftRight+= 1;
                        context.fillRect(leftRight,upDown1-1,1,1);
                    }
                }
            }
        }
    }
}
function componentToHex(c) {
    var hex = c.toString(16);
    return hex.length == 1 ? "0" + hex : hex;
}
function rgbToHex(r, g, b) {
    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
ColorizeData.prototype.colorToText = function(arg) 
{
    var text = "";
    var context = this.canvas.getContext("2d");
    var size = 0;
    for(var index = 0;index<4;index+= 1)
    {
        if(index == 0) {
            imgData = context.getImageData(0,0, this.canvas.width,1);
            size = this.canvas.width;
        }
        else
        {
            if(index == 1) {
                imgData = context.getImageData(this.canvas.width - 1,1, 1,this.canvas.height - 1);
                size = this.canvas.height - 1;
            }
            else
            {
                if(index == 2) {
                    imgData = context.getImageData(0,1, 1,this.canvas.height - 1);
                    size = this.canvas.height - 1;
                }
                else
                {   
                    imgData = context.getImageData(1,this.canvas.height -1, this.canvas.width-2, 1);
                    size = this.canvas.width-2;

                }
            }
        }
        for( var i = 0;i < size*4;i+=4) {
            var r = imgData.data[i+0];
            var g = imgData.data[i+1];
            var b = imgData.data[i+2];         
            var hex = rgbToHex(r, g, b);
            imgData.data[i+3] = 0;
            if(this.hexToCharTable.hasOwnProperty(hex))
            {
                text += this.hexToCharTable[hex];
            }
        }
        if(index == 0){ 
            context.putImageData(imgData,0,0);
        }
        if(index == 1) {
            context.putImageData(imgData,this.canvas.width-1,1);
        }
        if(index == 2) {
            context.putImageData(imgData,0,1);
        }
        if(index == 3) {
            context.putImageData(imgData,1,this.canvas.height -1);
        }
    }
    var dataStruct = "GTIN #,GTIN Name,Target Market,Information Provider GLN,Language,Published Node,Parent Node,Hierarchy Level,Link Quantity,Product Type,Brand Owner GLN,Brand Name,Qty of Next Level Item(s),Inner Pack,Net Content 1,Net Content UOM 1,Net Content 2,Net Content UOM 2,Packaging Type,Product Form,GPC Classification Code,Storage/Handling Temp Max,Storage/Handling Temp Min,Storage/Handling Temp UOM,Number of Complete Layers Contained in Item/GTIN Pallet Hi,Number of Items in a Complete Layer/GTIN Pallet Ti,Number of Items/Pallet,Variable Weight Trade Item,Base Unit Indicator,Consumer Unit Indicator,Own Label/Private Label,Manufacturer GLN,Manufacturer Name,EANUCC Code,EANUCC Type,Sub Brand,Functional Name,Variant,Product Description,Dispatch Unit Indicator,Invoice Unit Indicator,Pricing on Product,Ordering Unit Indicator,Dangerous Goods Indicator,Has Batch Number,Net Content Declared,Material Safety Data Sheet Number,Replaced by GTIN,Replaces GTIN,Alternate Item Classification Scheme,Alternate Item Classification Code,More Alternate Item Classification,Country of Origin,More Country of Origin,Primary Delivery Method,Alternate Item Identification Maintenance Agency,Alternate Item Number,More Alternate Item Number,Volume,Volume UOM,Depth,Depth UOM,Height,Height UOM,Width,Width UOM,Diameter,Diameter UOM,Gross Weight,Gross Weight UOM,Packaging Material Composition,Packaging Material Composition UOM,Net Weight,Net Weight UOM,Drained Weight,Drained Weight UOM,Non GTIN Pallet Height,Non GTIN Pallet Height UOM,Non GTIN Pallet Gross Weight,Non GTIN Pallet Gross Weight UOM,Peg Horizontal,Peg Horizontal UOM,Peg Vertical,Peg Vertical UOM,Peg Hole Number,Percentage of Alcohol per Volume,Product Color Description,Color,Color Code Maintenance Agency,Product Strength,Product Strength UOM,Product Strength Basis,Product Strength Basis UOM,Number of Layers Per Pallet/Non GTIN Pallet Hi,Number of Trade Items Per Pallet Layer/Non GTIN Pallet Ti,Handling Instruction Code,Max Stacking Weight,Max Stacking Weight UOM,Stacking Factor,Order Sizing Factor,Order Sizing Factor UOM,Pallet Code,Pallet Terms and Conditions,Start Availability Date,End Availability Date,Lead Time,Lead Time UOM,Last Ship Date,First Ship Date,Last Arrival Date,First Arrival Date,Min Product Lifespan from Production,Order Quantity Multiple,Min Order Quantity,Max Order Quantity,Trade Item Group Code,Trade Item Group Description,Coupon Family Code,Packaging Material Code,Material Code Agency,Product Size Code,Product Size Code Maintenance Agency,Descriptive Size,Short Description / POS Desc. 1,Product PLU Description,Image Thumbnail Path,Image Thumbnail File Name,Additional Description,Tax Rate,Tax Type Code,Tax Type Agency,Tax Type Description,List Price,List Price Basis Per Unit,List Price Basis UOM,List Price Currency,Suggested Retail Price,Suggested Retail Price per Unit,Suggested Retail Price Basis UOM,Suggested Retail Price Currency,Packaging Marked Returnable,Product Marked Recyclable,Product Marked with Ingredients ,Right of Return for Non-Sold Trade Item,Customs Classification Code,Green Dot Indicator,Dangerous Goods Class Code,Dangerous Goods Hazardous Code,Dangerous Goods Regulation Code,Flash Point Temperature,Flash Point Temperature UOM,U.N. Dangerous Goods Number,Dangerous Goods Shipping Name,Dangerous Goods A Margin Number,Dangerous Goods Packing Group,Dangerous Goods Technical Name,Hazmat Special Instructions,More HazMat,Package Group,Product Group,Pricing UPC,Pricing Item Indicator ,Units Per Consumer Unit,Total Units Per Case,Pricing Pack,Last Modified Date,Create Date,GDSN Registration Date,GDSN Registry Progress,GDSN Registry Status,Cancel Date,Discontinued Date,Special Item Code,Deposit Value Start Date,Deposit Value End Date,Terms or Conditions Code,Returnable Package Deposit Amount,Returnable Package Deposit Amount Currency,Returnable Package Deposit Code,Attribute Qualifier (1),Attribute Value (1),Attribute Qualifier (2),Attribute Value (2),Attribute Qualifier (3),Attribute Value (3),Attribute Qualifier (4),Attribute Value (4),Attribute Qualifier (5),Attribute Value (5),Attribute Qualifier (6),Attribute Value (6),Attribute Qualifier (7),Attribute Value (7),Attribute Qualifier (8),Attribute Value (8),Attribute Qualifier (9),Attribute Value (9),Attribute Qualifier (10),Attribute Value (10),Attribute Qualifier (11),Attribute Value (11),Attribute Qualifier (12),Attribute Value (12),Attribute Qualifier (13),Attribute Value (13),Attribute Qualifier (14),Attribute Value (14),Attribute Qualifier (15),Attribute Value (15),Attribute Qualifier (16),Attribute Value (16),Attribute Qualifier (17),Attribute Value (17),Attribute Qualifier (18),Attribute Value (18),Attribute Qualifier (19),Attribute Value (19),Attribute Qualifier (20),Attribute Value (20),More Attributes";
    Attributes = text.split(",");
    data = dataStruct.split(",");
    var body = document.body;
    var tbl  = document.createElement('table');
    tbl.style.width  = '100px';
    tbl.style.border = "1px solid black";
    for(var x = 0;x < 220;x++) {
    if(Attributes[x] != "" && Attributes[x] != undefined) {
            var tr = tbl.insertRow();
            var td = tr.insertCell();
            var td1 = tr.insertCell();
            td.appendChild(document.createTextNode(data[x]));
            td.style.border = "1px solid black";
            td1.appendChild(document.createTextNode(Attributes[x]));
            td1.style.border = "1px solid black";               
        }
    }
    body.appendChild(tbl);
}
ColorizeData.prototype.loadImage = function(arg) {
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
    var img = new Image();
    img.onload = function () {
        context.drawImage(img, 0, 0, 200, 200);
        Colorizer.colorToText('End');
    };
    img.src = arg;
}
ColorizeData.prototype.clear = function() {
    var context = this.canvas.getContext("2d");
    context.clearRect(0,0,this.canvas.width, this.canvas.height);
}
var Colorizer = new ColorizeData(document.getElementById("myCanvas"));
Colorizer.initTables();
Colorizer.loadImage('download.png');

</script>
</body>
</html>

download.png can be found here.

I have tested this with IE, Chrome and Firefox, Chrome is the only one that requires further setup operations for this to be able to work so far. chrome --disable-web-security is the least favored way and chrome --allow-file-access-from-files --allow-file-access --allow-cross-origin-auth-prompt the latter looks like the better of the 2 options, IMHO.

Any coding or other improvements will be greatly appreciated!!

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

In this code:

var i, pair, char, hex;
for(i=0; i < charHexPairs.length; i++)
{
        pair = charHexPairs[i];
        char = pair[0];
        // ...

There's no need to declare the variables in advance. In fact it's best to declare variables in the smallest scope possible, to avoid accidental misuses. So the above would be better this way:

for(var i=0; i < charHexPairs.length; i++)
{
        var pair = charHexPairs[i];
        var char = pair[0];
        // ...

This doesn't look so good:

var upDown = 1;
var upDown1 = 1;

These two variables have too similar names and can be easy to confuse. In general, try to avoid using numbers in variable names.


for(index = 0;index<arg.length;index++)
// ...
context.fillRect(leftRight,upDown,1,1);

It would be better to use spaces around operators and after semicolons and commas more generously, like this:

for (index = 0; index < arg.length; index++)
// ...
context.fillRect(leftRight, upDown, 1, 1);

It's more common and simpler to use ++upDown instead of upDown += 1.


This nested else-if chain is very unusual:

if(index == 0) {
    imgData = context.getImageData(0,0, this.canvas.width,1);
    size = this.canvas.width;
}
else
{
    if(index == 1) {
        imgData = context.getImageData(this.canvas.width - 1,1, 1,this.canvas.height - 1);
        size = this.canvas.height - 1;
    }
    else
    {
        if(index == 2) {
            imgData = context.getImageData(0,1, 1,this.canvas.height - 1);
            size = this.canvas.height - 1;
        }
        else
        {   
            imgData = context.getImageData(1,this.canvas.height -1, this.canvas.width-2, 1);
            size = this.canvas.width-2;

        }
    }
}

This is equivalent but simpler:

    if(index == 0) {
        imgData = context.getImageData(0,0, this.canvas.width,1);
        size = this.canvas.width;
    } else if(index == 1) {
        imgData = context.getImageData(this.canvas.width - 1,1, 1,this.canvas.height - 1);
        size = this.canvas.height - 1;
    } else if(index == 2) {
        imgData = context.getImageData(0,1, 1,this.canvas.height - 1);
        size = this.canvas.height - 1;
    } else {   
        imgData = context.getImageData(1,this.canvas.height -1, this.canvas.width-2, 1);
        size = this.canvas.width-2;
    }

But the most natural way when doing different action depending on a value is using a switch:

switch (index) {
    case 0:
        imgData = context.getImageData(0,0, this.canvas.width,1);
        size = this.canvas.width;
        break;
    case 1:
        imgData = context.getImageData(this.canvas.width - 1,1, 1,this.canvas.height - 1);
        size = this.canvas.height - 1;
        break;
    case 2:
        imgData = context.getImageData(0,1, 1,this.canvas.height - 1);
        size = this.canvas.height - 1;
        break;
    default:
        imgData = context.getImageData(1,this.canvas.height -1, this.canvas.width-2, 1);
        size = this.canvas.width - 2;
}

This is even worse than the point earlier, because it's inefficient, evaluating multiple conditions in sequence, even though only one of them can be true:

if(index == 0){ 
    context.putImageData(imgData,0,0);
}
if(index == 1) {
    context.putImageData(imgData,this.canvas.width-1,1);
}
if(index == 2) {
    context.putImageData(imgData,0,1);
}
if(index == 3) {
    context.putImageData(imgData,1,this.canvas.height -1);
}

Rewrite this using a switch as in the previous point.


Capitalized names are usually used for classes, since this is just an array, I suggest to rename to lowercase:

Attributes = text.split(",");
\$\endgroup\$
3
  • \$\begingroup\$ Thank you for the valued input. I will do all of the suggested improvements and repost the result. thank you! \$\endgroup\$ Jan 26, 2015 at 19:16
  • \$\begingroup\$ Just make sure to post in a different question, don't update the code in this one! \$\endgroup\$
    – janos
    Jan 26, 2015 at 19:18
  • \$\begingroup\$ Is there a coding Ideas stackexchange? \$\endgroup\$ Jan 27, 2015 at 1:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.