JavaScript (ES6), 301 328 312 bytes
(u,b)=>{i=new Image;i.src=u;e=document.createElement`canvas`;c=e.getContext`2d`;i.onload=_=>{w=e.width=i.width;h=e.height=i.height;c.drawImage(i,0,0);d=c.getImageData(0,0,w,h).data;for(o={},i=0;i<d.length;)++o[s=d.slice(i,i+=4)]?0:o[s]=1;b(o[(a=Object.keys(o).sort((a,b)=>o[b]-o[a]))[0]]==o[a[1]]?"Equal":a[0])}}
Feel free to golf further, this feels as long as Java to me personally.
This supports transparent images so alpha channel is included in output value.
The reason it's longer than before is because now that I've tested, it requires Image
to contain the attribute crossOrigin
, and the arguments to getImageData()
are not optional.
See Meta PCG for removal of CORS from byte count.
Usage
f("http://i.imgur.com/H5OmRVh.jpg", alert)
That will asynchronously alert
a color quadruplet or "Equal" after the image is loaded and counted.
The callback is not considered part of the program length because it is allowed as input by the OP in this special case.
How it works
It constructs an Image
, a Canvas
, and a CanvasRenderingContext2D
, then draws the image to the canvas after setting its width
and height
correctly. It then counts occurrences of each color by implicitly converting each quadruplet to a string and generating a hash of counters. After that, it sorts the hash keys by descending count before comparing the highest two occurrences and determining whether to return the first quadruplet string in the sorted array or the string "Equal"
.
If the demo below displays a SecurityError
, the domain of the image URL you chose does not support CORS.
Demo
f = (u, b) => {
let i = new Image;
i.crossOrigin = ''; // CORS added for demo
i.src = u;
let e = document.createElement `canvas`;
let c = e.getContext `2d`;
i.onload = _ => {
w = e.width = i.width;
h = e.height = i.height;
c.drawImage(i, 0, 0);
d = c.getImageData(0, 0, w, h).data;
for (o = {}, i = 0; i < d.length;)
++o[s = d.slice(i, i += 4)] ? 0 : o[s] = 1;
b(o[(a = Object.keys(o).sort((a, b) => o[b] - o[a]))[0]] == o[a[1]] ? "Equal" : a[0])
}
}
l = i => {
let p = i.nextElementSibling;
p.src = i.value;
f(`http://crossorigin.me/${i.value}`, c => p.nextElementSibling.value = c);
}
document.getElementById `i`.addEventListener('update', e => {
l(e.target)
})
Array.prototype.slice.call(document.querySelectorAll`.i`, 0, 3).forEach(l)
input {
display: block;
box-sizing: border-box;
width: 205px;
height: 18px;
}
input.o {
position: relative;
top: -36px;
}
img {
display: block;
position: relative;
box-sizing: border-box;
top: -18px;
left: 209px;
height: 40px;
}
<input class=i disabled value="http://i.stack.imgur.com/rqsAX.png">
<img>
<input class=o disabled>
<input class=i disabled value="http://i.stack.imgur.com/KECpJ.png">
<img>
<input class=o disabled>
<input class=i disabled value="http://i.stack.imgur.com/DRCWd.png">
<img>
<input class=o disabled>
<input class=i id=i placeholder="Try any image!">
<img>
<input class=o id=o disabled>
because this is kinda unclear. 3 close votes already. – Rɪᴋᴇʀ – 2016-05-22T10:52:07.783
3>
try clicking the little icon that kinda looks like a painting/background? Or link the image and I will do it. – Rɪᴋᴇʀ – 2016-05-22T11:05:20.070
@EᴀsᴛᴇʀʟʏIʀᴋEdited. – Arjun – 2016-05-22T11:45:28.183
Related. – Leaky Nun – 2016-05-22T11:54:42.370
Any image file format? – edc65 – 2016-05-22T13:48:35.790
@edc65 Only
.png
. – Arjun – 2016-05-22T14:14:16.383Could we have the image file contents as input, rather than the path, so that languages without file I/O can compete? – Mego – 2016-05-23T00:49:59.893
@Mego Yes, you can! – Arjun – 2016-05-23T01:16:50.930
If the language can only load an image from a path asynchronously, can we write a function that returns the value like
function dominant(url,function callback(color){...})
wherecallback()
is an input function? – Patrick Roberts – 2016-05-23T06:14:19.930@PatrickRoberts Yes, you can! – Arjun – 2016-05-23T06:19:00.467