What color is this?

9

2

You are to golf a program that will take a filename as input and you must output what color the file is.

The file will have any one of these extensions but your program only needs to support one. Please say which one in your answer.

  • .jpg
  • .png
  • .svg
  • .gif
  • .bmp

And now to the classic layout.

Input

A filename with one of the above extensions.

You may also take an image object or already encoded image instead.

Output

The only color in that file as a 6 digit hex code with an optional leading # e.g. #000000 is black.

You may also output a list/tuple/string containing the decimal or hex values of the RGB color, with a clear, non-numeric delimiter e.g. , | etc

You may not output the transparency.

If the file isn't all one color, you must output a falsy value that isn't #000000 and terminate without printing anything to STDERR. This is so that you can't simply open the file and get the RGB value of the first pixel.

Rules

  • The hex code only needs to be outputted if the file is all one color.
  • The file will be 500x500 pixels
  • The pixels will all have 0% transparency.
  • This is so shortest code wins!

Examples

caird coinheringaahing

Posted 2017-05-26T14:19:18.040

Reputation: 13 702

7The file all not being one colour just seems like an unnecessary complication to me. And a falsey value in strongly typed languages, e.g. C#, can only be a bool. For this case I'd be returning a string for the normal case and bool for the non-normal case, wrapped in an object. Is this fine or can I return an empty string or similar? – TheLethalCoder – 2017-05-26T14:26:00.660

5Also I suggest uploading your images to i.stack.imgur.com (my program can't get the image off of pasteboard) – user41805 – 2017-05-26T14:30:50.457

1

We have a default standard for image input, you can find it on our meta here. It's not significantly different from what you have, but you may want to link to it instead of your provided one.

– Pavel – 2017-05-26T14:32:28.810

1@TheLethalCoder you could probably get away with returning null, or an empty string. – Pavel – 2017-05-26T14:35:24.840

1@Phoenix That's what I'm asking though, is it okay as that is not a falsey value in C# and probably other strongly typed languages. – TheLethalCoder – 2017-05-26T14:36:15.863

@TheLethalCoder that's fine. Also the "it may be different colours is so that it isn't to trivial" – caird coinheringaahing – 2017-05-26T14:50:58.963

6

@Ilikemydog It does matter. Saying the output is "The only color in that file" leads answerers to assume that the image will contain a single color. Then the rules contradict that. On the other hand, it would be a lot clearer if the output section read something like "The only color in that file, or a falsy value different than... if the image contains more than one color". Or, as xnor so aptly put it, it's confusing when the body of the challenge says one thing but a later part says another

– Luis Mendo – 2017-05-26T15:23:22.840

On a side note you can use the sandbox for future challenges to avoid most of this back and forth with clarifications once the challenge has already been posted.

– TheLethalCoder – 2017-05-26T15:26:31.783

2Are we to assume that all files will always be 3 channel (8 bits each) RGB files? – Octopus – 2017-05-26T15:45:08.853

What @LuisMendo says is exactly what caused me to screw up my first attempt at this. – Shaggy – 2017-05-26T17:12:54.850

@Octopus yes you shoud – caird coinheringaahing – 2017-05-26T21:06:13.297

Can we only assume the format? – l4m2 – 2018-10-25T13:14:11.167

Answers

6

MATL, 15 12 bytes

Yi6Bed~?2MYm

Tested with the ".png" images given in the challenge. It probably works with other extensions too. Input can be a filename or a URL of the image.

Output is R, G, B decimal values separated by spaces, or the empty string (which is falsy) if there are more than one color.

Example with first and last test cases:

enter image description here

Explanation

Yi      % Implicitly input filename. Read image as an M×N×3 array
6B      % Push [true true false] (6 in binary)
e       % Reshape. This collapses firsts two dimensions. Gives an (M*N)×3 array
d       % Consecutive diferences down each column. Gives an an (M*N-1)×3 array
~?      % If all those differences are zero (this means there is a single color)
  2M    %   Push the (M*N)×3 array again
  Ym    %   Mean of each column
        % Implicit end
        % Implicitly display

Luis Mendo

Posted 2017-05-26T14:19:18.040

Reputation: 87 464

Does this have the check for the falsey image? – TheLethalCoder – 2017-05-26T14:57:25.937

1@TheLethalCoder Solved. Thanks for the heads-up – Luis Mendo – 2017-05-26T15:15:59.240

You may also take an image object or already encoded image instead. OP updated might be able to save bytes... – TheLethalCoder – 2017-05-26T15:18:15.933

@TheLethalCoder Thanks. I don't think it helps in this answer, unless I could input the M×N×3 array directly, which is probably not what the OP means – Luis Mendo – 2017-05-26T15:20:46.047

112 bytes?! Well, holy hell! – Shaggy – 2017-05-26T22:16:42.197

4

JavaScript (ES6) + HTML, 315 289 243 218 217 215 211 210 208 bytes

Checking that all pixels were identical added a lot of bytes. Down to it not being much bigger than when I was just checking the colour of the first pixel - happy with that :)

