Q955 Can I manipulate images a pixel at a time?

irt.org logo [Original Page]

JavaScript 1.0 and 1.1 has no ability to support byte 0 (null) within a string.

Therefore you cannot 'create' images that require \0, even if they can be specified using ascii characters. The only images that you can create are XBM images which are only black or white. (Looks more like black and transparent to me, IE5.50 - pk)

Here is an example of an XBM image. It script creates a one pixel by one pixel XBM image, which it then uses to inform you of the size of the document.

<body onLoad="init()">

<script language="JavaScript"><!--
var single_pixel_xbm =
   "#define x_width 1\n#define x_height 1\nstatic char x_bits = {0x00};\n";
function init() {
  var stn = "width = " + document.images[0].width + "\n";
  stn    += "height = " + document.images[0].height
  alert(stn);
}
//--></script>

<img src="javascript:single_pixel_xbm" width="100%" height="100%">

The following example demonstrates image creating and manipulation:

<html>
<head>
<script language="JavaScript"><!--
var image1 = '#define x_width 16\n#define x_height 16\nstatic char x_bits[] = {\n' +
' 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, ' +
'0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, ' +
'0x55, 0x55, 0x55, 0x55, 0x55, 0x55};\n';

var image2 = '#define x_width 16\n#define x_height 16\nstatic char x_bits[] = {\n' +
' 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, ' +
'0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, ' +
'0xff, 0xff, 0x00, 0x00, 0xff, 0xff};\n';
//--></script>
</head>

<body>

<img name="myImage" src="javascript:image1" width="16" height="16">

<form>
<input type="button" onClick="if (document.images) myImage.src='javascript:image1'"
     value="Show Image 1">
<input type="button" onClick="if (document.images) myImage.src='javascript:image2'"
     value="Show Image 2">
</form>

</body>
</html>

pk - The above is interesting and makes it seem like I can get to building up a simple graph, but for now at least I can not figure out how he got vertical bars out of the first image1 block of data, about 32 bytes. With an area defined as height 16 and width 16 which should be 16 X 16 or 256 bytes.

In JavaScript 1.2, the following can be achieved (tested in JavaScript 1.2 in Netscape Navigator 4.5 on GNU/Linux):

<script language="JavaScript"><!--
gif = 'GIF87a \0\20\0\200\0\0\0\0\0\377\377\377,\0\0\0\0 \0\20'+
      '\0\0\2 \214\217\251\313\355\17\243D\240\326\11\1\236zG\333y\231'+
      '8\222J\30\232\7\252\236W\13\307\362\274\25\0;';
//--></script>

<img name="myImage" src="javascript:gif" width="32" height="32">

I suspect that the above will still cause older browsers to crash. (Not only that, but it doesn't seem to work at all in IE5.50 - pk)

If you need to place the image in another window, then rather than using document.open('image/gif'), which causes the browser to crash, use something like:

<script language="JavaScript"><!--
gif = 'GIF87a \0\20\0\200\0\0\0\0\0\377\377\377,\0\0\0\0 \0\20'+
      '\0\0\2 \214\217\251\313\355\17\243D\240\326\11\1\236zG\333y\231'+
      '8\222J\30\232\7\252\236W\13\307\362\274\25\0;';

windowHandle = window.open('about:blank','windowName','width=100,height=100');
if (!windowHandle.opener)
    windowHandle.opener = self;
windowHandle.document.open();
windowHandle.document.write('<img name="myImage" src="javascript:opener.gif"
      width="100" height="100">');
windowHandle.document.close();
//--></script>

The previous image is created using the following JavaScript to define the image source:

<script language="JavaScript"><!--
gif1 = 'GIF87a \0\20\0\200\0\0\0\0\0\377\377\377,\0\0\0\0 \0\20\0\0\2 \
        214\217\251\313\355\17\243D\240\326\11\1\236zG\333y\2318\222J\3
        0\232\7\252\236W\13\307\362\274\25\0;';
//--></script>

On the latest browsers this should render as a black number 5 on a white background. The image source was given to me by someone on usenet. (No, nothing at all here, IE5.50 - pk)

Saving the source of the above image to disk and then loading the image into a hex editor reveals something that looks similar to:

00000000  4749 4638 3761 2000 1000 8000 0000 0000  GIF87a ... .....
00000010  FFFF FF2C 0000 0000 2000 1000 0002 208C  ÿÿÿ,.... .....
00000020  8FA9 CBED 0FA3 44A0 D609 019E 7A47 DB79  ©Ëí. £D Ö.. zGÛy
00000030  9938 924A 189A 07AA 9E57 0BC7 F2BC 1500   8 J. .ª W.Çò¼..
00000040  3B0A                                     ;...............

Therefore, one could assume that the hex data that makes up the image is:

47494638376120001000800000000000FFFFFF2C00000000200010000002208C8FA9CBED0FA344A0D609
019E7A47DB799938924A189A07AA9E570BC7F2BC15003B0A

Using JavaScript, we can attempt to store this data as a string, and then convert it to the format similar to the one used in the first example.

<script language="JavaScript"><!--
function binary(d) {
    var o = '';
    for (var i=0; i<d.length; i=i+2)
       o += String.fromCharCode(eval('0x'+(d.substring(i,i+2)).toString(16)));
    return o;
}

gif2 = binary('47494638376120001000800000000000FFFFFF2C00000000200010000002208C8FA9C
               BED0FA344A0D609019E7A47DB799938924A189A07AA9E570BC7F2BC15003B0A');
//--></script>
(No, this didn't work either - checked in help203A.htm - pk)

And then used as:

<img src="javascript:gif2"> or
<img src="javascript:binary('47494638376120001000800000000000ffffff2c000000002000
                             10000002208c8fa9cbed0fa344a0d609019e7a47db799938924a
                             189a07aa9e570bc7f2bc15003b0a')">
(Neither did this - checked in help203A.htm - pk)