问题
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!
回答1:
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
来源:https://stackoverflow.com/questions/57547818/php-detect-png8-or-png24