-
Notifications
You must be signed in to change notification settings - Fork 26
/
Iptc.php
executable file
·403 lines (369 loc) · 10.8 KB
/
Iptc.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
<?php
/**
* Class to manipulate EXIF and image IPTC
*
* @category Image
* @package Iptc
* @author Bruno Thiago Leite Agutoli <bruno.agutoli@gmail.com>
* @license https://github.com/agutoli/Image_Iptc/blob/master/MIT-LICENSE.txt
* @link https://github.com/agutoli/Image_Iptc/
*/
/**
* Dependencies
*/
require 'Iptc/Exception.php';
/**
* Class to manipulate EXIF and image IPTC
*
* @category Image
* @package Iptc
* @author Bruno Thiago Leite Agutoli <bruno.agutoli@gmail.com>
* @license https://github.com/agutoli/Image_Iptc/blob/master/MIT-LICENSE.txt
* @link https://github.com/agutoli/Image_Iptc/
*/
class Iptc
{
const OBJECT_NAME = '005';
const EDIT_STATUS = '007';
const PRIORITY = '010';
const CATEGORY = '015';
const SUPPLEMENTAL_CATEGORY = '020';
const FIXTURE_IDENTIFIER = '022';
const KEYWORDS = '025';
const RELEASE_DATE = '030';
const RELEASE_TIME = '035';
const SPECIAL_INSTRUCTIONS = '040';
const REFERENCE_SERVICE = '045';
const REFERENCE_DATE = '047';
const REFERENCE_NUMBER = '050';
const CREATED_DATE = '055';
const CREATED_TIME = '060';
const ORIGINATING_PROGRAM = '065';
const PROGRAM_VERSION = '070';
const OBJECT_CYCLE = '075';
const CREATOR = '080';
const CITY = '090';
const PROVINCE_STATE = '095';
const COUNTRY_CODE = '100';
const COUNTRY = '101';
const ORIGINAL_TRANSMISSION_REFERENCE = '103';
const HEADLINE = '105';
const CREDIT = '110';
const SOURCE = '115';
const COPYRIGHT_STRING = '116';
const CAPTION = '120';
const LOCAL_CAPTION = '121';
const CAPTION_WRITER = '122';
/**
* variable that stores the IPTC tags
*
* @var array
*/
private $_meta = array();
/**
* This variable was checks whether any tag class setada
*
* @var boolean
*/
private $_hasMeta = false;
/**
* allowed extensions
*
* @var array
*/
private $_allowedExt = array('jpg', 'jpeg', 'pjpeg');
/**
* Image name ex. /home/user/image.jpg
*
* @var String
*/
private $_filename;
/**
* Constructor class
*
* @param string $filename - Name of file
*
* @throw Iptc_Exception
* @see http://www.php.net/manual/pt_BR/book.image.php - PHP GD
* @see iptcparse
* @see getimagesize
* @return void
*/
public function __construct($filename)
{
/**
* Check PHP version
* @since 2.0.1
*/
if (version_compare(phpversion(), '5.1.3', '<') === true) {
throw new Iptc_Exception(
'ERROR: Your PHP version is '.phpversion() .
'. Iptc class requires PHP 5.1.3 or newer.'
);
}
if ( ! extension_loaded('gd') ) {
throw new Iptc_Exception(
'Since PHP 4.3 there is a bundled version of the GD lib.'
);
}
if ( ! file_exists($filename) ) {
throw new Iptc_Exception(
'Image not found!'
);
}
if ( ! is_writable($filename) ) {
throw new Iptc_Exception(
"File \"{$filename}\" is not writable!"
);
}
$parts = explode('.', strtolower($filename));
if ( ! in_array(end($parts), $this->_allowedExt) ) {
throw new Iptc_Exception(
'Support only for the following extensions: ' .
implode(',', $this->_allowedExt)
);
}
$size = getimagesize($filename, $imageinfo);
$this->_hasMeta = isset($imageinfo["APP13"]);
if ($this->_hasMeta) {
$this->_meta = iptcparse($imageinfo["APP13"]);
}
$this->_filename = $filename;
}
/**
* Set parameters you want to record in a particular tag "IPTC"
*
* @param Integer|const $tag - Code or const of tag
* @param array|mixed $data - Value of tag
*
* @return Iptc object
* @access public
*/
public function set($tag, $data)
{
$data = $this->_charset_decode($data);
$this->_meta["2#{$tag}"] = array($data);
$this->_hasMeta = true;
return $this;
}
/**
* adds an item at the beginning of the array
*
* @param Integer|const $tag - Code or const of tag
* @param array|mixed $data - Value of tag
*
* @return Iptc object
* @access public
*/
public function prepend($tag, $data)
{
$data = $this->_charset_decode($data);
if ( ! empty($this->_meta["2#{$tag}"])) {
array_unshift($this->_meta["2#{$tag}"], $data);
$data = $this->_meta["2#{$tag}"];
}
$this->_meta["2#{$tag}"] = array( $data );
$this->_hasMeta = true;
return $this;
}
/**
* adds an item at the end of the array
*
* @param Integer|const $tag - Code or const of tag
* @param array|mixed $data - Value of tag
*
* @return Iptc object
* @access public
*/
public function append($tag, $data)
{
$data = $this->_charset_decode($data);
if ( ! empty($this->_meta["2#{$tag}"])) {
array_push($this->_meta["2#{$tag}"], $data);
$data = $this->_meta["2#{$tag}"];
}
$this->_meta["2#{$tag}"] = array( $data );
$this->_hasMeta = true;
return $this;
}
/**
* Return fisrt IPTC tag by tag name
*
* @param Integer|const $tag - Name of tag
*
* @example $iptc->fetch(Iptc::KEYWORDS);
*
* @access public
* @return mixed|false
*/
public function fetch($tag)
{
if (isset($this->_meta["2#{$tag}"])) {
return $this->_charset_encode($this->_meta["2#{$tag}"][0]);
}
return false;
}
/**
* Return all IPTC tags by tag name
*
* @param Integer|const $tag - Name of tag
*
* @example $iptc->fetchAll(Iptc::KEYWORDS);
*
* @access public
* @return mixed|false
*/
public function fetchAll($tag)
{
if (isset($this->_meta["2#{$tag}"])) {
return $this->_charset_encode($this->_meta["2#{$tag}"]);
}
return false;
}
/**
* debug that returns all the IPTC tags already in the image
*
* @access public
* @return string
*/
public function dump()
{
return $this->_charset_encode(print_r($this->_meta, true));
}
/**
* returns a string with the binary code
*
* @access public
* @return string
*/
public function binary()
{
$iptc = '';
foreach (array_keys($this->_meta) as $key) {
$tag = str_replace("2#", "", $key);
foreach($this->_meta[$key] as $value) {
$iptc .= $this->iptcMakeTag(2, $tag, $value);
}
}
return $iptc;
}
/**
* Assemble the tags "IPTC" in character "ascii"
*
* @param Integer $rec - Type of tag ex. 2
* @param Integer $dat - code of tag ex. 025 or 000 etc
* @param mixed $val - any caracterer
*
* @access public
* @return binary source
*/
public function iptcMakeTag($rec, $dat, $val)
{
//beginning of the binary string
$iptcTag = chr(0x1c).chr($rec).chr($dat);
if (is_array($val)) {
$src = '';
foreach ($val as $item) {
$len = strlen($item);
$src .= $iptcTag . $this->_testBitSize($len) . $item;
}
return $src;
}
$len = strlen($val);
$src = $iptcTag . $this->_testBitSize($len) . $val;
return $src;
}
/**
* create the new image file already
* with the new "IPTC" recorded
*
* @access public
* @return boolean
*/
public function write()
{
//@see http://php.net/manual/pt_BR/function.iptcembed.php
$content = iptcembed($this->binary(), $this->_filename, 0);
if ($content === false) {
throw new Iptc_Exception(
'Failed to save IPTC data into file'
);
}
@unlink($this->_filename);
return file_put_contents($this->_filename, $content) !== false;
}
/**
* completely remove all tags "IPTC" image
*
* @access public
* @return void
*/
public function removeAllTags()
{
$this->_hasMeta = false;
$this->_meta = Array();
$impl = implode(file($this->_filename));
$img = imagecreatefromstring($impl);
unlink($this->_filename);
imagejpeg($img, $this->_filename, 100);
}
/**
* It proper test to ensure that
* the size of the values are supported within the
*
* @param Integer $len - size of the character
*
* @access public
* @return boolean
*/
private function _testBitSize($len)
{
if ($len < 0x8000) {
return
chr($len >> 8) .
chr($len & 0xff);
}
return
chr(0x1c).chr(0x04) .
chr(($len >> 24) & 0xff) .
chr(($len >> 16) & 0xff) .
chr(($len >> 8 ) & 0xff) .
chr(($len ) & 0xff);
}
/**
* Decode charset utf8 before being saved
*
* @param String $data
* @access private
* @return string decoded string
*/
private function _charset_decode($data) {
$result = array();
if (is_array($data)) {
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($data)) as $value) {
$result[] = utf8_decode($value);
}
} else {
return utf8_decode($data);
}
return $result;
}
/**
* Encode charset to utf8 before being saved
*
* @param String $data
* @access private
* @return string encoded string
*/
private function _charset_encode($data) {
$result = array();
if (is_array($data)) {
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($data)) as $value) {
$result[] = utf8_encode($value);
}
} else {
return utf8_encode($data);
}
return $result;
}
}