Лучший способ получить карту всех пикселей изображения с помощью GD

Следующий код использует библиотеку SimpleImage

У меня есть функция, которая получает пиксель от изображения:

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; } 

Чтобы получить каждый пиксель в изображении, я использую этот цикл:

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

Мне интересно, есть ли более быстрый способ сделать это с помощью GD и PHP?

РЕДАКТИРОВАТЬ

Я думаю, что это способ получить значение каждого пикселя из GD без петли PHP.

Это уродливый метод грубой силы, используя imagecolorat () для каждого пикселя. В моих тестах с большими (6.5Mpixel) изображениями он составляет около 3,6 сек., Или примерно на 1,1 сек быстрее, чем более элегантный GD-хак, предлагаемый компанией @cleong. Он также имеет преимущество жестокой простоты и независимости от недокументированного внутреннего формата GD2.

 $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; } 

Существует более быстрый способ, но это очень сложно. Он включает в себя экспорт изображения в формат GD2, а затем прямой доступ к байтам. GD хранит пиксели в кусках, поэтому петля через пиксели не является прямой. Когда все сделано правильно, это дает намного лучшую производительность, так как вы больше не накладываете накладные расходы на вызов функции на каждом пикселе.

Вот код, который у меня есть, который я написал, который захватывает альфа-канал из изображения. Как вы можете видеть, петля не так ужасно очевидна из-за chunking:

  imagesavealpha($image, true); ob_start(); imagegd2($image); $gdRawData = ob_get_clean(); $array = unpack("Nheader/nversion/nimageWidth/nimageHeight/nchunkSize/ndataFormat/ncolumnCount/nrowCount", $gdRawData); $imageWidth = $array['imageWidth']; $imageHeight = $array['imageHeight']; $chunkWidth = $chunkHeight = $array['chunkSize']; $columnCount = $array['columnCount']; $rowCount = $array['rowCount']; $lastColumnWidth = $imageWidth - ($columnCount - 1) * $chunkWidth; $lastRowHeight = $imageHeight - ($rowCount - 1) * $chunkHeight; static $transparencyToAlpha = array("\x7f" => "\x00", "\x7f" => "\x01", "\x7e" => "\x02", "\x7e" => "\x03", "\x7d" => "\x04", "\x7d" => "\x05", "\x7c" => "\x06", "\x7c" => "\x07", "\x7b" => "\x08", "\x7b" => "\x09", "\x7a" => "\x0a", "\x7a" => "\x0b", "\x79" => "\x0c", "\x79" => "\x0d", "\x78" => "\x0e", "\x78" => "\x0f", "\x77" => "\x10", "\x77" => "\x11", "\x76" => "\x12", "\x76" => "\x13", "\x75" => "\x14", "\x75" => "\x15", "\x74" => "\x16", "\x74" => "\x17", "\x73" => "\x18", "\x73" => "\x19", "\x72" => "\x1a", "\x72" => "\x1b", "\x71" => "\x1c", "\x71" => "\x1d", "\x70" => "\x1e", "\x70" => "\x1f", "\x6f" => "\x20", "\x6f" => "\x21", "\x6e" => "\x22", "\x6e" => "\x23", "\x6d" => "\x24", "\x6d" => "\x25", "\x6c" => "\x26", "\x6c" => "\x27", "\x6b" => "\x28", "\x6b" => "\x29", "\x6a" => "\x2a", "\x6a" => "\x2b", "\x69" => "\x2c", "\x69" => "\x2d", "\x68" => "\x2e", "\x68" => "\x2f", "\x67" => "\x30", "\x67" => "\x31", "\x66" => "\x32", "\x66" => "\x33", "\x65" => "\x34", "\x65" => "\x35", "\x64" => "\x36", "\x64" => "\x37", "\x63" => "\x38", "\x63" => "\x39", "\x62" => "\x3a", "\x62" => "\x3b", "\x61" => "\x3c", "\x61" => "\x3d", "\x60" => "\x3e", "\x60" => "\x3f", "\x5f" => "\x40", "\x5f" => "\x41", "\x5e" => "\x42", "\x5e" => "\x43", "\x5d" => "\x44", "\x5d" => "\x45", "\x5c" => "\x46", "\x5c" => "\x47", "\x5b" => "\x48", "\x5b" => "\x49", "\x5a" => "\x4a", "\x5a" => "\x4b", "\x59" => "\x4c", "\x59" => "\x4d", "\x58" => "\x4e", "\x58" => "\x4f", "\x57" => "\x50", "\x57" => "\x51", "\x56" => "\x52", "\x56" => "\x53", "\x55" => "\x54", "\x55" => "\x55", "\x54" => "\x56", "\x54" => "\x57", "\x53" => "\x58", "\x53" => "\x59", "\x52" => "\x5a", "\x52" => "\x5b", "\x51" => "\x5c", "\x51" => "\x5d", "\x50" => "\x5e", "\x50" => "\x5f", "\x4f" => "\x60", "\x4f" => "\x61", "\x4e" => "\x62", "\x4e" => "\x63", "\x4d" => "\x64", "\x4d" => "\x65", "\x4c" => "\x66", "\x4c" => "\x67", "\x4b" => "\x68", "\x4b" => "\x69", "\x4a" => "\x6a", "\x4a" => "\x6b", "\x49" => "\x6c", "\x49" => "\x6d", "\x48" => "\x6e", "\x48" => "\x6f", "\x47" => "\x70", "\x47" => "\x71", "\x46" => "\x72", "\x46" => "\x73", "\x45" => "\x74", "\x45" => "\x75", "\x44" => "\x76", "\x44" => "\x77", "\x43" => "\x78", "\x43" => "\x79", "\x42" => "\x7a", "\x42" => "\x7b", "\x41" => "\x7c", "\x41" => "\x7d", "\x40" => "\x7e", "\x40" => "\x7f", "\x3f" => "\x80", "\x3f" => "\x81", "\x3e" => "\x82", "\x3e" => "\x83", "\x3d" => "\x84", "\x3d" => "\x85", "\x3c" => "\x86", "\x3c" => "\x87", "\x3b" => "\x88", "\x3b" => "\x89", "\x3a" => "\x8a", "\x3a" => "\x8b", "\x39" => "\x8c", "\x39" => "\x8d", "\x38" => "\x8e", "\x38" => "\x8f", "\x37" => "\x90", "\x37" => "\x91", "\x36" => "\x92", "\x36" => "\x93", "\x35" => "\x94", "\x35" => "\x95", "\x34" => "\x96", "\x34" => "\x97", "\x33" => "\x98", "\x33" => "\x99", "\x32" => "\x9a", "\x32" => "\x9b", "\x31" => "\x9c", "\x31" => "\x9d", "\x30" => "\x9e", "\x30" => "\x9f", "\x2f" => "\xa0", "\x2f" => "\xa1", "\x2e" => "\xa2", "\x2e" => "\xa3", "\x2d" => "\xa4", "\x2d" => "\xa5", "\x2c" => "\xa6", "\x2c" => "\xa7", "\x2b" => "\xa8", "\x2b" => "\xa9", "\x2a" => "\xaa", "\x2a" => "\xab", "\x29" => "\xac", "\x29" => "\xad", "\x28" => "\xae", "\x28" => "\xaf", "\x27" => "\xb0", "\x27" => "\xb1", "\x26" => "\xb2", "\x26" => "\xb3", "\x25" => "\xb4", "\x25" => "\xb5", "\x24" => "\xb6", "\x24" => "\xb7", "\x23" => "\xb8", "\x23" => "\xb9", "\x22" => "\xba", "\x22" => "\xbb", "\x21" => "\xbc", "\x21" => "\xbd", "\x20" => "\xbe", "\x20" => "\xbf", "\x1f" => "\xc0", "\x1f" => "\xc1", "\x1e" => "\xc2", "\x1e" => "\xc3", "\x1d" => "\xc4", "\x1d" => "\xc5", "\x1c" => "\xc6", "\x1c" => "\xc7", "\x1b" => "\xc8", "\x1b" => "\xc9", "\x1a" => "\xca", "\x1a" => "\xcb", "\x19" => "\xcc", "\x19" => "\xcd", "\x18" => "\xce", "\x18" => "\xcf", "\x17" => "\xd0", "\x17" => "\xd1", "\x16" => "\xd2", "\x16" => "\xd3", "\x15" => "\xd4", "\x15" => "\xd5", "\x14" => "\xd6", "\x14" => "\xd7", "\x13" => "\xd8", "\x13" => "\xd9", "\x12" => "\xda", "\x12" => "\xdb", "\x11" => "\xdc", "\x11" => "\xdd", "\x10" => "\xde", "\x10" => "\xdf", "\x0f" => "\xe0", "\x0f" => "\xe1", "\x0e" => "\xe2", "\x0e" => "\xe3", "\x0d" => "\xe4", "\x0d" => "\xe5", "\x0c" => "\xe6", "\x0c" => "\xe7", "\x0b" => "\xe8", "\x0b" => "\xe9", "\x0a" => "\xea", "\x0a" => "\xeb", "\x09" => "\xec", "\x09" => "\xed", "\x08" => "\xee", "\x08" => "\xef", "\x07" => "\xf0", "\x07" => "\xf1", "\x06" => "\xf2", "\x06" => "\xf3", "\x05" => "\xf4", "\x05" => "\xf5", "\x04" => "\xf6", "\x04" => "\xf7", "\x03" => "\xf8", "\x03" => "\xf9", "\x02" => "\xfa", "\x02" => "\xfb", "\x01" => "\xfc", "\x01" => "\xfd", "\x00" => "\xfe", "\x00" => "\xff"); $alphaDataSize = $imageWidth * $imageHeight; $alphaData = str_repeat("\x00", $alphaDataSize); // loop through all rows for($r = 0, $j = 23; $r < $rowCount; $r++) { $rowHeight = ($r == $rowCount - 1) ? $lastRowHeight : $chunkHeight; // loop through chunks in each row for($c = 0; $c < $columnCount; $c++) { $columnWidth = ($c == $columnCount - 1) ? $lastColumnWidth : $chunkWidth; $firstY = $r * $chunkHeight; $lastY = $firstY + $rowHeight; // loop through scanlines in each chunk for($y = $firstY; $y < $lastY; $y++) { $firstX = $c * $chunkWidth; $firstAlphaPosition = $y * $imageWidth + $firstX; $lastAlphaPosition = $firstAlphaPosition + $columnWidth; // loop through each pixel in each chunk scanline for($i = $firstAlphaPosition; $i < $lastAlphaPosition; $i++, $j+= 4) { $alphaData[$i] = $transparencyToAlpha[$gdRawData[$j]]; } } } } 

Каждый пиксель состоит из четырех байтов: альфа, красный, зеленый и синий. Здесь я только фиксирую первый байт.