11
\$\begingroup\$

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

\$\endgroup\$
12
  • 8
    \$\begingroup\$ The 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? \$\endgroup\$ May 26, 2017 at 14:26
  • 5
    \$\begingroup\$ Also I suggest uploading your images to i.stack.imgur.com (my program can't get the image off of pasteboard) \$\endgroup\$
    – user41805
    May 26, 2017 at 14:30
  • 2
    \$\begingroup\$ @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. \$\endgroup\$ May 26, 2017 at 14:36
  • 6
    \$\begingroup\$ @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 \$\endgroup\$
    – Luis Mendo
    May 26, 2017 at 15:23
  • 2
    \$\begingroup\$ Are we to assume that all files will always be 3 channel (8 bits each) RGB files? \$\endgroup\$
    – Octopus
    May 26, 2017 at 15:45

15 Answers 15

6
\$\begingroup\$

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
\$\endgroup\$
5
  • \$\begingroup\$ Does this have the check for the falsey image? \$\endgroup\$ May 26, 2017 at 14:57
  • 1
    \$\begingroup\$ @TheLethalCoder Solved. Thanks for the heads-up \$\endgroup\$
    – Luis Mendo
    May 26, 2017 at 15:15
  • \$\begingroup\$ You may also take an image object or already encoded image instead. OP updated might be able to save bytes... \$\endgroup\$ May 26, 2017 at 15:18
  • \$\begingroup\$ @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 \$\endgroup\$
    – Luis Mendo
    May 26, 2017 at 15:20
  • 1
    \$\begingroup\$ 12 bytes?! Well, holy hell! \$\endgroup\$
    – Shaggy
    May 26, 2017 at 22:16
5
\$\begingroup\$

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.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Oh my, that's impressive. \$\endgroup\$
    – MD XF
    May 27, 2017 at 3:47
4
\$\begingroup\$

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>

\$\endgroup\$
4
  • \$\begingroup\$ 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? \$\endgroup\$ May 26, 2017 at 15:14
  • 1
    \$\begingroup\$ @TheLethalCoder, No! :D And, now that you say it, I can see how I can save a few bytes :) \$\endgroup\$
    – Shaggy
    May 26, 2017 at 15:15
  • \$\begingroup\$ You may also take an image object or already encoded image instead. OP updated might be able to save bytes... \$\endgroup\$ May 26, 2017 at 15:18
  • \$\begingroup\$ @TheLethalCoder, I was able to chop "data:image/png;base64,"+ out of my code by taking input as a URL instead. \$\endgroup\$
    – Shaggy
    May 26, 2017 at 15:21
3
\$\begingroup\$

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.

\$\endgroup\$
3
  • \$\begingroup\$ You may also take an image object or already encoded image instead. OP updated might be able to save bytes... \$\endgroup\$ May 26, 2017 at 15:18
  • \$\begingroup\$ @TheLethalCoder So then I should assume an already opened image and just write print i and i[0][1][:3]? \$\endgroup\$ May 26, 2017 at 16:17
  • \$\begingroup\$ I'd assume you'd need the get colours call to \$\endgroup\$ May 26, 2017 at 16:55
3
\$\begingroup\$

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
\$\endgroup\$
4
  • \$\begingroup\$ a==1==a<2 and Join@@ is equivalent to ~Flatten~1 in this case. (Join breaks if the list contains any nonlists.) \$\endgroup\$ May 26, 2017 at 21:13
  • \$\begingroup\$ 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]& \$\endgroup\$ May 26, 2017 at 22:45
  • \$\begingroup\$ I misinterpreted the OP's comment You may also take an image object or already encoded image instead.. Will update. \$\endgroup\$
    – Ian Miller
    May 27, 2017 at 4:11
  • \$\begingroup\$ @CalculatorFeline Thanks for hint about Join@@. \$\endgroup\$
    – Ian Miller
    May 27, 2017 at 4:13
2
\$\begingroup\$

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

\$\endgroup\$
5
  • \$\begingroup\$ You may also take an image object or already encoded image instead. OP updated might be able to save bytes... \$\endgroup\$ May 26, 2017 at 15:18
  • \$\begingroup\$ @TheLethalCoder Oh perfect. Thanks! \$\endgroup\$
    – hyper-neutrino
    May 26, 2017 at 17:10
  • \$\begingroup\$ 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? \$\endgroup\$ Oct 25, 2018 at 13:02
  • \$\begingroup\$ @KevinCruijssen Thanks. And yeah, I think I did :P \$\endgroup\$
    – hyper-neutrino
    Oct 25, 2018 at 17:00
  • 1
    \$\begingroup\$ @HyperNeutrino You forgot to change it to Java 8 (or higher). ;) \$\endgroup\$ Oct 25, 2018 at 17:03
1
\$\begingroup\$

Python 2, 123 85 bytes

from PIL import Image
c=Image.open(input()).getdata()
print len(set(c))<2and c[0][:3]
\$\endgroup\$
5
  • \$\begingroup\$ You may also take an image object or already encoded image instead. OP updated might be able to save bytes... \$\endgroup\$ May 26, 2017 at 15:18
  • \$\begingroup\$ 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 \$\endgroup\$
    – Foon
    May 26, 2017 at 20:12
  • \$\begingroup\$ @Foon PIL is a exception to imports, you can't do from PIL import* norPIL. \$\endgroup\$
    – Rod
    May 26, 2017 at 20:13
  • \$\begingroup\$ Thanks; did not know that or at least forgot it \$\endgroup\$
    – Foon
    May 26, 2017 at 20:20
  • \$\begingroup\$ Inconsistency is horrible :( \$\endgroup\$ May 27, 2017 at 19:44
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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;};
\$\endgroup\$
1
  • \$\begingroup\$ 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) \$\endgroup\$ Oct 25, 2018 at 13:06
0
\$\begingroup\$

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]
\$\endgroup\$
5
  • \$\begingroup\$ You may also take an image object or already encoded image instead. OP updated might be able to save bytes... \$\endgroup\$ May 26, 2017 at 15:18
  • \$\begingroup\$ ok. I made some changes.thanks \$\endgroup\$
    – ZaMoC
    May 26, 2017 at 15:23
  • \$\begingroup\$ Is lowercase hex acceptable? \$\endgroup\$
    – DELETE_ME
    May 26, 2017 at 15:29
  • \$\begingroup\$ Most@PixelValue[i, {1, 1}, "Byte"] will save some bytes. \$\endgroup\$
    – DELETE_ME
    May 26, 2017 at 15:33
  • \$\begingroup\$ 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. \$\endgroup\$
    – DELETE_ME
    May 26, 2017 at 16:07
0
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ You can drop the quotes from around the format specifiers. Also ((`identify -format %k $1`-1))|| is shorter than i=$(expr `identify -format "%k" $1` = 1)&&. \$\endgroup\$ May 26, 2017 at 23:26
0
\$\begingroup\$

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)
}
\$\endgroup\$
0
\$\begingroup\$

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
\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.