User:Eleanorg/1.2/Forbidden Pixels/extracting pixel colours

From XPUB & Lens-Based wiki

Aim: to break an image down into a list of each pixel's position & colour, so that it can be re-created with html & css. Each pixel becomes an area coloured with a #hex code; thus manipulable - and no longer strictly part of an image. Question: how to write a script that will extract a grid of pixel colours from a given image?

ImageMagick colour extraction

Colour values for specific pixels

Command syntax: convert imagename.png -format '%[pixel:p{xpos,ypos}]' info:- Returns the rgba value of the bottom right pixel in a 20x10 grid:

# convert 20by10PixelsSection1.png -format '%[pixel:p{20,10}]' info:-
rgba(135,161,160,1)

List of unique colours

You can get a list of all the *unique* colours in an image thus. In my image of 200 pixels total, this line returns 167 unique colours:

# convert 20by10PixelsSection1.png -unique-colors -depth 16 txt:-
# ImageMagick pixel enumeration: 168,1,65535,rgba
0,0: (26471,33924,33410,65535)  #676784848282  rgba(103,132,130,1)
1,0: (26214,34438,34181,65535)  #666686868585  rgba(40%,52.549%,52.1569%,1)
2,0: (26985,34438,33924,65535)  #696986868484  rgba(41.1765%,52.549%,51.7647%,1)
3,0: (27499,34952,34438,65535)  #6B6B88888686  rgba(41.9608%,53.3333%,52.549%,1)
4,0: (26985,35209,34952,65535)  #696989898888  rgba(41.1765%,53.7255%,53.3333%,1)
5,0: (26985,35723,35466,65535)  #69698B8B8A8A  rgba(41.1765%,54.5098%,54.1176%,1)
6,0: (28013,35466,34952,65535)  #6D6D8A8A8888  rgba(42.7451%,54.1176%,53.3333%,1)
7,0: (29298,36751,36237,65535)  #72728F8F8D8D  rgba(44.7059%,56.0784%,55.2941%,1)
8,0: (29041,37265,37008,65535)  #717191919090  rgba(44.3137%,56.8627%,56.4706%,1)
9,0: (30583,38807,38550,65535)  #777797979696  rgba(46.6667%,59.2157%,58.8235%,1)
10,0: (31097,37779,37522,65535)  #797993939292  rgba(47.451%,57.6471%,57.2549%,1)
11,0: (31611,38293,38036,65535)  #7B7B95959494  rgba(48.2353%,58.4314%,58.0392%,1)
12,0: (30326,39064,38807,65535)  #767698989797  rgba(46.2745%,59.6078%,59.2157%,1)
13,0: (31868,39321,38807,65535)  #7C7C99999797  rgba(48.6275%,60%,59.2157%,1)
14,0: (32382,41120,40863,65535)  #7E7EA0A09F9F  rgba(49.4118%,62.7451%,62.3529%,1)
#etc...

Instead of a text list you can output it as an image file, which is a row of pixels showing each unique colour:

convert 20by10PixelsSection1.png -unique-colors -scale 1000%  unique_colors.gif

This is what you get: Kind of annoying that this only returns unique colours - so 167 out of 200 - but this could maybe be interesting too. A kind of 'condensation' of the essential elements.

Still, try to figure out how to get the grid... is there an easier way than just typing this...?
# convert 20by10PixelsSection1.png -format '%[pixel:p{0,0}]' info:-
rgba(135,161,160,1)
# convert 20by10PixelsSection1.png -format '%[pixel:p{0,1}]' info:-
rgba(135,161,160,1)
# convert 20by10PixelsSection1.png -format '%[pixel:p{0,2}]' info:-
rgba(135,161,160,1)

Histograms of colour distribution

Interesting other tools for 'analysing' images with imagemagick are discussed on [| this help page]. Here's a way of making a little histogram image out of a picture with a reasonably small no. of unique colours:

<source lang="bash"> convert rose: -colors 256 -format %c histogram:info:- |

   sed 's/:.*#/ #/' |
     while read count color colorname; do
       convert -size 1x$count xc:$color miff:-
     done |
       convert - -alpha set -gravity south -background none +append \
               unique_color_histogram.png

</bash> ...but can't get it to work. here's the error i get: <source lang="bash">

  1. ./histogram.sh

convert: unable to open image `20by10PixelSection.jpg:': /usr/lib/ImageMagick-6.6.0/modules-Q16/coders/jpg:.la @ error/blob.c/OpenBlob/2489. convert: missing an image filename `histogram:info:-' @ error/convert.c/ConvertImageCommand/2940. convert: no decode delegate for this image format `/tmp/magick-XXarJlLN' @ error/constitute.c/ReadImage/533. convert: missing an image filename `unique_color_histogram.png' @ error/convert.c/ConvertImageCommand/2940 </bash>

hm. First, do it the hack way and just get a value for each individual pixel.