もっと
This commit is contained in:
@@ -96,7 +96,7 @@ class Png implements ImageInterface {
|
||||
public array $frames = [];
|
||||
private ?array $currentFrame = null;
|
||||
|
||||
// TODO: 残り: sBIT, cICP, mDCV, cLLI, iTXt, hIST, sPLT, tIME
|
||||
// TODO: 残り: sBIT, iTXt, hIST, sPLT, tIME
|
||||
public function parse(string $file): \stdClass {
|
||||
$png = new \stdClass();
|
||||
$fp = fopen($file, 'rb');
|
||||
@@ -114,6 +114,8 @@ class Png implements ImageInterface {
|
||||
|
||||
// N = ビッグエンディアン(4ビット)
|
||||
$this->IHDR = new \stdClass;
|
||||
$this->IHDR->name = 'IHDR';
|
||||
$this->IHDR->length = $length;
|
||||
$this->IHDR->width = unpack('N', substr($data, 0, 4))[1];
|
||||
$this->IHDR->height = unpack('N', substr($data, 4, 4))[1];
|
||||
$this->IHDR->bitDepth = ord($data[8]); // 1, 2, 4, 8, 16
|
||||
@@ -154,6 +156,8 @@ next_chunk:
|
||||
}
|
||||
|
||||
$this->PLTE = new \stdClass;
|
||||
$this->PLTE->name = 'PLTE';
|
||||
$this->PLTE->length = $length;
|
||||
$this->PLTE->palette = $palette;
|
||||
$this->PLTE->crc = $crc;
|
||||
$this->PLTE->crc32 = unpack('N', $crc)[1];
|
||||
@@ -163,6 +167,8 @@ next_chunk:
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x74\x52\x4e\x53") { // tRNS
|
||||
$this->tRNS = new \stdClass;
|
||||
$this->tRNS->name = 'tRNS';
|
||||
$this->tRNS->length = $length;
|
||||
$vals = [];
|
||||
$bytes = $this->IHDR->colorType === 2 ? 3 : 1;
|
||||
for ($i = 0; $i < $length; $i += $bytes) {
|
||||
@@ -181,6 +187,8 @@ next_chunk:
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x63\x48\x52\x4d") { // cHRM
|
||||
$this->cHRM = new \stdClass;
|
||||
$this->cHRM->name = 'cHRM';
|
||||
$this->cHRM->length = $length;
|
||||
$this->cHRM->whitePointX = unpack('N', substr($data, 0, 4))[1];
|
||||
$this->cHRM->whitePointY = unpack('N', substr($data, 4, 4))[1];
|
||||
$this->cHRM->redX = unpack('N', substr($data, 8, 4))[1];
|
||||
@@ -196,6 +204,8 @@ next_chunk:
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x67\x41\x4d\x41") { // gAMA
|
||||
$this->gAMA = new \stdClass;
|
||||
$this->gAMA->name = 'gAMA';
|
||||
$this->gAMA->length = $length;
|
||||
$this->gAMA->value = unpack('N', $data)[1];
|
||||
$this->gAMA->crc = $crc;
|
||||
$this->gAMA->crc32 = unpack('N', $crc)[1];
|
||||
@@ -204,6 +214,8 @@ next_chunk:
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x69\x43\x43\x50") { // iCCP
|
||||
$this->iCCP = new \stdClass;
|
||||
$this->iCCP->name = 'iCCP';
|
||||
$this->iCCP->length = $length;
|
||||
|
||||
$nullPos = strpos($data, "\0");
|
||||
if ($nullPos === false || $nullPos < 1 || $nullPos > 79) {
|
||||
@@ -235,11 +247,18 @@ iccp_crc:
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x73\x42\x49\x54") { // sBIT
|
||||
$this->sBIT = new \stdClass;
|
||||
kys('sBIT');
|
||||
$this->sBIT->name = 'sBIT';
|
||||
$this->sBIT->length = $length;
|
||||
kys(['sBIT', $length, bin2hex($data)]);
|
||||
$this->sBIT->crc = $crc;
|
||||
$this->sBIT->crc32 = unpack('N', $crc)[1];
|
||||
$this->sBIT->crcHex = bin2hex($crc);
|
||||
$png->significantBits = $this->sBIT;
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x73\x52\x47\x42") { // sRGB
|
||||
$this->sRGB = new \stdClass;
|
||||
$this->sRGB->name = 'sRGB';
|
||||
$this->sRGB->length = $length;
|
||||
$this->sRGB->intent = ord($data);
|
||||
$name = [
|
||||
0 => 'Perceptual',
|
||||
@@ -255,34 +274,85 @@ iccp_crc:
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x63\x49\x43\x50") { // cICP
|
||||
$this->cICP = new \stdClass;
|
||||
kys('cICP');
|
||||
$this->cICP->name = 'cICP';
|
||||
$this->cICP->length = $length;
|
||||
$this->cICP->colorPrimaries = ord($data[0]);
|
||||
$this->cICP->transferFunction = ord($data[1]);
|
||||
$this->cICP->matrixCoefficients = ord($data[2]);
|
||||
$this->cICP->videoFullRangeFlag = ord($data[3]);
|
||||
$this->cICP->crc = $crc;
|
||||
$this->cICP->crc32 = unpack('N', $crc)[1];
|
||||
$this->cICP->crcHex = bin2hex($crc);
|
||||
$png->videoSignalTypeId = $this->cICP;
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x6d\x44\x43\x56") { // mDCV
|
||||
$this->mDCV = new \stdClass;
|
||||
kys('mDCV');
|
||||
$this->mDCV->name = 'mDCV';
|
||||
$this->mDCV->length = $length;
|
||||
|
||||
$u16 = fn($off) => unpack('n', substr($data, $off, 2))[1];
|
||||
$u32 = fn($off) => unpack('N', substr($data, $off, 4))[1];
|
||||
$this->mDCV->primaries = [
|
||||
'red' => ['x' => $u16(0), 'y' => $u16(2)],
|
||||
'green' => ['x' => $u16(4), 'y' => $u16(6)],
|
||||
'blue' => ['x' => $u16(8), 'y' => $u16(10)],
|
||||
];
|
||||
$this->mDCV->whitePoint = [
|
||||
'x' => $u16(12),
|
||||
'y' => $u16(14),
|
||||
];
|
||||
$this->mDCV->luminance = [
|
||||
'max' => $u16(16) * 0.0001,
|
||||
'min' => $u16(20) * 0.0001,
|
||||
'maxRaw' => $u16(16),
|
||||
'minRaw' => $u16(20),
|
||||
];
|
||||
$this->mDCV->crc = $crc;
|
||||
$this->mDCV->crc32 = unpack('N', $crc)[1];
|
||||
$this->mDCV->crcHex = bin2hex($crc);
|
||||
$png->masterDisplayColorVolume = $this->mDCV;
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x63\x4c\x4c\x49") { // cLLI
|
||||
$this->cLLI = new \stdClass;
|
||||
kys('cLLI');
|
||||
$this->cLLI->name = 'cLLI';
|
||||
$this->cLLI->length = $length;
|
||||
$this->cLLI->maxCCL = unpack('N', substr($data, 0, 4))[1] * 0.0001;
|
||||
$this->cLLI->maxCCLRaw = unpack('N', substr($data, 0, 4))[1];
|
||||
$this->cLLI->maxFALL = unpack('N', substr($data, 4, 4))[1] * 0.0001;
|
||||
$this->cLLI->maxFALLRaw = unpack('N', substr($data, 4, 4))[1];
|
||||
$this->cLLI->crc = $crc;
|
||||
$this->cLLI->crc32 = unpack('N', $crc)[1];
|
||||
$this->cLLI->crcHex = bin2hex($crc);
|
||||
$png->contentLightLevelInfo = $this->cLLI;
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x74\x45\x58\x74") { // tEXt
|
||||
if (!isset($png->textualData)) $png->textualData = [];
|
||||
$this->tEXt = new \stdClass;
|
||||
$this->tEXt->name = 'tEXt';
|
||||
$this->tEXt->length = $length;
|
||||
$this->tEXt->text = $data;
|
||||
$this->tEXt->crc = $crc;
|
||||
$this->tEXt->crc32 = unpack('N', $crc)[1];
|
||||
$this->tEXt->crcHex = bin2hex($crc);
|
||||
$png->textualData = $this->tEXt;
|
||||
$png->textualData[] = $this->tEXt;
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x69\x54\x58\x74") { // iTXt
|
||||
if (!isset($png->internationalTextualData)) $png->textualData = [];
|
||||
$this->iTXt = new \stdClass;
|
||||
kys('iTXt');
|
||||
$png->internationalTextualData = $this->iTXt;
|
||||
$this->iTXt->name = 'iTXt';
|
||||
$this->iTXt->length = $length;
|
||||
kys(['iTXt', $length, bin2hex($data)]);
|
||||
$this->iTXt->crc = $crc;
|
||||
$this->iTXt->crc32 = unpack('N', $crc)[1];
|
||||
$this->iTXt->crcHex = bin2hex($crc);
|
||||
$png->internationalTextualData[] = $this->iTXt;
|
||||
kys($png);
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x7a\x54\x58\x74") { // zTXt
|
||||
if (!isset($png->compressedTextualData)) $png->textualData = [];
|
||||
$this->zTXt = new \stdClass;
|
||||
$this->zTXt->name = 'zTXt';
|
||||
$this->zTXt->length = $length;
|
||||
|
||||
$nullPos = strpos($data, "\0");
|
||||
if ($nullPos === false || $nullPos < 1 || $nullPos > 79) {
|
||||
@@ -325,10 +395,12 @@ zTXt_crc:
|
||||
$this->zTXt->crc = $crc;
|
||||
$this->zTXt->crc32 = unpack('N', $crc)[1];
|
||||
$this->zTXt->crcHex = bin2hex($crc);
|
||||
$png->compressedTextualData = $this->zTXt;
|
||||
$png->compressedTextualData[] = $this->zTXt;
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x62\x4b\x47\x44") { // bKGD
|
||||
$this->bKGD = new \stdClass;
|
||||
$this->bKGD->name = 'bKGD';
|
||||
$this->bKGD->length = $length;
|
||||
if ($this->IHDR->colorType === 2 || $this->IHDR->colorType === 6) {
|
||||
$r = (ord($data[0]) << 8) | ord($data[1]);
|
||||
$g = (ord($data[2]) << 8) | ord($data[3]);
|
||||
@@ -363,11 +435,19 @@ zTXt_crc:
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x68\x49\x53\x54") { // hIST
|
||||
$this->hIST = new \stdClass;
|
||||
kys('hIST');
|
||||
$this->hIST->name = 'hIST';
|
||||
$this->hIST->length = $length;
|
||||
kys(['hIST', $length, bin2hex($data)]);
|
||||
$this->hIST->crc = $crc;
|
||||
$this->hIST->crc32 = unpack('N', $crc)[1];
|
||||
$this->hIST->crcHex = bin2hex($crc);
|
||||
$png->imageHistogram = $this->hIST;
|
||||
kys($png);
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x70\x48\x59\x73") { // pHYs
|
||||
$this->pHYs = new \stdClass;
|
||||
$this->pHYs->name = 'pHYs';
|
||||
$this->pHYs->length = $length;
|
||||
$this->pHYs->x = unpack('N', substr($data, 0, 4))[1];
|
||||
$this->pHYs->y = unpack('N', substr($data, 4, 4))[1];
|
||||
$unit = [
|
||||
@@ -383,11 +463,19 @@ zTXt_crc:
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x73\x50\x4c\x54") { // sPLT
|
||||
$this->sPLT = new \stdClass;
|
||||
kys('sPLT');
|
||||
$this->sPLT->name = 'sPLT';
|
||||
$this->sPLT->length = $length;
|
||||
kys(['sPLT', $length, bin2hex($data)]);
|
||||
$this->sPLT->crc = $crc;
|
||||
$this->sPLT->crc32 = unpack('N', $crc)[1];
|
||||
$this->sPLT->crcHex = bin2hex($crc);
|
||||
$png->suggestedPalette = $this->sPLT;
|
||||
kys($png);
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x65\x58\x49\x66") { // eXIf
|
||||
$this->eXIf = new \stdClass;
|
||||
$this->eXIf->name = 'eXIf';
|
||||
$this->eXIf->length = $length;
|
||||
|
||||
if (strlen($data) < 8) {
|
||||
$this->eXIf->valid = false;
|
||||
@@ -423,11 +511,19 @@ exif_crc:
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x74\x49\x4d\x45") { // tIME
|
||||
$this->tIME = new \stdClass;
|
||||
kys('tIME');
|
||||
$this->tIME->name = 'tIME';
|
||||
$this->tIME->length = $length;
|
||||
kys(['tIME', $length, bin2hex($data)]);
|
||||
$this->tIME->crc = $crc;
|
||||
$this->tIME->crc32 = unpack('N', $crc)[1];
|
||||
$this->tIME->crcHex = bin2hex($crc);
|
||||
$png->lastModificationTime = $this->tIME;
|
||||
kys($png);
|
||||
goto next_chunk;
|
||||
} else if ($nextChunk === "\x61\x63\x54\x4c") { // acTL
|
||||
$this->acTL = new \stdClass;
|
||||
$this->acTL->name = 'acTL';
|
||||
$this->acTL->length = $length;
|
||||
$this->acTL->numFrames = unpack('N', substr($data, 0, 4))[1];
|
||||
$this->acTL->numPlays = unpack('N', substr($data, 4, 4))[1];
|
||||
$this->acTL->crc = $crc;
|
||||
@@ -439,6 +535,8 @@ exif_crc:
|
||||
if ($this->currentFrame !== null) $this->frames[] = (object)$this->currentFrame;
|
||||
|
||||
$this->currentFrame = [
|
||||
'name' => 'fcTL',
|
||||
'length' => $length,
|
||||
'sequenceNumber' => unpack('N', substr($data, 0, 4))[1],
|
||||
'width' => unpack('N', substr($data, 4, 4))[1],
|
||||
'height' => unpack('N', substr($data, 8, 4))[1],
|
||||
@@ -467,6 +565,8 @@ exif_crc:
|
||||
}
|
||||
|
||||
$compressedData = ($nextChunk === "\x66\x64\x41\x54") ? substr($data, 4) : $data;
|
||||
$this->currentFrame['name'] = 'fdAT';
|
||||
$this->currentFrame['length'] = $length;
|
||||
$this->currentFrame['data'] = $compressedData;
|
||||
$this->currentFrame['dataBase64'] = base64_encode($compressedData);
|
||||
$this->currentFrame['dataHex'] = bin2hex($compressedData);
|
||||
@@ -477,6 +577,7 @@ exif_crc:
|
||||
$this->currentFrame['crcHex'] = bin2hex($crc);
|
||||
|
||||
if ($nextChunk === "\x49\x44\x41\x54") {
|
||||
$this->currentFrame['name'] = 'IDAT';
|
||||
$this->frames[] = (object)$this->currentFrame;
|
||||
$this->currentFrame = null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user