Takes the URL (absolute, relative, data or anything that can be used as the src of an img) of the image file as input. Outputs the RGB colour as a comma separated string or 0 for falsey. Tested with PNG files but should work with JPG & GIF too.

u=>(a=[...Array(c.width=c.height=500)]).map((_,x)=>a.map((_,y)=>(v=""+[(d=g.getImageData(x,y,1,1).data)[0],d[1],d[2]],h=x&y?v!=h?0:h:v)),i.src=u,(g=c.getContext`2d`).drawImage(i,0,0))&&h
<img id=i><canvas id=c

Try it

Requires the addition of a closing > on the canvas element in order to work in a Snippet. As pulling images in from external sources would cause an error to be thrown, the following will instead take Base-64 data URLs as input. Uncomment the last line to test for different colours using an image consisting of the 4 test colours.

f=
u=>(a=[...Array(c.width=c.height=500)]).map((_,x)=>a.map((_,y)=>(v=""+[(d=g.getImageData(x,y,1,1).data)[0],d[1],d[2]],h=x&y?v!=h?0:h:v)),i.src=u,(g=c.getContext`2d`).drawImage(i,0,0))&&h
console.log(f("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0AQMAAADxGE3JAAAAA1BMVEUWwpMvG5UqAAAANUlEQVR42u3BMQEAAADCIPun9lkMYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5fQAAASJ0bysAAAAASUVORK5CYII"))
//console.log(f("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0AgMAAAC2uDcZAAAADFBMVEWLFsIWwpOVkJCE8Az9F2TyAAABB0lEQVR42uzNIQEAMAwDsEk8ucmTS9xElAwkBlI3cipit9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91uX72/yO+I3W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdPhu1fdT2UdtHbR+1fdT2UdsHs+0AqVGfBnNZ7+UAAAAASUVORK5CYII"))
<img id=i><canvas id=c>

Shaggy

Posted 2017-05-26T14:19:18.040

Reputation: 24 623

A filename with one of the above extensions. -> You sure you can take the image as an encoded string instead of loading from a file? – TheLethalCoder – 2017-05-26T15:14:05.063

1@TheLethalCoder, No! :D And, now that you say it, I can see how I can save a few bytes :) – Shaggy – 2017-05-26T15:15:24.413

You may also take an image object or already encoded image instead. OP updated might be able to save bytes... – TheLethalCoder – 2017-05-26T15:18:19.140

@TheLethalCoder, I was able to chop "data:image/png;base64,"+ out of my code by taking input as a URL instead. – Shaggy – 2017-05-26T15:21:03.027

4

Bash + core-utils + Imagemagick, 60

