9
\$\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\$
  • 7
    \$\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\$ – TheLethalCoder May 26 '17 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\$ – Cows quack May 26 '17 at 14:30
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Pavel May 26 '17 at 14:32
  • 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 '17 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 '17 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\$
  • \$\begingroup\$ Does this have the check for the falsey image? \$\endgroup\$ – TheLethalCoder May 26 '17 at 14:57
  • 1
    \$\begingroup\$ @TheLethalCoder Solved. Thanks for the heads-up \$\endgroup\$ – Luis Mendo May 26 '17 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\$ – TheLethalCoder May 26 '17 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 '17 at 15:20
  • 1
    \$\begingroup\$ 12 bytes?! Well, holy hell! \$\endgroup\$ – Shaggy May 26 '17 at 22:16
4
\$\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
    \$\begingroup\$ Oh my, that's impressive. \$\endgroup\$ – MD XF May 27 '17 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\$
  • \$\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\$ – TheLethalCoder May 26 '17 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 '17 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\$ – TheLethalCoder May 26 '17 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 '17 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\$
  • \$\begingroup\$ You may also take an image object or already encoded image instead. OP updated might be able to save bytes... \$\endgroup\$ – TheLethalCoder May 26 '17 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\$ – Gábor Fekete May 26 '17 at 16:17
  • \$\begingroup\$ I'd assume you'd need the get colours call to \$\endgroup\$ – TheLethalCoder May 26 '17 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\$
  • \$\begingroup\$ a==1==a<2 and Join@@ is equivalent to ~Flatten~1 in this case. (Join breaks if the list contains any nonlists.) \$\endgroup\$ – CalculatorFeline May 26 '17 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\$ – Julian Wolf May 26 '17 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 '17 at 4:11
  • \$\begingroup\$ @CalculatorFeline Thanks for hint about Join@@. \$\endgroup\$ – Ian Miller May 27 '17 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\$
  • \$\begingroup\$ You may also take an image object or already encoded image instead. OP updated might be able to save bytes... \$\endgroup\$ – TheLethalCoder May 26 '17 at 15:18
  • \$\begingroup\$ @TheLethalCoder Oh perfect. Thanks! \$\endgroup\$ – HyperNeutrino May 26 '17 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\$ – Kevin Cruijssen Oct 25 '18 at 13:02
  • \$\begingroup\$ @KevinCruijssen Thanks. And yeah, I think I did :P \$\endgroup\$ – HyperNeutrino Oct 25 '18 at 17:00
  • 1
    \$\begingroup\$ @HyperNeutrino You forgot to change it to Java 8 (or higher). ;) \$\endgroup\$ – Kevin Cruijssen Oct 25 '18 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\$
  • \$\begingroup\$ You may also take an image object or already encoded image instead. OP updated might be able to save bytes... \$\endgroup\$ – TheLethalCoder May 26 '17 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 '17 at 20:12
  • \$\begingroup\$ @Foon PIL is a exception to imports, you can't do from PIL import* norPIL. \$\endgroup\$ – Rod May 26 '17 at 20:13
  • \$\begingroup\$ Thanks; did not know that or at least forgot it \$\endgroup\$ – Foon May 26 '17 at 20:20
  • \$\begingroup\$ Inconsistency is horrible :( \$\endgroup\$ – CalculatorFeline May 27 '17 at 19:44
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\$
  • \$\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\$ – Kevin Cruijssen Oct 25 '18 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\$
  • \$\begingroup\$ You may also take an image object or already encoded image instead. OP updated might be able to save bytes... \$\endgroup\$ – TheLethalCoder May 26 '17 at 15:18
  • \$\begingroup\$ ok. I made some changes.thanks \$\endgroup\$ – J42161217 May 26 '17 at 15:23
  • \$\begingroup\$ Is lowercase hex acceptable? \$\endgroup\$ – user202729 May 26 '17 at 15:29
  • \$\begingroup\$ Most@PixelValue[i, {1, 1}, "Byte"] will save some bytes. \$\endgroup\$ – user202729 May 26 '17 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\$ – user202729 May 26 '17 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\$
  • \$\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\$ – Digital Trauma May 26 '17 at 23:26
0
\$\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\$
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, privacy policy and cookie policy

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