Skip to content

Commit ede7715

Browse files
committed
Begin to manage PNG processing.
1 parent 7f00367 commit ede7715

File tree

11 files changed

+567
-6
lines changed

11 files changed

+567
-6
lines changed

.travis.yml

-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ php:
88

99
before_install:
1010
- sudo apt-get install --yes openjdk-7-jdk
11-
- java -version
1211
- curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
1312
- sudo apt-get install --yes nodejs
1413
- npm install -g grunt-cli
@@ -18,9 +17,6 @@ install:
1817
- composer install
1918

2019
script:
21-
- ls /home/travis/build/gomoob/php-metadata-extractor/src/main/resources/jars
22-
- java -classpath '/home/travis/build/gomoob/php-metadata-extractor/src/main/resources/jars/metadata-extractor-2.9.1.jar' com.drew.imaging.ImageMetadataReader '/home/travis/build/gomoob/php-metadata-extractor/src/test/resources/elephant.jpg'
23-
- java -classpath /home/travis/build/gomoob/php-metadata-extractor/src/main/resources/jars/metadata-extractor-2.9.1.jar com.drew.imaging.ImageMetadataReader '/home/travis/build/gomoob/php-metadata-extractor/src/test/resources/elephant.jpg'
2420
- grunt
2521

2622
after_script:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/**
4+
* Copyright 2016 SARL GOMOOB. All rights reserved.
5+
*/
6+
namespace Gomoob\Java\Lang;
7+
8+
/**
9+
* Thrown to indicate that a method has been passed an illegal or inappropriate argument.
10+
*
11+
* @author Baptiste GAILLARD ([email protected])
12+
*/
13+
class IllegalArgumentException extends \Exception
14+
{
15+
// Empty
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/**
4+
* Copyright 2016 SARL GOMOOB. All rights reserved.
5+
*/
6+
namespace Gomoob\Java\Lang;
7+
8+
/**
9+
* RuntimeException is the superclass of those exceptions that can be thrown during the normal operation of the Java
10+
* Virtual Machine.
11+
*
12+
* RuntimeException and its subclasses are unchecked exceptions. Unchecked exceptions do not need to be declared in a
13+
* method or constructor's throws clause if they can be thrown by the execution of the method or constructor and
14+
* propagate outside th
15+
*
16+
* @author Baptiste GAILLARD ([email protected])
17+
*/
18+
class RuntimeException extends \Exception
19+
{
20+
// Empty
21+
}

src/main/php/Gomoob/MetadataExtractor/Imaging/ImageMetadataReader.php

+51-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
use Gomoob\MetadataExtractor\Metadata\Exif\Makernotes\CanonMakernoteDirectory;
3232
use Gomoob\MetadataExtractor\Metadata\Exif\GpsDirectory;
3333
use Gomoob\MetadataExtractor\Lang\Rational;
34+
use Gomoob\MetadataExtractor\Metadata\Png\PngDirectory;
35+
use Gomoob\MetadataExtractor\Imaging\Png\PngChunkType;
3436

3537
/**
3638
* Reads metadata from any supported file format.
@@ -631,12 +633,60 @@ private static function createDirectoryWithName($directoryName)
631633
case 'Photoshop':
632634
$directory = new PhotoshopDirectory();
633635
break;
636+
case 'PNG-IHDR':
637+
$directory = new PngDirectory('IHDR');
638+
break;
639+
case 'PNG-PLTE':
640+
$directory = new PngDirectory('PLTE');
641+
break;
642+
case 'PNG-IDAT':
643+
$directory = new PngDirectory('IDAT');
644+
break;
645+
case 'PNG-IEND':
646+
$directory = new PngDirectory('IEND');
647+
break;
648+
case 'PNG-cHRM':
649+
$directory = new PngDirectory('cHRM');
650+
break;
651+
case 'PNG-gAMA':
652+
$directory = new PngDirectory('gAMA');
653+
break;
654+
case 'PNG-iCCP':
655+
$directory = new PngDirectory('iCCP');
656+
break;
657+
case 'PNG-sBIT':
658+
$directory = new PngDirectory('sBIT');
659+
break;
660+
case 'PNG-sRGB':
661+
$directory = new PngDirectory('sRGB');
662+
break;
663+
case 'PNG-bKGD':
664+
$directory = new PngDirectory('bKGD');
665+
break;
666+
case 'PNG-hIST':
667+
$directory = new PngDirectory('hIST');
668+
break;
669+
case 'PNG-tRNS':
670+
$directory = new PngDirectory('tRNS');
671+
break;
672+
case 'PNG-pHYs':
673+
$directory = new PngDirectory('pHYs');
674+
break;
675+
case 'PNG-sPLT':
676+
$directory = new PngDirectory('sPLT');
677+
break;
678+
case 'PNG-tIME':
679+
$directory = new PngDirectory('tIME');
680+
break;
681+
case 'PNG-iTXt':
682+
$directory = new PngDirectory('iTXt');
683+
break;
634684
case 'XMP':
635685
$directory = new XmpDirectory();
636686
break;
637687
default:
638688
// TODO: To be enabled in testing
639-
// throw new \RuntimeException('Unknown directory name \'' . $directoryName . '\' !');
689+
throw new \RuntimeException('Unknown directory name \'' . $directoryName . '\' !');
640690
}
641691

642692
return $directory;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
<?php
2+
3+
/**
4+
* gomoob/php-metadata-extractor
5+
*
6+
* @copyright Copyright (c) 2016, GOMOOB SARL (http://gomoob.com)
7+
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE.md file)
8+
*/
9+
namespace Gomoob\MetadataExtractor\Imaging\Png;
10+
11+
use Gomoob\Java\Lang\IllegalArgumentException;
12+
13+
/**
14+
* @author Baptiste GAILLARD ([email protected])
15+
*/
16+
class PngChunkType
17+
{
18+
private $identifiersAllowingMultiples = ['IDAT', 'sPLT', 'iTXt', 'tEXt', 'zTXt'];
19+
20+
//
21+
// Standard critical chunks
22+
//
23+
/**
24+
* Denotes a critical {@link PngChunk} that contains basic information about the PNG image.
25+
* This must be the first chunk in the data sequence, and may only occur once.
26+
*
27+
* The format is:
28+
* * <b>pixel width</b> 4 bytes, unsigned and greater than zero
29+
* * <b>pixel height</b> 4 bytes, unsigned and greater than zero>
30+
* * <b>bit depth</b> 1 byte, number of bits per sample or per palette index (not per pixel)
31+
* * <b>color type</b> 1 byte, maps to {@link PngColorType} enum
32+
* * <b>compression method</b> 1 byte, currently only a value of zero (deflate/inflate) is in the standard
33+
* * <b>filter method</b> 1 byte, currently only a value of zero (adaptive filtering with five basic filter types)
34+
* is in the standard</li>
35+
* * <b>interlace method</b> 1 byte, indicates the transmission order of image data, currently only 0 (no interlace)
36+
* and 1 (Adam7 interlace) are in the standard</li>
37+
*/
38+
public static $IHDR = null;
39+
40+
/**
41+
* Denotes a critical {@link PngChunk} that contains palette entries.
42+
* This chunk should only appear for a {@link PngColorType} of <code>IndexedColor</code>,
43+
* and may only occur once in the PNG data sequence.
44+
* <p>
45+
* The chunk contains between one and 256 entries, each of three bytes:
46+
* <ul>
47+
* <li><b>red</b> 1 byte</li>
48+
* <li><b>green</b> 1 byte</li>
49+
* <li><b>blue</b> 1 byte</li>
50+
* </ul>
51+
* The number of entries is determined by the chunk length. A chunk length indivisible by three is an error.
52+
*/
53+
public static $PLTE = null;
54+
public static $IDAT = null;
55+
public static $IEND = null;
56+
57+
//
58+
// Standard ancillary chunks
59+
//
60+
public static $cHRM = null;
61+
public static $gAMA = null;
62+
public static $iCCP = null;
63+
public static $sBIT = null;
64+
public static $sRGB = null;
65+
public static $bKGD = null;
66+
public static $hIST = null;
67+
public static $tRNS = null;
68+
public static $pHYs = null;
69+
public static $sPLT = null;
70+
public static $tIME = null;
71+
public static $iTXt = null;
72+
73+
/**
74+
* Denotes an ancillary {@link PngChunk} that contains textual data, having first a keyword and then a value.
75+
* If multiple text data keywords are needed, then multiple chunks are included in the PNG data stream.
76+
* <p>
77+
* The format is:
78+
* <ul>
79+
* <li><b>keyword</b> 1-79 bytes</li>
80+
* <li><b>null separator</b> 1 byte (\0)</li>
81+
* <li><b>text string</b> 0 or more bytes</li>
82+
* </ul>
83+
* Text is interpreted according to the Latin-1 character set [ISO-8859-1].
84+
* Newlines should be represented by a single linefeed character (0x9).
85+
*/
86+
public static $tEXt = null;
87+
public static $zTXt = null;
88+
89+
private $bytes;
90+
private $multipleAllowed;
91+
92+
public function __construct($identifierOrBytes, $multipleAllowed = null)
93+
{
94+
if (is_string($identifierOrBytes)) {
95+
$this->multipleAllowed = $multipleAllowed;
96+
try {
97+
$splitted = str_split($identifierOrBytes);
98+
$bytes = [];
99+
100+
foreach ($splitted as $s) {
101+
$bytes[] = ord($s[0]);
102+
}
103+
$this->validateBytes($bytes);
104+
$this->bytes = $bytes;
105+
} catch (UnsupportedEncodingException $e) {
106+
throw new IllegalArgumentException("Unable to convert string code to bytes.");
107+
}
108+
} elseif (is_array($identifierOrBytes)) {
109+
$this->validateBytes($bytes);
110+
$this->bytes = $bytes;
111+
$this->multipleAllowed = in_array($this->getIdentifier(), $this->identifiersAllowingMultiples);
112+
}
113+
}
114+
115+
private static function validateBytes($bytes)
116+
{
117+
if (count($bytes) != 4) {
118+
throw new IllegalArgumentException("PNG chunk type identifier must be four bytes in length");
119+
}
120+
121+
foreach ($bytes as $b) {
122+
if (!static::isValidByte($b)) {
123+
throw new IllegalArgumentException("PNG chunk type identifier may only contain alphabet characters");
124+
}
125+
}
126+
}
127+
128+
public function isCritical()
129+
{
130+
return $this->isUpperCase($this->bytes[0]);
131+
}
132+
133+
public function isAncillary()
134+
{
135+
return !$this->isCritical();
136+
}
137+
138+
public function isPrivate()
139+
{
140+
return $this->isUpperCase($this->bytes[1]);
141+
}
142+
143+
public function isSafeToCopy()
144+
{
145+
return $this->isLowerCase($this->bytes[3]);
146+
}
147+
148+
public function areMultipleAllowed()
149+
{
150+
return $this->multipleAllowed;
151+
}
152+
153+
private static function isLowerCase($b)
154+
{
155+
return ($b & (1 << 5)) != 0;
156+
}
157+
158+
private static function isUpperCase($b)
159+
{
160+
return ($b & (1 << 5)) == 0;
161+
}
162+
163+
private static function isValidByte($b)
164+
{
165+
return ($b >= 65 && $b <= 90) || ($b >= 97 && $b <= 122);
166+
}
167+
168+
public function getIdentifier()
169+
{
170+
try {
171+
$identifier = '';
172+
foreach ($this->bytes as $b) {
173+
$identifier .= chr($b);
174+
}
175+
176+
return $identifier;
177+
} catch (UnsupportedEncodingException $e) {
178+
// The constructor should ensure that we're always able to encode the bytes in ASCII.
179+
// noinspection ConstantConditions
180+
assert(false);
181+
return "Invalid object instance";
182+
}
183+
}
184+
185+
public function toString()
186+
{
187+
return $this->getIdentifier();
188+
}
189+
190+
public function equals($o)
191+
{
192+
if ($this === $o) {
193+
return true;
194+
}
195+
196+
if ($o === null || $this->getClass() !== $o->getClass()) {
197+
return false;
198+
}
199+
200+
$that = $o;
201+
202+
return Arrays.equals($this->bytes, $that->bytes);
203+
}
204+
205+
public function hashCode()
206+
{
207+
return Arrays.hashCode($this->bytes);
208+
}
209+
}
210+
211+
/* FIXME: Will be fixed when static initializers will be added in PHP
212+
*
213+
* ----------------------------------------------------------------------
214+
* FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE
215+
* ----------------------------------------------------------------------
216+
* 1 | WARNING | A file should declare new symbols (classes, functions,
217+
* | | constants, etc.) and cause no other side effects, or
218+
* | | it should execute logic with side effects, but should
219+
* | | not do both. The first symbol is defined on line 16
220+
* | | and the first side effect is on line 212.
221+
* ----------------------------------------------------------------------
222+
PngChunkType::$IHDR = new PngChunkType('IHDR');
223+
PngChunkType::$PLTE = new PngChunkType("PLTE");
224+
PngChunkType::$IDAT = new PngChunkType("IDAT", true);
225+
PngChunkType::$IEND = new PngChunkType("IEND");
226+
PngChunkType::$cHRM = new PngChunkType("cHRM");
227+
PngChunkType::$gAMA = new PngChunkType("gAMA");
228+
PngChunkType::$iCCP = new PngChunkType("iCCP");
229+
PngChunkType::$sBIT = new PngChunkType("sBIT");
230+
PngChunkType::$sRGB = new PngChunkType("sRGB");
231+
PngChunkType::$bKGD = new PngChunkType("bKGD");
232+
PngChunkType::$hIST = new PngChunkType("hIST");
233+
PngChunkType::$tRNS = new PngChunkType("tRNS");
234+
PngChunkType::$pHYs = new PngChunkType("pHYs");
235+
PngChunkType::$sPLT = new PngChunkType("sPLT", true);
236+
PngChunkType::$tIME = new PngChunkType("tIME");
237+
PngChunkType::$iTXt = new PngChunkType("iTXt", true);
238+
PngChunkType::$tEXt = new PngChunkType("tEXt", true);
239+
PngChunkType::$zTXt = new PngChunkType("zTXt", true);
240+
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/**
4+
* gomoob/php-metadata-extractor
5+
*
6+
* @copyright Copyright (c) 2016, GOMOOB SARL (http://gomoob.com)
7+
* @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE.md file)
8+
*/
9+
namespace Gomoob\MetadataExtractor\Metadata\Png;
10+
11+
use Gomoob\MetadataExtractor\Metadata\TagDescriptor;
12+
13+
/**
14+
* @author Baptiste GAILLARD ([email protected])
15+
*/
16+
class PngDescriptor extends TagDescriptor
17+
{
18+
19+
}

0 commit comments

Comments
 (0)