a=(`convert $1 txt:|sort -uk3`)
((${#a[@]}-9))||echo ${a[2]}

Outputs the colour if there is one colour and nothing if there is more than one colour.

  • convert $1 txt: reads the input file and outputs as a text file, specifically in this format:
# ImageMagick pixel enumeration: 500,500,255,srgba
0,0: (245,236,236,1)  #F5ECEC  srgba(245,236,236,1)
1,0: (245,236,236,1)  #F5ECEC  srgba(245,236,236,1)
2,0: (245,236,236,1)  #F5ECEC  srgba(245,236,236,1)
3,0: (245,235,235,1)  #F5EBEB  srgba(245,235,235,1)
4,0: (245,235,235,1)  #F5EBEB  srgba(245,235,235,1)
  • sort -uk3 uniquely sorts this by the third column. This output is assigned to an array a

  • ((${#a[@]}-9)) tests if the array does NOT have length 9

  • if the array does NOT NOT have length 9 (i.e. it does have length 9), then output element 2 (0-based) which will be the unique colour.

Digital Trauma

Posted 2017-05-26T14:19:18.040

Reputation: 64 644

1Oh my, that's impressive. – MD XF – 2017-05-27T03:47:27.723

3

Python 2, 80 bytes

from PIL import Image
i=Image.open(input()).getcolors(1)
print i and i[0][1][:3]

PIL.Image has a getcolors function which returns None if the number of colors is bigger than the parameter and returns a histogram of the colors in a [(pixels, (r,g,b,a)), ...] structure.

Gábor Fekete

Posted 2017-05-26T14:19:18.040

Reputation: 2 809

You may also take an image object or already encoded image instead. OP updated might be able to save bytes... – TheLethalCoder – 2017-05-26T15:18:57.973

@TheLethalCoder So then I should assume an already opened image and just write print i and i[0][1][:3]? – Gábor Fekete – 2017-05-26T16:17:25.013

I'd assume you'd need the get colours call to – TheLethalCoder – 2017-05-26T16:55:32.013

3

Mathematica, 55 51 Bytes

-4 thanks to CalculatorFeline

+0 for refactoring into full function.

Using Mathematica image object as input - Import["filename.png"].

If[Length@#==1,#,0]&@Union[Join@@ImageData@#]&

Returns 0 if not all one color. Outputs the decimal value of the color if just one.

Explanation:

                                 ImageData@# & - Convert input into 2D array of RGB values
                           Join@@              - Join the array into 1D array f RGB values
                     Union[                 ]  - Union all the RGB values
   Length@#        &@                          - Find length of the union of arrays
If[        ==1,#,0]                            - Check if its 1, return it if true, return 0 if not

Ian Miller

Posted 2017-05-26T14:19:18.040

Reputation: 727

a==1==a<2 and Join@@ is equivalent to ~Flatten~1 in this case. (Join breaks if the list contains any nonlists.) – CalculatorFeline – 2017-05-26T21:13:42.203

By default, a full function or program is required. For using an already-decoded image object, I believe you'd still need to do something like If[Length@#==1,#,0]&@Union[ImageData@#~Flatten~1]& – Julian Wolf – 2017-05-26T22:45:49.983

I misinterpreted the OP's comment You may also take an image object or already encoded image instead.. Will update. – Ian Miller – 2017-05-27T04:11:26.957

@CalculatorFeline Thanks for hint about Join@@. – Ian Miller – 2017-05-27T04:13:38.233

2

Java 8+, 331 165 119 bytes

i->{Integer j=i.getRGB(0,0),k=500,l;for(;k-->0;)for(l=500;l-->0;)if(i.getRGB(k,l)!=j)return"";return j.toHexString(j);}

-a lot of bytes thanks to @LethalCoder for updating me on a rule change that allowed for a lot of golfing
-46 bytes thanks to @KevinCruijssen and fixed typo

HyperNeutrino

Posted 2017-05-26T14:19:18.040

Reputation: 26 575

You may also take an image object or already encoded image instead. OP updated might be able to save bytes... – TheLethalCoder – 2017-05-26T15:18:47.110

@TheLethalCoder Oh perfect. Thanks! – HyperNeutrino – 2017-05-26T17:10:57.990

I know it's been a while, but some things to golf (without changing the Java 7 version): Object f(java.awt.image.BufferedImage i){Integer j=i.getRGB(0,0),k=500,l;for(;k-->0;)for(l=500;l-->0;)if(i.getRGB(k,l)!=i)return"";return j.toHexString(j);}. By changing the Java version to 8+, you can also change Object f(java.awt.image.BufferedImage i) to i->. Also, I think you've made a typo: shouldn't if(i.getRGB(k,l)!=i) be !=j instead? – Kevin Cruijssen – 2018-10-25T13:02:15.383

@KevinCruijssen Thanks. And yeah, I think I did :P – HyperNeutrino – 2018-10-25T17:00:06.563

1@HyperNeutrino You forgot to change it to Java 8 (or higher). ;) – Kevin Cruijssen – 2018-10-25T17:03:43.093

1

C#, 163 128 125 bytes

b=>{var c=b.GetPixel(0,0);for(int w=500,h;w-->0;)for(h=500;h-->0;)if(b.GetPixel(w,h)!=c)return"";return c.R+" "+c.G+" "+c.B;}

Saved 3 bytes thanks to @Kevin Cruijssen.

If we didn't have to have the additional check for the image being the same colours this is only 55 bytes:

b=>{var c=b.GetPixel(0,0);return c.R+" "+c.G+" "+c.B;};

TheLethalCoder

Posted 2017-05-26T14:19:18.040

Reputation: 6 930

I know it's been a while, but: b=>{var c=b.GetPixel(0,0);for(int w=500,h;w-->0;)for(h=500;h-->0;)if(b.GetPixel(w,h)!=c)return"";return c.R+" "+c.G+" "+c.B;} (-3 bytes) – Kevin Cruijssen – 2018-10-25T13:06:15.000

1

Python 2, 123 85 bytes

from PIL import Image
c=Image.open(input()).getdata()
print len(set(c))<2and c[0][:3]

Rod

Posted 2017-05-26T14:19:18.040

Reputation: 17 588

You may also take an image object or already encoded image instead. OP updated might be able to save bytes... – TheLethalCoder – 2017-05-26T15:18:23.430

I would expect from PIL import* to save a few bytes(or alternatively, import PIL and then c=PIL.Image ) unless I'm overlooking something – Foon – 2017-05-26T20:12:39.907

@Foon PIL is a exception to imports, you can't do from PIL import* norPIL. – Rod – 2017-05-26T20:13:50.930

Thanks; did not know that or at least forgot it – Foon – 2017-05-26T20:20:45.670

Inconsistency is horrible :( – CalculatorFeline – 2017-05-27T19:44:39.963

0

Mathematica, 112 bytes

image

i=Import@"c:\a.png";

If[Length@DominantColors@i==1,"#"<>StringPadLeft[IntegerString[Most@PixelValue[i,{1,1},"Byte"],16],2,"0"],False]

J42161217

Posted 2017-05-26T14:19:18.040

Reputation: 15 931

You may also take an image object or already encoded image instead. OP updated might be able to save bytes... – TheLethalCoder – 2017-05-26T15:18:55.270

ok. I made some changes.thanks – J42161217 – 2017-05-26T15:23:30.210

Is lowercase hex acceptable? – user202729 – 2017-05-26T15:29:07.397

Most@PixelValue[i, {1, 1}, "Byte"] will save some bytes. – user202729 – 2017-05-26T15:33:40.033

103 bytes: If[Length@Tally[a=i~ImageData~"Byte"]<2,"#"<>StringPadLeft[Most@a[[1,1]]~IntegerString~16,2,"0"],False] - use your ImageData function. Didn't know that existed. – user202729 – 2017-05-26T16:07:25.053

0

Bash + ImageMagick, 100 bytes

i=$(expr `identify -format "%k" $1` = 1)&&convert $1 -format "%c" histogram:info:-|grep -o "#......"

Tested with .png, should work with the other formats as well. The output for a polychromatic image is simply an empty string.

3141

Posted 2017-05-26T14:19:18.040

Reputation: 1

You can drop the quotes from around the format specifiers. Also ((\identify -format %k $1`-1))||is shorter thani=$(expr `identify -format "%k" $1` = 1)&&`. – Digital Trauma – 2017-05-26T23:26:56.993

0

C, 224 205 bytes

m[3],i;
main(c,v)char**v;{
void*s=fopen(v[1],"r");
for(;i<54;i++)getc(s);
m[2]=getc(s);m[1]=getc(s);*m=getc(s);
for(i=0;i<500*500;i++)if((c=getc(s))!=m[i%3]&&~c)exit(puts("0"));
printf("%d,%d,%d",*m,m[1],m[2]);}

Takes a 500x500 bitmap as a command-line argument. Prints the RGB of the file, e.g. 255,255,255, or 0 if the file is not constant. Probably crashes badly if no file is provided.

Interesting points to note:

  • Uses void* in the place of FILE* to avoid including <stdio.h>
  • Uses a simple for loop with i%3 to determine if all bytes are the same
  • Can be very golfed, I golfed 50 bytes while writing this answer
  • BMP stores colors as BGR so it more/less reads backwards

MD XF

Posted 2017-05-26T14:19:18.040

Reputation: 11 605

0

JavaScript + HTML, 143 + 23 = 166 bytes

u=>(i.src=u,s=C.width=C.height=500,c=C.getContext`2d`,c.drawImage(i,0,0),d=c.getImageData(0,0,s,s).data,!d.some((n,i)=>n-d[i%4])&&d.slice(0,3))
<img id=i><canvas id=C>

Try it:

f=
u=>(i.src=u,s=C.width=C.height=500,c=C.getContext`2d`,c.drawImage(i,0,0),d=c.getImageData(0,0,s,s).data,!d.some((n,i)=>n-d[i%4])&&d.slice(0,3))

console.log(
    f('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0AQMAAADxGE3JAAAAA1BMVEUWwpMvG5UqAAAANUlEQVR42u3BMQEAAADCIPun9lkMYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5fQAAASJ0bysAAAAASUVORK5CYII'),
    f('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0AgMAAAC2uDcZAAAADFBMVEWLFsIWwpOVkJCE8Az9F2TyAAABB0lEQVR42uzNIQEAMAwDsEk8ucmTS9xElAwkBlI3cipit9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91uX72/yO+I3W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdPhu1fdT2UdtHbR+1fdT2UdsHs+0AqVGfBnNZ7+UAAAAASUVORK5CYII')
)
<img id=i><canvas id=C>

Less golfed:

u => {
    i.src = u
    s = C.width = C.height = 500
    c = C.getContext('2d')
    c.drawImage(i, 0, 0)
    d = c.getImageData(0, 0, s, s).data
    return d.every((n,i) => n == d[i % 4]) && d.slice(0,3)
}

darrylyeo

Posted 2017-05-26T14:19:18.040

Reputation: 6 214

0

PowerShell, 79 bytes

param($b)if(!($c=499..0*500|%{$b|% G*l $_ $y;$y+=!$_}|gu).Rank){$c.R;$c.G;$c.B}

Less golfed test script:

$f = {

    param($b)
    $c=499..0*500|%{$b.GetPixel($_,$y);$y+=!$_}|gu
    if(!$c.Rank){
        $c.R;$c.G;$c.B
    }

}

@(
    ,("22 194 147", "https://cdn.pbrd.co/images/8bawQk5kM.png")
    ,("139 22 194", "https://cdn.pbrd.co/images/8b9foR0H6.png")
    ,("149 144 144","https://cdn.pbrd.co/images/8baglmIE8.png")
    ,("132 240 12", "https://cdn.pbrd.co/images/8b9Uhhovn.png")
    ,("",           "https://cdn.pbrd.co/images/8bb4DeKx3.png")

) | % {
    $expected,$s = $_

    $binData = [System.Net.WebClient]::new().DownloadData($s)
    $memoryStream = [System.IO.MemoryStream]::new($binData)
    $bitmap = [System.Drawing.Bitmap]::FromStream($memoryStream)

    $sw = [System.Diagnostics.Stopwatch]::StartNew()
    $result = &$f $bitmap
    "$("$result"-eq$expected): $($sw.Elapsed): $result"
}
  • Note 1: expression 499..0*500 means: repeat 500 times an range from 499 downto 0
  • Note 2: expression $b|% G*l $_ $y is shortcut for $b.GetPixel($_,$y). This trick is usefull with gofing, but it slows down the code.

Output with $b|% G*l $_ $y:

True: 00:01:45.4904622: 22 194 147
True: 00:01:56.4208157: 139 22 194
True: 00:01:46.7629439: 149 144 144
True: 00:01:48.1999005: 132 240 12
True: 00:01:55.8579935:

Output with $b.GetPixel($_,$y):

True: 00:00:05.7637937: 22 194 147
True: 00:00:06.8743244: 139 22 194
True: 00:00:08.7456055: 149 144 144
True: 00:00:08.5942450: 132 240 12
True: 00:00:06.6495706:

Explanation:

  • the script creates an array of each pixel color.
  • the script applies gu (alias for Get-Unique) to the array of color.
  • if the result of hu is a single element (property rank has value for an array only) then output decimal value of R,G,B of this element

mazzy

Posted 2017-05-26T14:19:18.040

Reputation: 4 832

0

Python 2 + OpenCV + NumPy: 66 characters

colors.py

import numpy as N
def c(i):p=i[0,0];print(p[::-1],"")[N.any(i-p)]

test.py

import cv2
from colors import c

c(cv2.imread('16C293.png'))
c(cv2.imread('84F00C.png'))
c(cv2.imread('8B16C2.png'))
c(cv2.imread('959090.png'))
c(cv2.imread('falsy.png'))

Result:

18:14 ~/colors $ python test.py
[ 22 194 147]
[132 240  12]
[139  22 194]
[149 144 144]

18:15 ~/colors $ 

OpenCV is able to read an image and return it as an N-dimensional array. NumPy is used to test the first pixel against the others and either print out the RGB values or blank.

dana

Posted 2017-05-26T14:19:18.040

Reputation: 2 541

0

PHP, 88 bytes

function($i){return~-imagecolorstotal($i)?0:sprintf("#%06x",imagecolorsforindex($i,0));}

anonymous function takes an indexed PHP image resource as parameter, assumes color in first palette slot, returns color code or 0.

program, 96 bytes

imagecolorstotal($i=imagecreatefromgif($argv[1]))-1||sprintf("#%06x",imagecolorsforindex($i,0));

takes GIF file name from argument, prints color code or nothing. Run with php -r '<code>' <filename.gif>.

for true color images, 113 112 bytes

function($i){for(;$p<25e4;$p++)$r[$c=imagecolorat($i,$p%500,$p/500)]=1;return~-count($r)?0:sprintf("#%06x",$c);}

as above, but requires true color image.

program, 122 116 bytes

for(;$p<25e4;$p++)$r[$c=imagecolorat(imagecreatefrompng($argv[1]),$p%500,$p/500)]=1;count($r)-1||printf("#%06x",$c);

as above, but requires PNG file.

Titus

Posted 2017-05-26T14:19:18.040

Reputation: 13 814