Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better way to get map of all pixels of an image with GD

Tags:

php

gd

The following code uses the SimpleImage library

I have a function that gets a pixel from an image:

function getPixel($x, $y) {

    $colors = imagecolorsforindex($this->image, imagecolorat($this->image, $x, $y));
    $n[0] = $colors['red'];
    $n[1] = $colors['green'];
    $n[2] = $colors['blue'];
    $str = "#";
    for($x=0;$x < 3; $x++){
        $n[$x] = intval($n[$x],10);
        if (is_nan($n[$x])) return "00";
        $n[$x] = max(0, min($n[$x],255));
        $bam = "0123456789ABCDEF";
        $str .= $bam{($n[$x]-$n[$x]%16)/16} . $bam{$n[$x]%16};
    }
    return $str; 
}

To get every pixel in an image, I use this loop:

$arr = [];
for($y = 0;$y < $image->getHeight(); $y++){
    $arr[$y] = [];
    for($x = 0; $x < $image->getWidth(); $x++){
        $arr[$y][$x] = $image->getPixel($x, $y);
    }
}

I'm wondering if there is a faster way to do this with GD and PHP?

EDIT

What I'm thinking of is some way to get the value of every pixel from GD without a PHP loop.

like image 926
PitaJ Avatar asked Dec 09 '12 20:12

PitaJ


1 Answers

This is the ugly brute-force method, using imagecolorat() on every pixel. In my tests with large (6.5Mpixel) images, it's about 3.6sec, or about 1.1sec faster than the more elegant GD hack proposed by @cleong. It also has the advantage of brutal simplicity, and independence from the undocumented internal GD2 format.

$alphaLookup = array(
    0x00000000=>"\xff",0x01000000=>"\xfd",0x02000000=>"\xfb",0x03000000=>"\xf9",
    0x04000000=>"\xf7",0x05000000=>"\xf5",0x06000000=>"\xf3",0x07000000=>"\xf1",
    0x08000000=>"\xef",0x09000000=>"\xed",0x0a000000=>"\xeb",0x0b000000=>"\xe9",
    0x0c000000=>"\xe7",0x0d000000=>"\xe5",0x0e000000=>"\xe3",0x0f000000=>"\xe1",
    0x10000000=>"\xdf",0x11000000=>"\xdd",0x12000000=>"\xdb",0x13000000=>"\xd9",
    0x14000000=>"\xd7",0x15000000=>"\xd5",0x16000000=>"\xd3",0x17000000=>"\xd1",
    0x18000000=>"\xcf",0x19000000=>"\xcd",0x1a000000=>"\xcb",0x1b000000=>"\xc9",
    0x1c000000=>"\xc7",0x1d000000=>"\xc5",0x1e000000=>"\xc3",0x1f000000=>"\xc1",
    0x20000000=>"\xbf",0x21000000=>"\xbd",0x22000000=>"\xbb",0x23000000=>"\xb9",
    0x24000000=>"\xb7",0x25000000=>"\xb5",0x26000000=>"\xb3",0x27000000=>"\xb1",
    0x28000000=>"\xaf",0x29000000=>"\xad",0x2a000000=>"\xab",0x2b000000=>"\xa9",
    0x2c000000=>"\xa7",0x2d000000=>"\xa5",0x2e000000=>"\xa3",0x2f000000=>"\xa1",
    0x30000000=>"\x9f",0x31000000=>"\x9d",0x32000000=>"\x9b",0x33000000=>"\x99",
    0x34000000=>"\x97",0x35000000=>"\x95",0x36000000=>"\x93",0x37000000=>"\x91",
    0x38000000=>"\x8f",0x39000000=>"\x8d",0x3a000000=>"\x8b",0x3b000000=>"\x89",
    0x3c000000=>"\x87",0x3d000000=>"\x85",0x3e000000=>"\x83",0x3f000000=>"\x81",
    0x40000000=>"\x7f",0x41000000=>"\x7d",0x42000000=>"\x7b",0x43000000=>"\x79",
    0x44000000=>"\x77",0x45000000=>"\x75",0x46000000=>"\x73",0x47000000=>"\x71",
    0x48000000=>"\x6f",0x49000000=>"\x6d",0x4a000000=>"\x6b",0x4b000000=>"\x69",
    0x4c000000=>"\x67",0x4d000000=>"\x65",0x4e000000=>"\x63",0x4f000000=>"\x61",
    0x50000000=>"\x5f",0x51000000=>"\x5d",0x52000000=>"\x5b",0x53000000=>"\x59",
    0x54000000=>"\x57",0x55000000=>"\x55",0x56000000=>"\x53",0x57000000=>"\x51",
    0x58000000=>"\x4f",0x59000000=>"\x4d",0x5a000000=>"\x4b",0x5b000000=>"\x49",
    0x5c000000=>"\x47",0x5d000000=>"\x45",0x5e000000=>"\x43",0x5f000000=>"\x41",
    0x60000000=>"\x3f",0x61000000=>"\x3d",0x62000000=>"\x3b",0x63000000=>"\x39",
    0x64000000=>"\x37",0x65000000=>"\x35",0x66000000=>"\x33",0x67000000=>"\x31",
    0x68000000=>"\x2f",0x69000000=>"\x2d",0x6a000000=>"\x2b",0x6b000000=>"\x29",
    0x6c000000=>"\x27",0x6d000000=>"\x25",0x6e000000=>"\x23",0x6f000000=>"\x21",
    0x70000000=>"\x1f",0x71000000=>"\x1d",0x72000000=>"\x1b",0x73000000=>"\x19",
    0x74000000=>"\x17",0x75000000=>"\x15",0x76000000=>"\x13",0x77000000=>"\x11",
    0x78000000=>"\x0f",0x79000000=>"\x0d",0x7a000000=>"\x0b",0x7b000000=>"\x09",
    0x7c000000=>"\x07",0x7d000000=>"\x05",0x7e000000=>"\x03",0x7f000000=>"\x00"
); // Lookup table for chr(255-(($x >> 23) & 0x7f)).


