| 23 | function createHSLHistogram(imageObj, quant) |
| 24 | { |
| 25 | var i; |
| 26 | |
| 27 | if (!$('#hsl_canvas').length) { |
| 28 | $('<canvas>', {id: 'hsl_canvas'}).hide().appendTo('body'); |
| 29 | } |
| 30 | |
| 31 | imageData = drawImage(imageObj,'hsl_canvas'); |
| 32 | |
| 33 | var outputLength = quant * quant * quant; |
| 34 | var outputArray = new Array(outputLength); |
| 35 | for (i=0; i<outputLength; i++) { |
| 36 | outputArray[i] = 0; |
| 37 | } |
| 38 | |
| 39 | var total = 0.0; |
| 40 | |
| 41 | var log2 = Math.log(2); |
| 42 | |
| 43 | //calculate value to shift by (log base 2) |
| 44 | |
| 45 | var shift_sat = Math.floor(Math.log(quant)/log2); |
| 46 | var shift_hue = Math.floor(Math.log(quant*quant)/log2); |
| 47 | |
| 48 | //console.log("bit-shift sat = " + shift_sat); |
| 49 | //console.log("bit-shift hue = " + shift_hue); |
| 50 | |
| 51 | var data = imageData.data; |
| 52 | |
| 53 | //Loop through each pixel |
| 54 | var y,p; |
| 55 | for (y=0,p=0; y<imageObj.height; y++) { |
| 56 | var x; |
| 57 | for (x=0; x<imageObj.width; x++,p+=4) { |
| 58 | // convert 4 byte data value into a colour pixel |
| 59 | var rgb_c = new RGBColour(data[p],data[p+1],data[p+2],data[p+3]/255.0); |
| 60 | var hsl = new rgb_c.getHSL(); |
| 61 | |
| 62 | // express h,s and b in the range 0..1 |
| 63 | |
| 64 | var h = hsl.h / 360.0; |
| 65 | var s = hsl.s / 100.0; |
| 66 | var b = hsl.l / 100.0; |
| 67 | |
| 68 | var result = (Math.floor(h * (quant - 1)) << shift_hue) |
| 69 | | (Math.floor(s * (quant - 1)) << shift_sat) |
| 70 | | Math.floor(b * (quant - 1)); |
| 71 | |
| 72 | //number of opaque pixels |
| 73 | var count = hsl.a; // 'a' is naturally in the range 0..1 |
| 74 | |
| 75 | //add to the total number of opaque pixels |
| 76 | total += count; |
| 77 | |
| 78 | //add the frequency of each colour to the histogram |
| 79 | outputArray[result] += count; |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | //Normalise the histogram, based on the number of opaque pixels |
| 84 | for (i=0; i<outputArray.length; i++) { |
| 85 | outputArray[i] = outputArray[i] / total; |
| 86 | } |
| 87 | |
| 88 | return outputArray; |
| 89 | } |
| 90 | |
| 91 | var flag_comparison_array = Array(2); |
| 92 | var clicked_on_count = 0; |
| 93 | |
| 94 | function quantizedColourHistogramComparison(quant_colour_hist1,quant_colour_hist2) |
| 95 | { |
| 96 | // Assumes both histograms are of the same length |
| 97 | |
| 98 | var i; |
| 99 | var quant_product = 0.0; |
| 100 | |
| 101 | //Loop through and compare the histograms |
| 102 | for (i=0; i<quant_colour_hist1.length; i++) { |
| 103 | //take the overlap |
| 104 | quant_product += Math.min(quant_colour_hist1[i], quant_colour_hist2[i]); |
| 105 | |
| 106 | // consider replacing with abs for difference |
| 107 | } |
| 108 | |
| 109 | alert("Product for HSL histogram: " + quant_product); |
| 110 | |
| 111 | } |
| 112 | |
| 156 | |
| 157 | imageObj.onclick = function() { |
| 158 | // Store result of HSL quantization in the image object/tag |
| 159 | if (!this.quantHSLHist) { |
| 160 | // Only need to compute this if it is not already stored in the object/tag |
| 161 | this.quantHSLHist = createHSLHistogram(this,16); |
| 162 | console.log(this.quantHSLHist); |
| 163 | } |
| 164 | flag_comparison_array[clicked_on_count] = this.quantHSLHist; |
| 165 | |
| 166 | clicked_on_count++; |
| 167 | if (clicked_on_count==2) { |
| 168 | // trigger comparison |
| 169 | quantizedColourHistogramComparison(flag_comparison_array[0],flag_comparison_array[1]); |
| 170 | clicked_on_count=0; |
| 171 | } |
| 172 | }; |
| 173 | |
66 | | |
67 | | |
| 183 | function computeFlagHistogramChain(chain_count, img_list_len, |
| 184 | progressVal, progress_step, |
| 185 | $progressArea,$progressBar) |
| 186 | { |
| 187 | var flag_id = "flag-img-" + chain_count; |
| 188 | console.log("Processing Image ID: " + flag_id); |
| 189 | var imageObj = document.getElementById(flag_id); |
| 190 | |
| 191 | if (!imageObj.quantHSLHist) { |
| 192 | // Only need to compute this if it is not |
| 193 | // already stored in the object/tag |
| 194 | imageObj.quantHSLHist = createHSLHistogram(imageObj,16); |
| 195 | //console.log(imageObj.quantHSLHist); |
| 196 | } |
| 197 | |
| 198 | if (chain_count < img_list_len-1) { |
| 199 | progressVal += progress_step; |
| 200 | $progressBar.progressbar('value',progressVal); |
| 201 | |
| 202 | setTimeout(function() |
| 203 | { computeFlagHistogramChain(chain_count+1,img_list_len, |
| 204 | progressVal, progress_step, |
| 205 | $progressArea,$progressBar) |
| 206 | } |
| 207 | ,timeout_delay // any time delay causes break in 'rendering' thread, even 0! |
| 208 | ); |
| 209 | |
| 210 | } |
| 211 | else { |
| 212 | $progressArea.find('span:first').text("Done."); |
| 213 | if (img_list_len>show_progress) { |
| 214 | progressVal = 100; |
| 215 | $progressBar.progressbar('value',progressVal); |
| 216 | $progressArea.slideUp(); |
| 217 | } |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | function computeFlagHistograms(img_list,$progressArea,$progressBar) |
| 222 | { |
| 223 | var img_list_len = img_list.length; |
| 224 | |
| 225 | |
| 226 | if (img_list_len==0) { |
| 227 | $progressArea.find('span:first').text("Empty list: no computation needed."); |
| 228 | return; |
| 229 | } |
| 230 | |
| 231 | $progressArea.find('span:first').text("Computing histograms:"); |
| 232 | progressVal = 0; |
| 233 | |
| 234 | if (img_list_len>show_progress) { |
| 235 | $progressArea.slideDown(); |
| 236 | } |
| 237 | |
| 238 | var progress_step = 100.0 / img_list_len; |
| 239 | |
| 240 | // Start the chaining process |
| 241 | setTimeout(function() |
| 242 | { computeFlagHistogramChain(0,img_list_len, |
| 243 | progressVal, progress_step, |
| 244 | $progressArea,$progressBar) |
| 245 | } |
| 246 | ,timeout_delay // any time delay causes break in 'rendering' thread, even 0! |
| 247 | ); |
| 248 | |
| 249 | } |