1 jls.loader.provide('jls.util.Image'); 2 3 jls.loader.requireLibrary('jls_jpeg'); 4 5 jls.loader.require('jls.io.File'); 6 jls.loader.require('jls.io.FileChannel'); 7 8 jls.util.Image = jls.lang.Class.create( /** @lends jls.util.Image.prototype */ 9 { 10 /** 11 * Creates an image. 12 * 13 * @param {Number} width The image width. 14 * @param {Number} height The image height. 15 * @param {Number} [mode] The image mode. 16 * @constructs 17 * @class This class represents an image 18 */ 19 initialize : function(width, height, mode) { 20 this._width = width; 21 this._height = height; 22 this._bitPerPixel = 24; 23 this._bytePerPixel = 3; 24 this._rowLength = (this._width * this._bitPerPixel) / 8; 25 if (this._rowLength % 4 != 0) { 26 this._rowLength = this._rowLength + 4 - this._rowLength % 4; 27 } 28 this._size = this._rowLength * this._height; 29 this._buffer = jls.lang.ByteBuffer.allocate(this._size); 30 mode = mode || 0; 31 this._mode = mode; 32 }, 33 /** 34 * Returns the image width. 35 * 36 * @returns {Number} The image width. 37 */ 38 getWidth : function() { 39 return this._width; 40 }, 41 /** 42 * Returns the image height. 43 * 44 * @returns {Number} The image height. 45 */ 46 getHeight : function() { 47 return this._height; 48 }, 49 /** 50 * Returns the image buffer. 51 * 52 * @returns {jls.lang.Buffer} The image buffer. 53 */ 54 getBuffer : function() { 55 return this._buffer; 56 }, 57 _moveTo : function(x, y) { 58 var offset = this._rowLength * y + this._bytePerPixel * x; 59 this._buffer.setPosition(offset); 60 return this; 61 }, 62 /** 63 * Returns a pixel value. 64 * 65 * @param {Number} x The x coordinate of the pixel. 66 * @param {Number} y The y coordinate of the pixel. 67 * @returns {Array} The pixel value. 68 */ 69 getPixel : function(x, y) { 70 this._moveTo(x, y); 71 var p = []; 72 p.push(this._buffer.getByte()); 73 p.push(this._buffer.getByte()); 74 p.push(this._buffer.getByte()); 75 return p; 76 }, 77 /** 78 * Sets a pixel. 79 * 80 * @param {Number} x The x coordinate of the pixel. 81 * @param {Number} y The y coordinate of the pixel. 82 * @param {Number} r The red value to set. 83 * @param {Number} g The green value to set. 84 * @param {Number} b The blue value to set. 85 */ 86 setPixel : function(x, y, r, g, b) { 87 this._moveTo(x, y); 88 this._buffer.putByte(r); 89 this._buffer.putByte(g); 90 this._buffer.putByte(b); 91 return this; 92 } 93 }); 94 95 /* 96 typedef struct tagBITMAPFILEHEADER { 97 WORD bfType; 2 98 DWORD bfSize; 4 99 WORD bfReserved1; 2 100 WORD bfReserved2; 2 101 DWORD bfOffBits; 4 102 } BITMAPFILEHEADER, *PBITMAPFILEHEADER; = 14 103 104 typedef struct tagBITMAPCOREHEADER { 105 DWORD bcSize; 106 WORD bcWidth; 107 WORD bcHeight; 108 WORD bcPlanes; 109 WORD bcBitCount; 110 } BITMAPCOREHEADER, *PBITMAPCOREHEADER; = 12 111 112 typedef struct tagBITMAPINFOHEADER { 113 DWORD biSize; 114 LONG biWidth; 115 LONG biHeight; 116 WORD biPlanes; 117 WORD biBitCount; 118 DWORD biCompression; 119 DWORD biSizeImage; 120 LONG biXPelsPerMeter; 121 LONG biYPelsPerMeter; 122 DWORD biClrUsed; 123 DWORD biClrImportant; 124 } BITMAPINFOHEADER, *PBITMAPINFOHEADER; = 9*4 + 2*2 = 40 125 */ 126 127 Object.extend(jls.util.Image, /** @lends jls.util.Image */ 128 { 129 /** 130 * Reads a BMP. 131 * 132 * @param {jls.io.FileInputStream} input The input to read the image. 133 * @returns {jls.util.Image} The image. 134 */ 135 readBMP : function(input) { 136 /*var dumpObj = function(obj) { 137 for (var key in obj) { 138 if (typeof obj[key] == 'function') continue; 139 jls.logger.debug('obj.' + key + ': ' + obj[key]); 140 } 141 };*/ 142 /*var dumpNum = function(num) { 143 jls.logger.debug('num: ' + num + ' (0x' + num.toString(16) + ')'); 144 };*/ 145 var buffer = jls.lang.ByteBuffer.allocate(1024); 146 buffer.setByteOrder(jls.lang.Buffer.LITTLE_ENDIAN); 147 148 buffer.clear(); 149 buffer.setLimit(14); 150 input.read(buffer); 151 buffer.flip(); 152 //var typeStr = buffer.getString(2); 153 //jls.logger.debug('type: "' + typeStr + '"'); 154 var typeStr = buffer.getShort(); 155 var size = buffer.getInt(true); 156 //dumpNum(size); 157 buffer.incrementPosition(4); 158 var offBits = buffer.getInt(true); 159 //dumpNum(offBits); 160 161 buffer.clear(); 162 buffer.setLimit(offBits - 14); 163 input.read(buffer); 164 buffer.flip(); 165 166 var sSize = buffer.getInt(true); 167 //dumpNum(sSize); 168 var width, height, planes, bitCount; 169 if (sSize == 12) { 170 width = buffer.getShort(true); 171 height = buffer.getShort(true); 172 planes = buffer.getShort(true); 173 bitCount = buffer.getShort(true); 174 } else if (sSize == 40) { 175 width = buffer.getInt(true); 176 height = buffer.getInt(true); 177 planes = buffer.getShort(true); 178 bitCount = buffer.getShort(true); 179 } else { 180 throw 'Invalid BMP (' + sSize + ')'; 181 } 182 jls.logger.debug('BMP: ' + width + ', ' + height + ', ' + planes + ', ' + bitCount); 183 var img = new jls.util.Image(width, height); 184 input.read(img.getBuffer()); 185 return img; 186 }, 187 /** 188 * Reads a JPEG. 189 * 190 * @param {jls.io.FileInputStream} input The input to read the image. 191 * @returns {jls.util.Image} The image. 192 */ 193 readJPEG : function(input) { 194 var jdecompressor = new _native.jpeg.JpegDecompressor(); 195 var buffer = jls.lang.ByteBuffer.allocate(40000); 196 /** @ignore */ 197 var srcMgr = { 198 sourceBuffer : buffer, 199 sourceByteArray : buffer._barray, 200 sourceCapacity : buffer.capacity(), 201 sourceOffset : 0, 202 initSource : function() { 203 jls.logger.debug('initSource()'); 204 }, 205 fillSource : function() { 206 jls.logger.debug('fillSource()'); 207 //this.sourceCapacity = file.read(this.sourceByteArray, this.sourceOffset, this.sourceByteArray.size() - this.sourceOffset); 208 this.sourceBuffer.clear(); 209 this.sourceBuffer.setPosition(this.sourceOffset); 210 jls.logger.debug('sourceOffset: ' + this.sourceOffset); 211 //this.sourceBuffer.setLimit(this.sourceBuffer.capacity()); 212 this.sourceCapacity = input.read(this.sourceBuffer); 213 jls.logger.debug('sourceCapacity: ' + this.sourceCapacity); 214 }, 215 skipSource : function(count) { 216 jls.logger.debug('skipSource(' + count + ')'); 217 // TODO 218 }, 219 termSource : function() { 220 jls.logger.debug('termSource()'); 221 } 222 }; 223 jdecompressor.start(srcMgr); 224 var width = jdecompressor.getWidth(); 225 var height = jdecompressor.getHeight(); 226 var components = jdecompressor.getComponents(); 227 jls.logger.debug('JPEG: ' + width + ', ' + height + ', ' + components); 228 var img = new jls.util.Image(width, height); 229 jdecompressor.read(img.getBuffer()._barray, -1); 230 jdecompressor.finish(); 231 _native.jpeg.swapRGB(img.getBuffer()._barray, width, height); 232 return img; 233 } 234 }); 235 236