$chr = array(
    "\x00","\x01","\x02","\x03","\x04","\x05","\x06","\x07","\x08","\x09","\x0A","\x0B","\x0C","\x0D","\x0E","\x0F",
    "\x10","\x11","\x12","\x13","\x14","\x15","\x16","\x17","\x18","\x19","\x1A","\x1B","\x1C","\x1D","\x1E","\x1F",
    "\x20","\x21","\x22","\x23","\x24","\x25","\x26","\x27","\x28","\x29","\x2A","\x2B","\x2C","\x2D","\x2E","\x2F",
    "\x30","\x31","\x32","\x33","\x34","\x35","\x36","\x37","\x38","\x39","\x3A","\x3B","\x3C","\x3D","\x3E","\x3F",
    "\x40","\x41","\x42","\x43","\x44","\x45","\x46","\x47","\x48","\x49","\x4A","\x4B","\x4C","\x4D","\x4E","\x4F",
    "\x50","\x51","\x52","\x53","\x54","\x55","\x56","\x57","\x58","\x59","\x5A","\x5B","\x5C","\x5D","\x5E","\x5F",
    "\x60","\x61","\x62","\x63","\x64","\x65","\x66","\x67","\x68","\x69","\x6A","\x6B","\x6C","\x6D","\x6E","\x6F",
    "\x70","\x71","\x72","\x73","\x74","\x75","\x76","\x77","\x78","\x79","\x7A","\x7B","\x7C","\x7D","\x7E","\x7F",
    "\x80","\x81","\x82","\x83","\x84","\x85","\x86","\x87","\x88","\x89","\x8A","\x8B","\x8C","\x8D","\x8E","\x8F",
    "\x90","\x91","\x92","\x93","\x94","\x95","\x96","\x97","\x98","\x99","\x9A","\x9B","\x9C","\x9D","\x9E","\x9F",
    "\xA0","\xA1","\xA2","\xA3","\xA4","\xA5","\xA6","\xA7","\xA8","\xA9","\xAA","\xAB","\xAC","\xAD","\xAE","\xAF",
    "\xB0","\xB1","\xB2","\xB3","\xB4","\xB5","\xB6","\xB7","\xB8","\xB9","\xBA","\xBB","\xBC","\xBD","\xBE","\xBF",
    "\xC0","\xC1","\xC2","\xC3","\xC4","\xC5","\xC6","\xC7","\xC8","\xC9","\xCA","\xCB","\xCC","\xCD","\xCE","\xCF",
    "\xD0","\xD1","\xD2","\xD3","\xD4","\xD5","\xD6","\xD7","\xD8","\xD9","\xDA","\xDB","\xDC","\xDD","\xDE","\xDF",
    "\xE0","\xE1","\xE2","\xE3","\xE4","\xE5","\xE6","\xE7","\xE8","\xE9","\xEA","\xEB","\xEC","\xED","\xEE","\xEF",
    "\xF0","\xF1","\xF2","\xF3","\xF4","\xF5","\xF6","\xF7","\xF8","\xF9","\xFA","\xFB","\xFC","\xFD","\xFE","\xFF",
); // Lookup for chr($x): much faster.



function lookUpImageBytes($canvas) {
    global $alphaLookup, $chr;
    $imageWidth = imagesx($canvas);
    $imageHeight = imagesy($canvas);
    // Faster than append, and >500mb more memory efficient for a 6.5MPx image!
    $imageData = str_repeat("\x00\x00\x00\x00", $imageWidth * $imageHeight);

    // Loop over each single pixel.
    $j = 0;
    for ($y = 0; $y < $imageHeight; $y++) {
        for ($x = 0; $x < $imageWidth; $x++) {
            // Grab the pixel data.
            $argb = imagecolorat($canvas, $x, $y);
            $imageData[$j++] = $alphaLookup[$argb & 0x7f000000]; // A (convert from GD).
            // NB: three $chr arrays to replace the shifts WON'T improve speed.
            $imageData[$j++] = $chr[($argb >> 16) & 0xFF]; // R
            $imageData[$j++] = $chr[($argb >> 8) & 0xFF]; // G
            $imageData[$j++] = $chr[$argb & 0xFF]; // B
        }
    }
    return $imageData;
}
like image 157
Dewi Morgan Avatar answered Nov 15 '22 17:11

Dewi Morgan