IWETHEY v. 0.3.0 | TODO
1,095 registered users | 0 active users | 0 LpH | Statistics
Login | Create New User
IWETHEY Banner

Welcome to IWETHEY!

New Creating images on the fly in client side JavaScript
I have a need to generate some raster images on a client browser using JavaScript - not using the server to generate the images. In investigating the matter, I see that you can [link|http://examples.oreilly.com/jscript2/14.2.txt|generate xbm files] on the fly and use the generated string to display in an image node. Seen some useful examples such as [link|http://builder.com.com/5100-6371-1050181.html?tag=s|dynamic barcodes] and [link|http://www.massmind.org/techref/language/java/script/xbmsample.htm|random numbers].

In my application, I've got a bunch of raster images being generated, that I'd like to display in the browser without need of a return trip the server. I can get the results I need shown in the sample code below. However, the method used requires constructing the complete xbm in a Javascript string beforehand. What I really would like is if the writing of the xbm file was somehow cached or buffered. Maybe a generator or somesuch.

Anyone used xbm file generation in JavaScript? And if so, have you found a way to lower the memory footprint?

Thanks. Sample code follows:
<html>\n<head>\n<title>Generate XBM Image From Client Side JavaScript</title>\n</head>\n<body>\n<script language='JavaScript' type='text/javascript'>\n<!--\n   // map the bitmap value into output string (note the nibble/octet swap)\n   HexMap = [\n      "0x00","0x10","0x20","0x30","0x40","0x50","0x60","0x70","0x80","0x90","0xa0","0xb0","0xc0","0xd0","0xe0","0xf0",\n      "0x01","0x11","0x21","0x31","0x41","0x51","0x61","0x71","0x81","0x91","0xa1","0xb1","0xc1","0xd1","0xe1","0xf1",\n      "0x02","0x12","0x22","0x32","0x42","0x52","0x62","0x72","0x82","0x92","0xa2","0xb2","0xc2","0xd2","0xe2","0xf2",\n      "0x03","0x13","0x23","0x33","0x43","0x53","0x63","0x73","0x83","0x93","0xa3","0xb3","0xc3","0xd3","0xe3","0xf3",\n      "0x04","0x14","0x24","0x34","0x44","0x54","0x64","0x74","0x84","0x94","0xa4","0xb4","0xc4","0xd4","0xe4","0xf4",\n      "0x05","0x15","0x25","0x35","0x45","0x55","0x65","0x75","0x85","0x95","0xa5","0xb5","0xc5","0xd5","0xe5","0xf5",\n      "0x06","0x16","0x26","0x36","0x46","0x56","0x66","0x76","0x86","0x96","0xa6","0xb6","0xc6","0xd6","0xe6","0xf6",\n      "0x07","0x17","0x27","0x37","0x47","0x57","0x67","0x77","0x87","0x97","0xa7","0xb7","0xc7","0xd7","0xe7","0xf7",\n      "0x08","0x18","0x28","0x38","0x48","0x58","0x68","0x78","0x88","0x98","0xa8","0xb8","0xc8","0xd8","0xe8","0xf8",\n      "0x09","0x19","0x29","0x39","0x49","0x59","0x69","0x79","0x89","0x99","0xa9","0xb9","0xc9","0xd9","0xe9","0xf9",\n      "0x0a","0x1a","0x2a","0x3a","0x4a","0x5a","0x6a","0x7a","0x8a","0x9a","0xaa","0xba","0xca","0xda","0xea","0xfa",\n      "0x0b","0x1b","0x2b","0x3b","0x4b","0x5b","0x6b","0x7b","0x8b","0x9b","0xab","0xbb","0xcb","0xdb","0xeb","0xfb",\n      "0x0c","0x1c","0x2c","0x3c","0x4c","0x5c","0x6c","0x7c","0x8c","0x9c","0xac","0xbc","0xcc","0xdc","0xec","0xfc",\n      "0x0d","0x1d","0x2d","0x3d","0x4d","0x5d","0x6d","0x7d","0x8d","0x9d","0xad","0xbd","0xcd","0xdd","0xed","0xfd",\n      "0x0e","0x1e","0x2e","0x3e","0x4e","0x5e","0x6e","0x7e","0x8e","0x9e","0xae","0xbe","0xce","0xde","0xee","0xfe",\n      "0x0f","0x1f","0x2f","0x3f","0x4f","0x5f","0x6f","0x7f","0x8f","0x9f","0xaf","0xbf","0xcf","0xdf","0xef","0xff"];\n\n   // image attributes\n   var myImageWidth  = 512;\n   var myImageHeight = 500;\n\n   // allocate array to hold each line of the raster image\n   var myImageArray  = new Array(myImageHeight);\n   for (var i = 0; i < myImageArray.length; i++) {\n      myImageArray[i] = new Array(Math.ceil(myImageWidth / 8));\n   }\n\n   // generate the bitmapped image in the array\n   // (for now fake image - all bits set)\n   for (var i = 0; i < myImageArray.length; i++) {\n      for (var j = 0; j < myImageArray[i].length; j++) {\n         myImageArray[i][j] = 0xFF;\n      }\n   }\n\n   // create the xbm file format string\n   var myImageString = [];\n   var k = 0;\n   for (var i = 0; i < myImageArray.length; i++) {\n      for (var j = 0; j < myImageArray[i].length; j++) {\n         myImageString[k++] = HexMap[myImageArray[i][j]];\n      }\n   }\n\n-->\n</script>\n   <img src='javascript:"#define cmr_width " + myImageWidth + "\\n" +\n      "#define cmr_height " + myImageHeight + "\\n" +\n      "#define cmr_x_hot -1\\n#define cmr_y_hot -1\\nstatic char cmr_bits[] = {\\n" +\n      myImageString.toString() + "};\\n"'>\n</body>\n</html>\n
Expand Edited by ChrisR March 8, 2004, 11:00:41 PM EST
Expand Edited by ChrisR March 8, 2004, 11:38:55 PM EST
New ???? wtf?
-drl
New Just trying to generate a dynamic image on the client
New with Javascript? (scratches head)
Admittedly this web stuff is so chaotic and bone-stupid that I have no real idea (nor care to) about what is worth a damn and what isn't. I do enjoy reading stories of experts at work.
-drl
New Admittedly, it's a hack
If you do it on the server, you can use practically any language to generate dynamic images - though you'd probably do gif or jpeg as the X-windows bitmap file format is rather inefficient.

But when you try to do the imaging on the client, your choices are rather limited - unless you're prepared to use the JVM or .Net, neither of which I've had too much on the client side.
Expand Edited by ChrisR March 8, 2004, 11:26:51 PM EST
New The only thing that leaps out at me...
You are generating myImageString with += of lots of pieces.

Every time you call += you have to create a new string and make the old one join garbage waiting for collection.

If the string is long then this is going to become very ineffient and be a lot of garbage.

Where you accumulate in the double-loop, try to add to an array in the inner loop, then join the array into another array in the outer loop, and then join that array once at the end.

It might or might not solve the memory problem, but it will definitely help performance.

Cheers,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New Not sure I follow your recomendation
For sure, the example I gave is gonna have way to much garbage from the string concatenation. I redid the mapping algorithm but I still have the overall problem of generating lots of garbage in the main loop:

Are you saying it should be changed to something like:

   for (var i = 0; i < myImageArray.length; i++) {\n      tempStr = "";\n      for (var j = 0; j < myImageArray[i].length; j++) {\n         tempStr += HexMap[myImageArray[i][j]];\n      }\n      myImageString += tempStr;\n   }


Thanks.
New Nevermind, I think I see what you are saying
It is much faster now (see original posts & history), in that I just allocate a new array element in the loop and then use the toString method to convert the entire array to a string with commas in between each element.

Thanks. I'd still like to find a method whereby the src url is an input stream or generator function, instead of building the xbm array in memory.
New You almost have it...
You are building up the entire output array and then joining it. I was suggesting doing that incrementally. Like this (untested):\r\n
\r\n   var myImageString = [];\r\n   for (var i = 0; i < myImageArray.length; i++) {\r\n      var myImageThisRow = [];\r\n      for (var j = 0; j < myImageArray[i].length; j++) {\r\n         myImageThisRow.push(HexMap[myImageArray[i][j]]);\r\n      }\r\n      // Reduce the number of objects to be nice on gc\r\n      myImageString.push(myImageThisRow.toString());\r\n   }\r\n
\r\nPast experience with large JavaScript datastructures tells me that while you'll thrash a lot less than when you create tons of garbage, the garbage collector still thrashes on lots of small objects that aren't to be collected. (It keeps on figuring out what it can collect..and finds nothing.) The above strategy keeps the number of objects that it wants to handle under control.

\r\n\r\nAs for not building it in memory, I wish that I knew how to do that, but I don't. I only know how to speed things up slightly.

\r\n\r\nCheers,
\r\nBen
"good ideas and bad code build communities, the other three combinations do not"\r\n- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
New Gettin in Tune
I see the push method is better at managing memory than simply adding onto the array.

Much Much faster now by orders of magnitude. Thanx.
New It isn't the push that made the difference
I just did that to reduce bookkeeping in the code.

The problem is that as you use lots of memory, you trigger frequent garbage collection runs. If there are lots of small objects, those runs take a long time. So you are spending a lot of CPU looking for garbage that isn't there.

Switching from having a very large number of small objects to just having a bunch of large objects and another bunch more small ones doesn't materially effect how often it runs garbage collection, but it does make a garbage collection (at least with some allocators) run much faster because it has fewer objects to look at until it decides that there is no garbage to eliminate.

It isn't an obvious thing to do to tune performance, unless you've faced the same problem before. (Which I have.)

Cheers,
Ben
"good ideas and bad code build communities, the other three combinations do not"
- [link|http://archives.real-time.com/pipermail/cocoon-devel/2000-October/003023.html|Stefano Mazzocchi]
     Creating images on the fly in client side JavaScript - (ChrisR) - (10)
         ???? wtf? -NT - (deSitter) - (3)
             Just trying to generate a dynamic image on the client -NT - (ChrisR) - (2)
                 with Javascript? (scratches head) - (deSitter) - (1)
                     Admittedly, it's a hack - (ChrisR)
         The only thing that leaps out at me... - (ben_tilly) - (5)
             Not sure I follow your recomendation - (ChrisR)
             Nevermind, I think I see what you are saying - (ChrisR) - (3)
                 You almost have it... - (ben_tilly) - (2)
                     Gettin in Tune - (ChrisR) - (1)
                         It isn't the push that made the difference - (ben_tilly)

Unfortunately, with great ambition comes great shit hitting the fan.
84 ms