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 }