I need an easy way to detect what PNG is being being uploaded. I tried getimagesize but it returns bits 8 for both PNG8 and PNG24.
Anyone have an idea how to detect it an image is PNG8, aka bit depth of 8. Thanks!
Try this to detect PNG8, PNG24 and PNG32:
<?php
$file = new SplFileObject('png8.png');
$realPath = $file->getRealPath();
if ($realPath === false) {
throw new RuntimeException(sprintf('File not found: %s', $file->getFilename()));
}
$file->rewind();
if ($file->fread(4) !== chr(0x89) . 'PNG') {
// This is not a PNG
throw new RuntimeException(sprintf('Invalid PNG file: %s', $file->getFilename()));
}
$file->rewind();
$file->fread(8 + 4);
$idr = $file->fread(4);
// Make sure we have an IHDR
if ($idr !== 'IHDR') {
throw new RuntimeException('No PNG IHDR header found, invalid PNG file.');
}
// PNG actually stores Width and height integers in big-endian.
$width = unpack('N', (string)$file->fread(4))[1];
$height = unpack('N', (string)$file->fread(4))[1];
// Bit depth: 1 byte
// Bit depth is a single-byte integer giving the number of bits per sample or
// per palette index (not per pixel).
//
// Valid values are 1, 2, 4, 8, and 16, although not all values are allowed for all color types.
$bitDepth = ord((string)$file->fread(1));
// Pixel format
// https://en.wikipedia.org/wiki/Portable_Network_Graphics#Pixel_format
// Color type is a single-byte integer that describes the interpretation of the image data.
// Color type codes represent sums of the following values:
// 1 (palette used), 2 (color used), and 4 (alpha channel used).
//
// Valid values are 0, 2, 3, 4, and 6.
$colorType = ord((string)$file->fread(1));
$colorTypes = [
0 => 'Greyscale',
2 => 'Truecolour',
3 => 'Indexed-colour',
4 => 'Greyscale with alpha',
6 => 'Truecolour with alpha',
];
$colorTypeText = $colorTypes[$colorType];
$pngType = '?';
// If the bitdepth is 8 and the colortype is 3 (Indexed-colour) you have a PNG8
if ($bitDepth === 8 && $colorType === 3) {
$pngType = 'PNG8';
}
// If the bitdepth is 8 and colortype is 2 (Truecolour) you have a PNG24.
if ($bitDepth === 8 && $colorType === 2) {
$pngType = 'PNG24';
}
// If the bitdepth is 8 and colortype is 6 (Truecolour with alpha) you have a PNG32.
if ($bitDepth === 8 && $colorType === 6) {
$pngType = 'PNG32';
}
echo sprintf('Width: %s, Height: %s, Bit-Depth: %s, Color-Type: %s (%s), Type: %s',
$width,
$height,
$bitDepth,
$colorType,
$colorTypeText,
$pngType
);
Output:
Width: 1500, Height: 500, Bit-Depth: 8, Color-Type: 3 (Indexed-colour), Type: PNG8
$image = new \Imagick("mypng.png"); dump($image->getImageProperties()) ;
"png:IHDR.bit-depth-orig" => "8" "png:IHDR.bit_depth" => "8"
– Manzolo