1 /** 2 * @namespace 3 */ 4 var ImageData = {}; 5 6 ImageData.fliph = function(imageData) 7 { 8 var p = imageData.data; 9 var w = imageData.width; 10 var h = imageData.height; 11 var tmp; 12 for(var y = 0; y < h; y++){ 13 for(var x = 0; x < w/2; x++){ 14 var i1 = (x + y*w)*4; 15 var i2 = ((w-1-x) + y*w)*4; 16 // swap red 17 tmp = p[i1+0]; 18 p[i1+0] = p[i2+0]; 19 p[i2+0] = tmp; 20 // swap red 21 tmp = p[i1+1]; 22 p[i1+1] = p[i2+1]; 23 p[i2+1] = tmp; 24 // swap green 25 tmp = p[i1+2]; 26 p[i1+2] = p[i2+2]; 27 p[i2+2] = tmp; 28 // swap alpha 29 tmp = p[i1+3]; 30 p[i1+3] = p[i2+3]; 31 p[i2+3] = tmp; 32 } 33 } 34 } 35 36 /** 37 * Convert the image to luminance 38 */ 39 ImageData.luminance = function(imageData, ratio) 40 { 41 ratio = ratio !== undefined ? ratio : 1.0; 42 var p = imageData.data; 43 var w = imageData.width; 44 var h = imageData.height; 45 for(var i = 0, y = 0; y < h; y++){ 46 for(var x = 0; x < w; x++, i += 4){ 47 var luminance = (0.2126*(p[i+0]/255)) + (0.7152*(p[i+1]/255)) + (0.0722*(p[i+2]/255)) 48 luminance = Math.floor(luminance*ratio*255); 49 p[i+0] = luminance; 50 p[i+1] = luminance; 51 p[i+2] = luminance; 52 } 53 } 54 } 55 56 /** 57 * Duplicate the ImageData 58 */ 59 ImageData.duplicate = function(srcImageData, ctx) 60 { 61 var dstImageData= ctx.createImageData(srcImageData); 62 var pSrc = srcImageData.data; 63 var pDst = dstImageData.data; 64 for(var i = 0; i < pSrc.length; i++){ 65 pDst[i] = pSrc[i]; 66 } 67 return dstImageData; 68 } 69 70 ////////////////////////////////////////////////////////////////////////////////// 71 // // 72 ////////////////////////////////////////////////////////////////////////////////// 73 74 ImageData.threshold = function(imageData, r, g, b) 75 { 76 var p = imageData.data; 77 var w = imageData.width; 78 var h = imageData.height; 79 for(var i = 0, y = 0; y < h; y++){ 80 for(var x = 0; x < w; x++, i += 4){ 81 if( (p[i+0] >= r.min && p[i+0] <= r.max) 82 && (p[i+1] >= g.min && p[i+1] <= g.max) 83 && (p[i+2] >= b.min && p[i+2] <= b.max) ){ 84 }else{ 85 p[i+0] = p[i+1] = p[i+2] = 0; 86 } 87 } 88 } 89 } 90 91 ImageData.convert = function(imageData, callback) 92 { 93 var p = imageData.data; 94 var w = imageData.width; 95 var h = imageData.height; 96 var i = 0; 97 for(var y = 0; y < h; y++){ 98 for(var x = 0; x < w; x++, i += 4){ 99 callback(p, i, x, y, imageData); 100 } 101 } 102 } 103 104 105 ////////////////////////////////////////////////////////////////////////////////// 106 // // 107 ////////////////////////////////////////////////////////////////////////////////// 108 109 ImageData.hline = function(imageData, y, r, g, b, a) 110 { 111 var p = imageData.data; 112 var w = imageData.width; 113 var i = y * w * 4; 114 r = r !== undefined ? r : 255; 115 g = g !== undefined ? g : 255; 116 b = b !== undefined ? b : 255; 117 a = a !== undefined ? a : 255; 118 for(var x = 0; x < w; x++, i += 4){ 119 p[i+0] = r; 120 p[i+1] = g; 121 p[i+2] = b; 122 p[i+3] = a; 123 } 124 } 125 126 ImageData.vline = function(imageData, x, r, g, b, a) 127 { 128 var p = imageData.data; 129 var w = imageData.width; 130 var h = imageData.height; 131 r = r !== undefined ? r : 255; 132 g = g !== undefined ? g : 255; 133 b = b !== undefined ? b : 255; 134 a = a !== undefined ? a : 255; 135 for(var i = x*4, y = 0; y < h; y++, i += w*4){ 136 p[i+0] = r; 137 p[i+1] = g; 138 p[i+2] = b; 139 p[i+3] = a; 140 } 141 } 142 143 ////////////////////////////////////////////////////////////////////////////////// 144 // // 145 ////////////////////////////////////////////////////////////////////////////////// 146 147 ImageData.smoothHistogram = function(hist, factor) 148 { 149 var value = 0; 150 for(var i = 0; i < hist.length; i++ ){ 151 value += (hist[i] - value) * factor; 152 hist[i] = value; 153 } 154 } 155 156 ImageData.windowedAverageHistogram = function(hist, width) 157 { 158 var halfW = Math.floor(width/2); 159 var winSum = 0; 160 var winLen = 0; 161 var origHist = new Array(hist.length); 162 for(var i = 0; i < hist.length; i++) origHist[i] = hist[i]; 163 164 // init window 165 for(var i = 0; i < halfW; i++){ 166 winSum += hist[i]; 167 winLen ++; 168 } 169 170 for(var i = 0; i < hist.length; i++){ 171 // update window forward 172 if( i + halfW <= hist.length ){ 173 winSum += origHist[i+halfW]; 174 winLen ++; 175 } 176 // update window backward 177 if( i-halfW >= 0 ){ 178 winSum -= origHist[i-halfW]; 179 winLen --; 180 } 181 // 182 hist[i] = winSum/winLen; 183 } 184 } 185 186 ImageData.getMaxHistogram = function(hist, imageData) 187 { 188 var max = -Number.MAX_VALUE; 189 var idx = 0; 190 for(var i = 0; i < hist.length; i++ ){ 191 if( hist[i] > max ){ 192 max = hist[i]; 193 idx = i; 194 } 195 } 196 return {max: max, idx: idx} 197 } 198 199 200 ////////////////////////////////////////////////////////////////////////////////// 201 // // 202 ////////////////////////////////////////////////////////////////////////////////// 203 204 ImageData.computeVerticalHistogram = function(imageData, filter) 205 { 206 var p = imageData.data; 207 var w = imageData.width; 208 var h = imageData.height; 209 var hist= new Float64Array(w); 210 console.assert(filter, "invalid parameter") 211 for(var x = 0; x < w; x++){ 212 for(var i = x*4, y = 0; y < h; y++, i += w*4){ 213 if( filter(p, i, x, y, imageData) ) hist[x]++; 214 } 215 } 216 return hist; 217 } 218 219 ImageData.displayVerticalHistogram = function(imageData, hist) 220 { 221 var p = imageData.data; 222 var w = imageData.width; 223 var h = imageData.height; 224 console.assert(hist.length === w); 225 // create temporary cancas 226 var canvas = document.createElement('canvas'); 227 canvas.width = w; 228 canvas.height = h; 229 var ctx = canvas.getContext("2d"); 230 // display the histogram in the canvas 231 ctx.fillStyle = 'red'; 232 for(var x = 0; x < w; x++ ){ 233 ctx.fillRect(x, h-hist[x], 1, hist[x]); 234 } 235 // copy the canvas in imageData 236 var srcImgData = ctx.getImageData(0,0, canvas.width, canvas.height); 237 var pSrc = srcImgData.data; 238 var pDst = imageData.data; 239 for(var i = 0; i < pSrc.length; i += 4){ 240 if( pSrc[i+0] !== 0 || pSrc[i+1] !== 0 || pSrc[i+2] !== 0 ){ 241 pDst[i+0] = pSrc[i+0]; 242 pDst[i+1] = pSrc[i+1]; 243 pDst[i+2] = pSrc[i+2]; 244 } 245 pDst[i+3] = 255; 246 } 247 } 248 249 250 251 ////////////////////////////////////////////////////////////////////////////////// 252 // // 253 ////////////////////////////////////////////////////////////////////////////////// 254 255 ImageData.computeHorizontalHistogram = function(imageData, filter) 256 { 257 var p = imageData.data; 258 var w = imageData.width; 259 var h = imageData.height; 260 var hist= new Float64Array(h); 261 console.assert(filter, "invalid parameter") 262 for(var i = 0, y = 0; y < h; y++){ 263 for(var x = 0; x < w; x++, i += 4){ 264 if( filter(p, i, x, y, imageData) ) hist[y]++; 265 } 266 } 267 return hist; 268 } 269 270 ImageData.displayHorizontalHistogram = function(imageData, hist) 271 { 272 var p = imageData.data; 273 var w = imageData.width; 274 var h = imageData.height; 275 console.assert(hist.length === h); 276 // create temporary cancas 277 var canvas = document.createElement('canvas'); 278 canvas.width = w; 279 canvas.height = h; 280 var ctx = canvas.getContext("2d"); 281 // display the histogram in the canvas 282 ctx.fillStyle = 'red'; 283 for(var y = 0; y < h; y++ ){ 284 ctx.fillRect(0, y, hist[y], 1); 285 } 286 // copy the canvas in imageData 287 var srcImgData = ctx.getImageData(0,0, canvas.width, canvas.height); 288 var pSrc = srcImgData.data; 289 var pDst = imageData.data; 290 for(var i = 0; i < pSrc.length; i += 4){ 291 if( pSrc[i+0] !== 0 || pSrc[i+1] !== 0 || pSrc[i+2] !== 0 ){ 292 pDst[i+0] = pSrc[i+0]; 293 pDst[i+1] = pSrc[i+1]; 294 pDst[i+2] = pSrc[i+2]; 295 } 296 pDst[i+3] = 255; 297 } 298 } 299 300 301 ////////////////////////////////////////////////////////////////////////////////// 302 // // 303 ////////////////////////////////////////////////////////////////////////////////// 304 305 ImageData.computeColorHistogram = function(imageData) 306 { 307 var p = imageData.data; 308 var w = imageData.width; 309 var h = imageData.height; 310 var hist= { 311 r : new Float64Array(256), 312 g : new Float64Array(256), 313 b : new Float64Array(256) 314 }; 315 316 for(var i = 0, y = 0; y < h; y++){ 317 for(var x = 0; x < w; x++, i += 4){ 318 hist.r[ p[i+0] ]++; 319 hist.g[ p[i+1] ]++; 320 hist.b[ p[i+2] ]++; 321 } 322 } 323 return hist; 324 } 325 326 ImageData.normalizeColorHistogram = function(colorHistogram) 327 { 328 var hist= colorHistogram; 329 330 // get the max value 331 var max = -Number.MAX_VALUE; 332 for (var i = 0; i < 256; i++ ){ 333 max = Math.max(max, hist.r[i]); 334 max = Math.max(max, hist.g[i]); 335 max = Math.max(max, hist.b[i]); 336 } 337 // normalize the histogram 338 for (var i = 0; i < 256; i++ ){ 339 hist.r[i] /= max; 340 hist.g[i] /= max; 341 hist.b[i] /= max; 342 } 343 344 var sumR = 0; 345 var sumG = 0; 346 var sumB = 0; 347 for (var i = 0; i < 256; i++ ){ 348 sumR += hist.r[i]; 349 sumG += hist.g[i]; 350 sumB += hist.b[i]; 351 } 352 console.log("sum", max, sumR, sumG, sumB) 353 } 354 355 ImageData.normalizeColorHistogram0 = function(colorHistogram) 356 { 357 var hist= colorHistogram; 358 359 // get the max value 360 var max = -Number.MAX_VALUE; 361 for (var i = 0; i < 256; i++ ) max = Math.max(max, hist.r[i]); 362 for (var i = 0; i < 256; i++ ) hist.r[i] /= max; 363 var max = -Number.MAX_VALUE; 364 for (var i = 0; i < 256; i++ ) max = Math.max(max, hist.g[i]); 365 for (var i = 0; i < 256; i++ ) hist.g[i] /= max; 366 var max = -Number.MAX_VALUE; 367 for (var i = 0; i < 256; i++ ) max = Math.max(max, hist.b[i]); 368 for (var i = 0; i < 256; i++ ) hist.b[i] /= max; 369 370 var sumR = 0, sumG = 0, sumB = 0; 371 for (var i = 0; i < 256; i++ ){ 372 sumR += hist.r[i]; 373 sumG += hist.g[i]; 374 sumB += hist.b[i]; 375 } 376 console.log("sum", max, sumR, sumG, sumB) 377 } 378 379 ImageData.displayColorHistogram = function(imageData, colorHistogram) 380 { 381 var p = imageData.data; 382 var w = imageData.width; 383 var h = imageData.height; 384 var hist= colorHistogram; 385 386 var canvas = document.createElement('canvas'); 387 canvas.width = w; 388 canvas.height = h; 389 var ctx = canvas.getContext("2d"); 390 391 392 var barW = canvas.width / 256; 393 var barH = canvas.height / 3; 394 395 ctx.fillStyle = 'red'; 396 var barYOffset = 0 * barH; 397 for (var i = 0; i < 256; i++ ){ 398 var valH = Math.floor(hist.r[i]*barH); 399 ctx.fillRect(i*barW, barYOffset+(barH-valH), barW, valH); 400 } 401 402 ctx.fillStyle = 'green'; 403 var barYOffset = 1 * barH; 404 for (var i = 0; i < 256; i++ ){ 405 var valH = Math.floor(hist.g[i]*barH); 406 ctx.fillRect(i*barW, barYOffset+(barH-valH), barW, valH); 407 } 408 409 ctx.fillStyle = 'blue'; 410 var barYOffset = 2 * barH; 411 for (var i = 0; i < 256; i++ ){ 412 var valH = Math.floor(hist.b[i]*barH); 413 ctx.fillRect(i*barW, barYOffset+(barH-valH), barW, valH); 414 } 415 416 var srcImgData = ctx.getImageData(0,0, canvas.width, canvas.height); 417 var pSrc = srcImgData.data; 418 var pDst = imageData.data; 419 for(var i = 0; i < pSrc.length; i += 4){ 420 if( pSrc[i+0] !== 0 || pSrc[i+1] !== 0 || pSrc[i+2] !== 0 ){ 421 pDst[i+0] = pSrc[i+0]; 422 pDst[i+1] = pSrc[i+1]; 423 pDst[i+2] = pSrc[i+2]; 424 } 425 } 426 }