| @@ -1,525 +1,520 @@ | ||
| 1 | -<?php | |
| 2 | - | |
| 3 | -$orig_srcpath='../tests/tiger.png'; // as specified in your file (could be full URL) | |
| 4 | -$file = 'http://127.0.0.1/MPDF1.com/common/mpdf/tests/tiger.png'; // Full URL | |
| 5 | -$fileIsLocal = true; // is the file in the same domain? | |
| 6 | - | |
| 7 | -//====================================================================== | |
| 8 | - | |
| 9 | -$ppUx = 0; | |
| 10 | -$type = ''; | |
| 11 | -$data = ''; | |
| 12 | - | |
| 13 | -echo 'File: ' .$orig_srcpath . '<br />'; | |
| 14 | -echo 'Full File URL: ' .$file . '<br />'; | |
| 15 | - if ($orig_srcpath && $fileIsLocal && $check = @fopen($orig_srcpath,"rb")) { | |
| 16 | - fclose($check); | |
| 17 | - $file=$orig_srcpath; | |
| 18 | - $data = file_get_contents($file); | |
| 19 | - $type = _imageTypeFromString($data); | |
| 20 | - echo 'File accessed using fopen on $orig_srcpath' . '<br />'; | |
| 21 | - } | |
| 22 | - if (!$data && $check = @fopen($file,"rb")) { | |
| 23 | - fclose($check); | |
| 24 | - $data = file_get_contents($file); | |
| 25 | - $type = _imageTypeFromString($data); | |
| 26 | - echo 'File accessed using fopen on $file' . '<br />'; | |
| 27 | - } | |
| 28 | - if ((!$data || !$type) && !ini_get('allow_url_fopen') ) { // only worth trying if remote file and !ini_get('allow_url_fopen') | |
| 29 | - file_get_contents_by_socket($file, $data); // needs full url?? even on local (never needed for local) | |
| 30 | - if ($data) { $type = _imageTypeFromString($data); } | |
| 31 | - echo 'File accessed using socket ' . '<br />'; | |
| 32 | - } | |
| 33 | - if ((!$data || !$type) && !ini_get('allow_url_fopen') && function_exists("curl_init")) { | |
| 34 | - file_get_contents_by_curl($file, $data); // needs full url?? even on local (never needed for local) | |
| 35 | - if ($data) { $type = _imageTypeFromString($data); } | |
| 36 | - echo 'File accessed using cURL ' . '<br />'; | |
| 37 | - } | |
| 38 | - | |
| 39 | - | |
| 40 | - | |
| 41 | - if (!$data) { echo 'Could not access image file' . '<br />'; exit; } | |
| 42 | - | |
| 43 | - echo 'Image type determined: ' .strtoupper($type) . '<br />'; | |
| 44 | - | |
| 45 | - // JPEG | |
| 46 | - if ($type == 'jpeg' || $type == 'jpg') { | |
| 47 | - $hdr = _jpgHeaderFromString($data); | |
| 48 | - if (!$hdr) { echo 'Error parsing JPG header' . '<br />'; exit; } | |
| 49 | - $a = _jpgDataFromHeader($hdr); | |
| 50 | - $channels = intval($a[4]); | |
| 51 | - echo 'Width: ' . $a[0]. '<br />'; | |
| 52 | - echo 'Height: ' . $a[1]. '<br />'; | |
| 53 | - echo 'Colorspace: ' . $a[2]. '<br />'; | |
| 54 | - echo 'BPC (bits per channel): ' . $a[3]. '<br />'; | |
| 55 | - echo 'Channels: ' . $channels. '<br />'; | |
| 56 | - | |
| 57 | - $j = strpos($data,'JFIF'); | |
| 58 | - if ($j) { | |
| 59 | - //Read resolution | |
| 60 | - $unitSp=ord(substr($data,($j+7),1)); | |
| 61 | - if ($unitSp > 0) { | |
| 62 | - $ppUx=_twobytes2int(substr($data,($j+8),2)); // horizontal pixels per meter, usually set to zero | |
| 63 | - if ($unitSp == 2) { // = dots per cm (if == 1 set as dpi) | |
| 64 | - $ppUx=round($ppUx/10 *25.4); | |
| 65 | - } | |
| 66 | - } | |
| 67 | - echo 'Resolution ppUx: ' . $ppUx. '<br />'; | |
| 68 | - } | |
| 69 | - else echo 'JFIF not found in header' . '<br />'; | |
| 70 | - | |
| 71 | - | |
| 72 | - // mPDF 6 ICC profile | |
| 73 | - $offset = 0; | |
| 74 | - $icc = array(); | |
| 75 | - while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) { | |
| 76 | - // get ICC sequence length | |
| 77 | - $length = _twobytes2int(substr($data, ($pos - 2),2)) - 16; | |
| 78 | - $sn = max(1, ord($data[($pos + 12)])); | |
| 79 | - $nom = max(1, ord($data[($pos + 13)])); | |
| 80 | - $icc[($sn - 1)] = substr($data, ($pos + 14), $length); | |
| 81 | - $offset = ($pos + 14 + $length); | |
| 82 | - } | |
| 83 | - // order and compact ICC segments | |
| 84 | - if (count($icc) > 0) { | |
| 85 | - echo 'ICC profile present' . '<br />'; | |
| 86 | - ksort($icc); | |
| 87 | - $icc = implode('', $icc); | |
| 88 | - if (substr($icc, 36, 4) != 'acsp') { | |
| 89 | - // invalid ICC profile | |
| 90 | - echo 'ICC profile INVALID (no acsp flag)' . '<br />'; | |
| 91 | - } | |
| 92 | - $input = substr($icc, 16, 4); | |
| 93 | - $output = substr($icc, 20, 4); | |
| 94 | - echo 'ICC profile Input: ' . $input. '<br />'; | |
| 95 | - echo 'ICC profile Output: ' . $output. '<br />'; | |
| 96 | - // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab | |
| 97 | - if ($input != 'RGB ' || $output != 'XYZ ') { echo 'ICC profile ignored by mPDF' . '<br />'; } | |
| 98 | - } | |
| 99 | - | |
| 100 | - } | |
| 101 | - | |
| 102 | - // PNG | |
| 103 | - else if ($type == 'png') { | |
| 104 | - //Check signature | |
| 105 | - if(substr($data,0,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) { | |
| 106 | - echo 'Error parsing PNG identifier<br />'; exit; | |
| 107 | - } | |
| 108 | - //Read header chunk | |
| 109 | - if(substr($data,12,4)!='IHDR') { | |
| 110 | - echo 'Incorrect PNG file (no IHDR block found)<br />'; exit; | |
| 111 | - } | |
| 112 | - | |
| 113 | - $w=_fourbytes2int(substr($data,16,4)); | |
| 114 | - $h=_fourbytes2int(substr($data,20,4)); | |
| 115 | - $bpc=ord(substr($data,24,1)); | |
| 116 | - $errpng = false; | |
| 117 | - $pngalpha = false; | |
| 118 | - $channels = 0; | |
| 119 | - | |
| 120 | - echo 'Width: ' .$w . '<br />'; | |
| 121 | - echo 'Height: ' .$h . '<br />'; | |
| 122 | - echo 'BPC (bits per channel): ' .$bpc . '<br />'; | |
| 123 | - | |
| 124 | - $ct=ord(substr($data,25,1)); | |
| 125 | - if($ct==0) { $colspace='DeviceGray'; $channels = 1; } | |
| 126 | - elseif($ct==2) { $colspace='DeviceRGB'; $channels = 3; } | |
| 127 | - elseif($ct==3) { $colspace='Indexed'; $channels = 1; } | |
| 128 | - elseif($ct==4) { $colspace='DeviceGray'; $channels = 1; $errpng = 'alpha channel'; $pngalpha = true; } | |
| 129 | - else { $colspace='DeviceRGB'; $channels = 3; $errpng = 'alpha channel'; $pngalpha = true; } | |
| 130 | - | |
| 131 | - echo 'Colorspace: ' . $colspace. '<br />'; | |
| 132 | - echo 'Channels: ' . $channels. '<br />'; | |
| 133 | - if ($pngalpha) echo 'Alpha channel detected'. '<br />'; | |
| 134 | - | |
| 135 | - if ($ct < 4 && strpos($data,'tRNS')!==false) { echo 'Transparency detected'. '<br />'; $errpng = 'transparency'; $pngalpha = true;} | |
| 136 | - | |
| 137 | - if ($ct == 3 && strpos($data,'iCCP')!==false) { echo 'Indexed plus ICC'. '<br />'; $errpng = 'indexed plus ICC'; } | |
| 138 | - | |
| 139 | - if(ord(substr($data,26,1))!=0) { echo 'compression method not set to zero<br />'; $errpng = 'compression method'; } // only 0 should be specified | |
| 140 | - if(ord(substr($data,27,1))!=0) { echo 'filter method not set to zero<br />'; $errpng = 'filter method'; } // only 0 should be specified | |
| 141 | - if(ord(substr($data,28,1))!=0) { echo 'interlaced file not set to zero<br />'; $errpng = 'interlaced file'; } | |
| 142 | - | |
| 143 | - $j = strpos($data,'pHYs'); | |
| 144 | - if ($j) { | |
| 145 | - //Read resolution | |
| 146 | - $unitSp=ord(substr($data,($j+12),1)); | |
| 147 | - if ($unitSp == 1) { | |
| 148 | - $ppUx=_fourbytes2int(substr($data,($j+4),4)); // horizontal pixels per meter, usually set to zero | |
| 149 | - $ppUx=round($ppUx/1000 *25.4); | |
| 150 | - } | |
| 151 | - echo 'Resolution ppUx: ' . $ppUx. '<br />'; | |
| 152 | - } | |
| 153 | - | |
| 154 | - // mPDF 6 Gamma correction | |
| 155 | - $gamma_correction = 0; | |
| 156 | - $gAMA = 0; | |
| 157 | - $j = strpos($data,'gAMA'); | |
| 158 | - if ($j && strpos($data,'sRGB')===false) { // sRGB colorspace - overrides gAMA | |
| 159 | - $gAMA=_fourbytes2int(substr($data,($j+4),4)); // Gamma value times 100000 | |
| 160 | - $gAMA /= 100000; | |
| 161 | - | |
| 162 | - } | |
| 163 | - | |
| 164 | - if ($gAMA) { $gamma_correction = 1/$gAMA; } | |
| 165 | - | |
| 166 | - // Don't need to apply gamma correction if == default i.e. 2.2 | |
| 167 | - if ($gamma_correction > 2.15 && $gamma_correction < 2.25) { $gamma_correction = 0; } | |
| 168 | - | |
| 169 | - if ($gamma_correction) { echo 'Gamma correction detected'. '<br />'; } | |
| 170 | - | |
| 171 | - // NOT supported at present | |
| 172 | - if (strpos($data,'sRGB')!==false) echo 'sRGB colorspace - NOT supported at present'. '<br />'; | |
| 173 | - if (strpos($data,'cHRM')!==false) echo 'Chromaticity and Whitepoint - NOT supported at present'. '<br />'; | |
| 174 | - | |
| 175 | - if (($errpng || $pngalpha || $gamma_correction)) { | |
| 176 | - if (function_exists('gd_info')) { $gd = gd_info(); } | |
| 177 | - else {$gd = array(); } | |
| 178 | - if (!isset($gd['PNG Support'])) { echo 'GD library required for PNG image ('.$errpng.')'. '<br />';} | |
| 179 | - $im = imagecreatefromstring($data); | |
| 180 | - | |
| 181 | - if (!$im) { echo 'Error creating GD image from PNG file ('.$errpng.')'. '<br />';} | |
| 182 | - $w = imagesx($im); | |
| 183 | - $h = imagesy($im); | |
| 184 | - if ($im) { | |
| 185 | - | |
| 186 | - // Alpha channel set (including using tRNS for Paletted images) | |
| 187 | - if ($pngalpha) { | |
| 188 | - echo 'Alpha channel will be used by mPDF (including when tRNS present in Paletted images)<br />'; | |
| 189 | - if ($colspace=='Indexed') { echo '...Generating Alpha channel values from tRNS (Indexed)<br />'; } | |
| 190 | - else if ($ct===0 || $ct==2) { echo '...Generating Alpha channel values from tRNS (non-Indexed)<br />'; } | |
| 191 | - else { echo '...Extracting Alpha channel<br />'; } | |
| 192 | - | |
| 193 | - | |
| 194 | - } | |
| 195 | - else { // No alpha/transparency set (but cannot read directly because e.g. bit-depth != 8, interlaced etc) | |
| 196 | - echo 'No alpha/transparency set (but cannot read directly because e.g. bit-depth != 8, interlaced etc)<br />'; | |
| 197 | - | |
| 198 | - // ICC profile | |
| 199 | - $icc = false; | |
| 200 | - $p = strpos($data,'iCCP'); | |
| 201 | - if ($p && $colspace=="Indexed") { | |
| 202 | - $p += 4; | |
| 203 | - $n=_fourbytes2int(substr($data,($p-8),4)); | |
| 204 | - $nullsep = strpos(substr($data,$p,80), chr(0)); | |
| 205 | - $icc = substr($data, ($p+$nullsep+2), ($n-($nullsep+2)) ); | |
| 206 | - // Test if file is gzcompressed | |
| 207 | - if (ord(substr($str, 0, 1)) == 0x1f && ord(substr($str, 1, 1)) == 0x8b) { | |
| 208 | - $icc = @gzuncompress($icc); // Ignored if fails | |
| 209 | - } | |
| 210 | - if ($icc) { | |
| 211 | - echo 'ICC profile present' . '<br />'; | |
| 212 | - if (substr($icc, 36, 4) != 'acsp') { echo 'ICC profile INVALID (no acsp flag)' . '<br />'; $icc = false; } // invalid ICC profile | |
| 213 | - else { | |
| 214 | - $input = substr($icc, 16, 4); | |
| 215 | - $output = substr($icc, 20, 4); | |
| 216 | - echo 'ICC profile Input: ' . $input. '<br />'; | |
| 217 | - echo 'ICC profile Output: ' . $output. '<br />'; | |
| 218 | - // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab | |
| 219 | - if ($input != 'RGB ' || $output != 'XYZ ') { $icc = false; echo 'ICC profile ignored by mPDF' . '<br />'; } | |
| 220 | - } | |
| 221 | - } | |
| 222 | - // Convert to RGB colorspace so can use ICC Profile | |
| 223 | - if ($icc) { echo 'ICC profile and Indexed colorspace both present - need to Convert to RGB colorspace so can use ICC Profile<br />'; } | |
| 224 | - } | |
| 225 | - | |
| 226 | - | |
| 227 | - } | |
| 228 | - } | |
| 229 | - echo 'PNG Image parsed on second pass' . '<br />'; | |
| 230 | - | |
| 231 | - // SECOND PASS | |
| 232 | - imagealphablending($im, false); | |
| 233 | - imagesavealpha($im, false); | |
| 234 | - imageinterlace($im, false); | |
| 235 | - ob_start(); | |
| 236 | - $check = @imagepng($im); | |
| 237 | - if (!$check) { echo 'Error creating temporary image object whilst using GD library to parse PNG image' . '<br />'; } | |
| 238 | - $data = ob_get_contents(); | |
| 239 | - ob_end_clean(); | |
| 240 | - if (!$data) { echo 'Error parsing temporary file image object created with GD library to parse PNG image' . '<br />'; } | |
| 241 | - imagedestroy($im); | |
| 242 | - | |
| 243 | - | |
| 244 | - //Check signature | |
| 245 | - if(substr($data,0,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) { | |
| 246 | - echo 'Error parsing PNG identifier<br />'; exit; | |
| 247 | - } | |
| 248 | - //Read header chunk | |
| 249 | - if(substr($data,12,4)!='IHDR') { | |
| 250 | - echo 'Incorrect PNG file (no IHDR block found)<br />'; exit; | |
| 251 | - } | |
| 252 | - | |
| 253 | - $w=_fourbytes2int(substr($data,16,4)); | |
| 254 | - $h=_fourbytes2int(substr($data,20,4)); | |
| 255 | - $bpc=ord(substr($data,24,1)); | |
| 256 | - $errpng = false; | |
| 257 | - $pngalpha = false; | |
| 258 | - $channels = 0; | |
| 259 | - | |
| 260 | - echo 'Width: ' .$w . '<br />'; | |
| 261 | - echo 'Height: ' .$h . '<br />'; | |
| 262 | - echo 'BPC (bits per channel): ' .$bpc . '<br />'; | |
| 263 | - | |
| 264 | - $ct=ord(substr($data,25,1)); | |
| 265 | - if($ct==0) { $colspace='DeviceGray'; $channels = 1; } | |
| 266 | - elseif($ct==2) { $colspace='DeviceRGB'; $channels = 3; } | |
| 267 | - elseif($ct==3) { $colspace='Indexed'; $channels = 1; } | |
| 268 | - elseif($ct==4) { $colspace='DeviceGray'; $channels = 1; $errpng = 'alpha channel'; $pngalpha = true; } | |
| 269 | - else { $colspace='DeviceRGB'; $channels = 3; $errpng = 'alpha channel'; $pngalpha = true; } | |
| 270 | - | |
| 271 | - echo 'Colorspace: ' . $colspace. '<br />'; | |
| 272 | - echo 'Channels: ' . $channels. '<br />'; | |
| 273 | - if ($pngalpha) echo 'Alpha channel detected'. '<br />'; | |
| 274 | - | |
| 275 | - if ($ct < 4 && strpos($data,'tRNS')!==false) { echo 'Transparency detected'. '<br />'; $errpng = 'transparency'; $pngalpha = true;} | |
| 276 | - | |
| 277 | - if ($ct == 3 && strpos($data,'iCCP')!==false) { echo 'Indexed plus ICC'. '<br />'; $errpng = 'indexed plus ICC'; } | |
| 278 | - | |
| 279 | - if(ord(substr($data,26,1))!=0) { echo 'compression method not set to zero<br />'; $errpng = 'compression method'; } // only 0 should be specified | |
| 280 | - if(ord(substr($data,27,1))!=0) { echo 'filter method not set to zero<br />'; $errpng = 'filter method'; } // only 0 should be specified | |
| 281 | - if(ord(substr($data,28,1))!=0) { echo 'interlaced file not set to zero<br />'; $errpng = 'interlaced file'; } | |
| 282 | - | |
| 283 | - $j = strpos($data,'pHYs'); | |
| 284 | - if ($j) { | |
| 285 | - //Read resolution | |
| 286 | - $unitSp=ord(substr($data,($j+12),1)); | |
| 287 | - if ($unitSp == 1) { | |
| 288 | - $ppUx=_fourbytes2int(substr($data,($j+4),4)); // horizontal pixels per meter, usually set to zero | |
| 289 | - $ppUx=round($ppUx/1000 *25.4); | |
| 290 | - } | |
| 291 | - echo 'Resolution ppUx: ' . $ppUx. '<br />'; | |
| 292 | - } | |
| 293 | - | |
| 294 | - //Gamma correction | |
| 295 | - $gamma_correction = 0; | |
| 296 | - $gAMA = 0; | |
| 297 | - $j = strpos($data,'gAMA'); | |
| 298 | - if ($j && strpos($data,'sRGB')===false) { // sRGB colorspace - overrides gAMA | |
| 299 | - $gAMA=_fourbytes2int(substr($data,($j+4),4)); // Gamma value times 100000 | |
| 300 | - $gAMA /= 100000; | |
| 301 | - | |
| 302 | - } | |
| 303 | - | |
| 304 | - if ($gAMA) { $gamma_correction = 1/$gAMA; } | |
| 305 | - | |
| 306 | - // Don't need to apply gamma correction if == default i.e. 2.2 | |
| 307 | - if ($gamma_correction > 2.15 && $gamma_correction < 2.25) { $gamma_correction = 0; } | |
| 308 | - | |
| 309 | - if ($gamma_correction) { echo 'Gamma correction detected'. '<br />'; } | |
| 310 | - | |
| 311 | - // NOT supported at present | |
| 312 | - if (strpos($data,'sRGB')!==false) echo 'sRGB colorspace - NOT supported at present'. '<br />'; | |
| 313 | - if (strpos($data,'cHRM')!==false) echo 'Chromaticity and Whitepoint - NOT supported at present'. '<br />'; | |
| 314 | - | |
| 315 | - } | |
| 316 | - | |
| 317 | - else { // PNG image with no need to convert alpha channels, bpc <> 8 etc. | |
| 318 | - //Scan chunks looking for palette, transparency and image data | |
| 319 | - $pal=''; | |
| 320 | - $trns=''; | |
| 321 | - $pngdata=''; | |
| 322 | - $icc = false; | |
| 323 | - $p = 33; | |
| 324 | - do { | |
| 325 | - $n=_fourbytes2int(substr($data,$p,4)); $p += 4; | |
| 326 | - $type=substr($data,$p,4); $p += 4; | |
| 327 | - if ($type=='PLTE') { | |
| 328 | - //Read palette | |
| 329 | - $pal=substr($data,$p,$n); $p += $n; | |
| 330 | - $p += 4; | |
| 331 | - } | |
| 332 | - else if($type=='tRNS') { | |
| 333 | - //Read transparency info | |
| 334 | - $t=substr($data,$p,$n); $p += $n; | |
| 335 | - if ($ct==0) $trns=array(ord(substr($t,1,1))); | |
| 336 | - else if ($ct==2) $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1))); | |
| 337 | - else { | |
| 338 | - $pos=strpos($t,chr(0)); | |
| 339 | - if(is_int($pos)) $trns=array($pos); | |
| 340 | - } | |
| 341 | - $p += 4; | |
| 342 | - } | |
| 343 | - else if ($type=='IDAT') { | |
| 344 | - $pngdata.=substr($data,$p,$n); $p += $n; | |
| 345 | - $p += 4; | |
| 346 | - } | |
| 347 | - else if ($type=='iCCP') { | |
| 348 | - $nullsep = strpos(substr($data,$p,80), chr(0)); | |
| 349 | - $icc = substr($data, ($p+$nullsep+2), ($n-($nullsep+2)) ); | |
| 350 | - // Test if file is gzcompressed | |
| 351 | - if (ord(substr($str, 0, 1)) == 0x1f && ord(substr($str, 1, 1)) == 0x8b) { | |
| 352 | - $icc = @gzuncompress($icc); // Ignored if fails | |
| 353 | - } | |
| 354 | - if ($icc) { | |
| 355 | - echo 'ICC profile present' . '<br />'; | |
| 356 | - if (substr($icc, 36, 4) != 'acsp') { echo 'ICC profile INVALID (no acsp flag)' . '<br />'; $icc = false; } // invalid ICC profile | |
| 357 | - else { | |
| 358 | - $input = substr($icc, 16, 4); | |
| 359 | - $output = substr($icc, 20, 4); | |
| 360 | - echo 'ICC profile Input: ' . $input. '<br />'; | |
| 361 | - echo 'ICC profile Output: ' . $output. '<br />'; | |
| 362 | - // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab | |
| 363 | - if ($input != 'RGB ' || $output != 'XYZ ') { $icc = false; echo 'ICC profile ignored by mPDF' . '<br />'; } | |
| 364 | - } | |
| 365 | - } | |
| 366 | - $p += $n; | |
| 367 | - $p += 4; | |
| 368 | - } | |
| 369 | - | |
| 370 | - | |
| 371 | - else if($type=='IEND') { break; } | |
| 372 | - else if (preg_match('/[a-zA-Z]{4}/',$type)) { $p += $n+4; } | |
| 373 | - else { echo 'Error parsing PNG image data<br />'; } | |
| 374 | - } | |
| 375 | - while($n); | |
| 376 | - if (!$pngdata) { echo 'Error parsing PNG image data - no IDAT data found<br />';} | |
| 377 | - if ($colspace=='Indexed' && empty($pal)) { echo 'Error parsing PNG image data - missing colour palette<br />'; } | |
| 378 | - echo 'PNG Image parsed directly' . '<br />'; | |
| 379 | - | |
| 380 | - } | |
| 381 | - | |
| 382 | - | |
| 383 | - } | |
| 384 | - | |
| 385 | - // GIF | |
| 386 | - else if ($type == 'gif') { | |
| 387 | - } | |
| 388 | - | |
| 389 | - // BMP (Windows Bitmap) | |
| 390 | - else if ($type == 'bmp') { | |
| 391 | - } | |
| 392 | - // WMF | |
| 393 | - else if ($type == 'wmf') { | |
| 394 | - } | |
| 395 | - // UNKNOWN TYPE - try GD imagecreatefromstring | |
| 396 | - else { | |
| 397 | - if (function_exists('gd_info')) { $gd = gd_info(); } | |
| 398 | - else {$gd = array(); } | |
| 399 | - if (isset($gd['PNG Support']) && $gd['PNG Support']) { | |
| 400 | - $im = @imagecreatefromstring($data); | |
| 401 | - if ($im) { echo 'Image type not recognised, but image created from file using GD imagecreate' . '<br />'; } | |
| 402 | - else { echo 'Error parsing image file - image type not recognised, and not supported by GD imagecreate' . '<br />'; } | |
| 403 | - } | |
| 404 | - } | |
| 405 | - | |
| 406 | - | |
| 407 | -exit; | |
| 408 | - | |
| 409 | -//============================================================== | |
| 410 | - | |
| 411 | -function _fourbytes2int($s) { | |
| 412 | - //Read a 4-byte integer from string | |
| 413 | - return (ord($s[0])<<24) + (ord($s[1])<<16) + (ord($s[2])<<8) + ord($s[3]); | |
| 414 | -} | |
| 415 | - | |
| 416 | -function _twobytes2int($s) { // equivalent to _get_ushort | |
| 417 | - //Read a 2-byte integer from string | |
| 418 | - return (ord(substr($s, 0, 1))<<8) + ord(substr($s, 1, 1)); | |
| 419 | -} | |
| 420 | - | |
| 421 | -function _jpgHeaderFromString(&$data) { | |
| 422 | - $p = 4; | |
| 423 | - $p += _twobytes2int(substr($data, $p, 2)); // Length of initial marker block | |
| 424 | - $marker = substr($data, $p, 2); | |
| 425 | - while($marker != chr(255).chr(192) && $marker != chr(255).chr(194) && $p<strlen($data)) { | |
| 426 | - // Start of frame marker (FFC0) or (FFC2) mPDF 4.4.004 | |
| 427 | - $p += (_twobytes2int(substr($data, $p+2, 2))) + 2; // Length of marker block | |
| 428 | - $marker = substr($data, $p, 2); | |
| 429 | - } | |
| 430 | - if ($marker != chr(255).chr(192) && $marker != chr(255).chr(194)) { return false; } | |
| 431 | - return substr($data, $p+2, 10); | |
| 432 | -} | |
| 433 | - | |
| 434 | -function _jpgDataFromHeader($hdr) { | |
| 435 | - $bpc = ord(substr($hdr, 2, 1)); | |
| 436 | - if (!$bpc) { $bpc = 8; } | |
| 437 | - $h = _twobytes2int(substr($hdr, 3, 2)); | |
| 438 | - $w = _twobytes2int(substr($hdr, 5, 2)); | |
| 439 | - $channels = ord(substr($hdr, 7, 1)); | |
| 440 | - if ($channels==3) { $colspace='DeviceRGB'; } | |
| 441 | - elseif($channels==4) { $colspace='DeviceCMYK'; } | |
| 442 | - else { $colspace='DeviceGray'; } | |
| 443 | - return array($w, $h, $colspace, $bpc, $channels); | |
| 444 | -} | |
| 445 | - | |
| 446 | -function file_get_contents_by_curl($url, &$data) { | |
| 447 | - $timeout = 5; | |
| 448 | - $ch = curl_init($url); | |
| 449 | - curl_setopt($ch, CURLOPT_HEADER, 0); | |
| 450 | - curl_setopt($ch, CURLOPT_NOBODY, 0); | |
| 451 | - curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 ); | |
| 452 | - curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , $timeout ); | |
| 453 | - $data = curl_exec($ch); | |
| 454 | - curl_close($ch); | |
| 455 | -} | |
| 456 | - | |
| 457 | - | |
| 458 | -function file_get_contents_by_socket($url, &$data) { | |
| 459 | - // mPDF 5.7.3 | |
| 460 | - $timeout = 1; | |
| 461 | - $p = parse_url($url); | |
| 462 | - $file = $p['path']; | |
| 463 | - if ($p['scheme']=='https') { | |
| 464 | - $prefix = 'ssl://'; | |
| 465 | - $port = ($p['port'] ? $p['port'] : 443); | |
| 466 | - } | |
| 467 | - else { | |
| 468 | - $prefix = ''; | |
| 469 | - $port = ($p['port'] ? $p['port'] : 80); | |
| 470 | - } | |
| 471 | - if ($p['query']) { $file .= '?'.$p['query']; } | |
| 472 | - if(!($fh = @fsockopen($prefix.$p['host'], $port, $errno, $errstr, $timeout))) { return false; } | |
| 473 | - | |
| 474 | - $getstring = | |
| 475 | - "GET ".$file." HTTP/1.0 \r\n" . | |
| 476 | - "Host: ".$p['host']." \r\n" . | |
| 477 | - "Connection: close\r\n\r\n"; | |
| 478 | - fwrite($fh, $getstring); | |
| 479 | - // Get rid of HTTP header | |
| 480 | - $s = fgets($fh, 1024); | |
| 481 | - if (!$s) { return false; } | |
| 482 | - $httpheader .= $s; | |
| 483 | - while (!feof($fh)) { | |
| 484 | - $s = fgets($fh, 1024); | |
| 485 | - if ( $s == "\r\n" ) { break; } | |
| 486 | - } | |
| 487 | - $data = ''; | |
| 488 | - while (!feof($fh)) { | |
| 489 | - $data .= fgets($fh, 1024); | |
| 490 | - } | |
| 491 | - fclose($fh); | |
| 492 | -} | |
| 493 | - | |
| 494 | -//============================================================== | |
| 495 | - | |
| 496 | -function _imageTypeFromString(&$data) { | |
| 497 | - $type = ''; | |
| 498 | - if (substr($data, 6, 4)== 'JFIF' || substr($data, 6, 4)== 'Exif' || substr($data, 0, 2)== chr(255).chr(216)) { // 0xFF 0xD8 | |
| 499 | - $type = 'jpeg'; | |
| 500 | - } | |
| 501 | - else if (substr($data, 0, 6)== "GIF87a" || substr($data, 0, 6)== "GIF89a") { | |
| 502 | - $type = 'gif'; | |
| 503 | - } | |
| 504 | - else if (substr($data, 0, 8)== chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) { | |
| 505 | - $type = 'png'; | |
| 506 | - } | |
| 507 | -/*-- IMAGES-WMF --*/ | |
| 508 | - else if (substr($data, 0, 4)== chr(215).chr(205).chr(198).chr(154)) { | |
| 509 | - $type = 'wmf'; | |
| 510 | - } | |
| 511 | -/*-- END IMAGES-WMF --*/ | |
| 512 | - else if (preg_match('/<svg.*<\/svg>/is',$data)) { | |
| 513 | - $type = 'svg'; | |
| 514 | - } | |
| 515 | - // BMP images | |
| 516 | - else if (substr($data, 0, 2)== "BM") { | |
| 517 | - $type = 'bmp'; | |
| 518 | - } | |
| 519 | - return $type; | |
| 520 | -} | |
| 521 | - | |
| 522 | - | |
| 523 | - | |
| 524 | - | |
| 525 | -?> | |
| 1 | +<?php | |
| 2 | + | |
| 3 | +$orig_srcpath='../tests/tiger.png'; // as specified in your file (could be full URL) | |
| 4 | +$file = 'http://127.0.0.1/MPDF1.com/common/mpdf/tests/tiger.png'; // Full URL | |
| 5 | +$fileIsLocal = true; // is the file in the same domain? | |
| 6 | + | |
| 7 | +//====================================================================== | |
| 8 | + | |
| 9 | +$ppUx = 0; | |
| 10 | +$type = ''; | |
| 11 | +$data = ''; | |
| 12 | + | |
| 13 | +echo 'File: ' .$orig_srcpath . '<br />'; | |
| 14 | +echo 'Full File URL: ' .$file . '<br />'; | |
| 15 | + if ($orig_srcpath && $fileIsLocal && $check = @fopen($orig_srcpath,"rb")) { | |
| 16 | + fclose($check); | |
| 17 | + $file=$orig_srcpath; | |
| 18 | + $data = file_get_contents($file); | |
| 19 | + $type = _imageTypeFromString($data); | |
| 20 | + echo 'File accessed using fopen on $orig_srcpath' . '<br />'; | |
| 21 | + } | |
| 22 | + if (!$data && $check = @fopen($file,"rb")) { | |
| 23 | + fclose($check); | |
| 24 | + $data = file_get_contents($file); | |
| 25 | + $type = _imageTypeFromString($data); | |
| 26 | + echo 'File accessed using fopen on $file' . '<br />'; | |
| 27 | + } | |
| 28 | + if ((!$data || !$type) && !ini_get('allow_url_fopen') ) { // only worth trying if remote file and !ini_get('allow_url_fopen') | |
| 29 | + file_get_contents_by_socket($file, $data); // needs full url?? even on local (never needed for local) | |
| 30 | + if ($data) { $type = _imageTypeFromString($data); } | |
| 31 | + echo 'File accessed using socket ' . '<br />'; | |
| 32 | + } | |
| 33 | + if ((!$data || !$type) && !ini_get('allow_url_fopen') && function_exists("curl_init")) { | |
| 34 | + file_get_contents_by_curl($file, $data); // needs full url?? even on local (never needed for local) | |
| 35 | + if ($data) { $type = _imageTypeFromString($data); } | |
| 36 | + echo 'File accessed using cURL ' . '<br />'; | |
| 37 | + } | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + if (!$data) { echo 'Could not access image file' . '<br />'; exit; } | |
| 42 | + | |
| 43 | + echo 'Image type determined: ' .strtoupper($type) . '<br />'; | |
| 44 | + | |
| 45 | + // JPEG | |
| 46 | + if ($type == 'jpeg' || $type == 'jpg') { | |
| 47 | + $hdr = _jpgHeaderFromString($data); | |
| 48 | + if (!$hdr) { echo 'Error parsing JPG header' . '<br />'; exit; } | |
| 49 | + $a = _jpgDataFromHeader($hdr); | |
| 50 | + $channels = intval($a[4]); | |
| 51 | + echo 'Width: ' . $a[0]. '<br />'; | |
| 52 | + echo 'Height: ' . $a[1]. '<br />'; | |
| 53 | + echo 'Colorspace: ' . $a[2]. '<br />'; | |
| 54 | + echo 'BPC (bits per channel): ' . $a[3]. '<br />'; | |
| 55 | + echo 'Channels: ' . $channels. '<br />'; | |
| 56 | + | |
| 57 | + $j = strpos($data,'JFIF'); | |
| 58 | + if ($j) { | |
| 59 | + //Read resolution | |
| 60 | + $unitSp=ord(substr($data,($j+7),1)); | |
| 61 | + if ($unitSp > 0) { | |
| 62 | + $ppUx=_twobytes2int(substr($data,($j+8),2)); // horizontal pixels per meter, usually set to zero | |
| 63 | + if ($unitSp == 2) { // = dots per cm (if == 1 set as dpi) | |
| 64 | + $ppUx=round($ppUx/10 *25.4); | |
| 65 | + } | |
| 66 | + } | |
| 67 | + echo 'Resolution ppUx: ' . $ppUx. '<br />'; | |
| 68 | + } | |
| 69 | + else echo 'JFIF not found in header' . '<br />'; | |
| 70 | + | |
| 71 | + | |
| 72 | + // mPDF 6 ICC profile | |
| 73 | + $offset = 0; | |
| 74 | + $icc = array(); | |
| 75 | + while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) { | |
| 76 | + // get ICC sequence length | |
| 77 | + $length = _twobytes2int(substr($data, ($pos - 2),2)) - 16; | |
| 78 | + $sn = max(1, ord($data[($pos + 12)])); | |
| 79 | + $nom = max(1, ord($data[($pos + 13)])); | |
| 80 | + $icc[($sn - 1)] = substr($data, ($pos + 14), $length); | |
| 81 | + $offset = ($pos + 14 + $length); | |
| 82 | + } | |
| 83 | + // order and compact ICC segments | |
| 84 | + if (count($icc) > 0) { | |
| 85 | + echo 'ICC profile present' . '<br />'; | |
| 86 | + ksort($icc); | |
| 87 | + $icc = implode('', $icc); | |
| 88 | + if (substr($icc, 36, 4) != 'acsp') { | |
| 89 | + // invalid ICC profile | |
| 90 | + echo 'ICC profile INVALID (no acsp flag)' . '<br />'; | |
| 91 | + } | |
| 92 | + $input = substr($icc, 16, 4); | |
| 93 | + $output = substr($icc, 20, 4); | |
| 94 | + echo 'ICC profile Input: ' . $input. '<br />'; | |
| 95 | + echo 'ICC profile Output: ' . $output. '<br />'; | |
| 96 | + // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab | |
| 97 | + if ($input != 'RGB ' || $output != 'XYZ ') { echo 'ICC profile ignored by mPDF' . '<br />'; } | |
| 98 | + } | |
| 99 | + | |
| 100 | + } | |
| 101 | + | |
| 102 | + // PNG | |
| 103 | + else if ($type == 'png') { | |
| 104 | + //Check signature | |
| 105 | + if(substr($data,0,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) { | |
| 106 | + echo 'Error parsing PNG identifier<br />'; exit; | |
| 107 | + } | |
| 108 | + //Read header chunk | |
| 109 | + if(substr($data,12,4)!='IHDR') { | |
| 110 | + echo 'Incorrect PNG file (no IHDR block found)<br />'; exit; | |
| 111 | + } | |
| 112 | + | |
| 113 | + $w=_fourbytes2int(substr($data,16,4)); | |
| 114 | + $h=_fourbytes2int(substr($data,20,4)); | |
| 115 | + $bpc=ord(substr($data,24,1)); | |
| 116 | + $errpng = false; | |
| 117 | + $pngalpha = false; | |
| 118 | + $channels = 0; | |
| 119 | + | |
| 120 | + echo 'Width: ' .$w . '<br />'; | |
| 121 | + echo 'Height: ' .$h . '<br />'; | |
| 122 | + echo 'BPC (bits per channel): ' .$bpc . '<br />'; | |
| 123 | + | |
| 124 | + $ct=ord(substr($data,25,1)); | |
| 125 | + if($ct==0) { $colspace='DeviceGray'; $channels = 1; } | |
| 126 | + elseif($ct==2) { $colspace='DeviceRGB'; $channels = 3; } | |
| 127 | + elseif($ct==3) { $colspace='Indexed'; $channels = 1; } | |
| 128 | + elseif($ct==4) { $colspace='DeviceGray'; $channels = 1; $errpng = 'alpha channel'; $pngalpha = true; } | |
| 129 | + else { $colspace='DeviceRGB'; $channels = 3; $errpng = 'alpha channel'; $pngalpha = true; } | |
| 130 | + | |
| 131 | + echo 'Colorspace: ' . $colspace. '<br />'; | |
| 132 | + echo 'Channels: ' . $channels. '<br />'; | |
| 133 | + if ($pngalpha) echo 'Alpha channel detected'. '<br />'; | |
| 134 | + | |
| 135 | + if ($ct < 4 && strpos($data,'tRNS')!==false) { echo 'Transparency detected'. '<br />'; $errpng = 'transparency'; $pngalpha = true;} | |
| 136 | + | |
| 137 | + if ($ct == 3 && strpos($data,'iCCP')!==false) { echo 'Indexed plus ICC'. '<br />'; $errpng = 'indexed plus ICC'; } | |
| 138 | + | |
| 139 | + if(ord(substr($data,26,1))!=0) { echo 'compression method not set to zero<br />'; $errpng = 'compression method'; } // only 0 should be specified | |
| 140 | + if(ord(substr($data,27,1))!=0) { echo 'filter method not set to zero<br />'; $errpng = 'filter method'; } // only 0 should be specified | |
| 141 | + if(ord(substr($data,28,1))!=0) { echo 'interlaced file not set to zero<br />'; $errpng = 'interlaced file'; } | |
| 142 | + | |
| 143 | + $j = strpos($data,'pHYs'); | |
| 144 | + if ($j) { | |
| 145 | + //Read resolution | |
| 146 | + $unitSp=ord(substr($data,($j+12),1)); | |
| 147 | + if ($unitSp == 1) { | |
| 148 | + $ppUx=_fourbytes2int(substr($data,($j+4),4)); // horizontal pixels per meter, usually set to zero | |
| 149 | + $ppUx=round($ppUx/1000 *25.4); | |
| 150 | + } | |
| 151 | + echo 'Resolution ppUx: ' . $ppUx. '<br />'; | |
| 152 | + } | |
| 153 | + | |
| 154 | + // mPDF 6 Gamma correction | |
| 155 | + $gamma_correction = 0; | |
| 156 | + $gAMA = 0; | |
| 157 | + $j = strpos($data,'gAMA'); | |
| 158 | + if ($j && strpos($data,'sRGB')===false) { // sRGB colorspace - overrides gAMA | |
| 159 | + $gAMA=_fourbytes2int(substr($data,($j+4),4)); // Gamma value times 100000 | |
| 160 | + $gAMA /= 100000; | |
| 161 | + | |
| 162 | + } | |
| 163 | + | |
| 164 | + if ($gAMA) { $gamma_correction = 1/$gAMA; } | |
| 165 | + | |
| 166 | + // Don't need to apply gamma correction if == default i.e. 2.2 | |
| 167 | + if ($gamma_correction > 2.15 && $gamma_correction < 2.25) { $gamma_correction = 0; } | |
| 168 | + | |
| 169 | + if ($gamma_correction) { echo 'Gamma correction detected'. '<br />'; } | |
| 170 | + | |
| 171 | + // NOT supported at present | |
| 172 | + if (strpos($data,'sRGB')!==false) echo 'sRGB colorspace - NOT supported at present'. '<br />'; | |
| 173 | + if (strpos($data,'cHRM')!==false) echo 'Chromaticity and Whitepoint - NOT supported at present'. '<br />'; | |
| 174 | + | |
| 175 | + if (($errpng || $pngalpha || $gamma_correction)) { | |
| 176 | + if (function_exists('gd_info')) { $gd = gd_info(); } | |
| 177 | + else {$gd = array(); } | |
| 178 | + if (!isset($gd['PNG Support'])) { echo 'GD library required for PNG image ('.$errpng.')'. '<br />';} | |
| 179 | + $im = imagecreatefromstring($data); | |
| 180 | + | |
| 181 | + if (!$im) { echo 'Error creating GD image from PNG file ('.$errpng.')'. '<br />';} | |
| 182 | + $w = imagesx($im); | |
| 183 | + $h = imagesy($im); | |
| 184 | + if ($im) { | |
| 185 | + | |
| 186 | + // Alpha channel set (including using tRNS for Paletted images) | |
| 187 | + if ($pngalpha) { | |
| 188 | + echo 'Alpha channel will be used by mPDF (including when tRNS present in Paletted images)<br />'; | |
| 189 | + if ($colspace=='Indexed') { echo '...Generating Alpha channel values from tRNS (Indexed)<br />'; } | |
| 190 | + else if ($ct===0 || $ct==2) { echo '...Generating Alpha channel values from tRNS (non-Indexed)<br />'; } | |
| 191 | + else { echo '...Extracting Alpha channel<br />'; } | |
| 192 | + | |
| 193 | + | |
| 194 | + } | |
| 195 | + else { // No alpha/transparency set (but cannot read directly because e.g. bit-depth != 8, interlaced etc) | |
| 196 | + echo 'No alpha/transparency set (but cannot read directly because e.g. bit-depth != 8, interlaced etc)<br />'; | |
| 197 | + | |
| 198 | + // ICC profile | |
| 199 | + $icc = false; | |
| 200 | + $p = strpos($data,'iCCP'); | |
| 201 | + if ($p && $colspace=="Indexed") { | |
| 202 | + $p += 4; | |
| 203 | + $n=_fourbytes2int(substr($data,($p-8),4)); | |
| 204 | + $nullsep = strpos(substr($data,$p,80), chr(0)); | |
| 205 | + $icc = substr($data, ($p+$nullsep+2), ($n-($nullsep+2)) ); | |
| 206 | + // Test if file is gzcompressed | |
| 207 | + if (ord(substr($str, 0, 1)) == 0x1f && ord(substr($str, 1, 1)) == 0x8b) { | |
| 208 | + $icc = @gzuncompress($icc); // Ignored if fails | |
| 209 | + } | |
| 210 | + if ($icc) { | |
| 211 | + echo 'ICC profile present' . '<br />'; | |
| 212 | + if (substr($icc, 36, 4) != 'acsp') { echo 'ICC profile INVALID (no acsp flag)' . '<br />'; $icc = false; } // invalid ICC profile | |
| 213 | + else { | |
| 214 | + $input = substr($icc, 16, 4); | |
| 215 | + $output = substr($icc, 20, 4); | |
| 216 | + echo 'ICC profile Input: ' . $input. '<br />'; | |
| 217 | + echo 'ICC profile Output: ' . $output. '<br />'; | |
| 218 | + // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab | |
| 219 | + if ($input != 'RGB ' || $output != 'XYZ ') { $icc = false; echo 'ICC profile ignored by mPDF' . '<br />'; } | |
| 220 | + } | |
| 221 | + } | |
| 222 | + // Convert to RGB colorspace so can use ICC Profile | |
| 223 | + if ($icc) { echo 'ICC profile and Indexed colorspace both present - need to Convert to RGB colorspace so can use ICC Profile<br />'; } | |
| 224 | + } | |
| 225 | + | |
| 226 | + | |
| 227 | + } | |
| 228 | + } | |
| 229 | + echo 'PNG Image parsed on second pass' . '<br />'; | |
| 230 | + | |
| 231 | + // SECOND PASS | |
| 232 | + imagealphablending($im, false); | |
| 233 | + imagesavealpha($im, false); | |
| 234 | + imageinterlace($im, false); | |
| 235 | + ob_start(); | |
| 236 | + $check = @imagepng($im); | |
| 237 | + if (!$check) { echo 'Error creating temporary image object whilst using GD library to parse PNG image' . '<br />'; } | |
| 238 | + $data = ob_get_contents(); | |
| 239 | + ob_end_clean(); | |
| 240 | + if (!$data) { echo 'Error parsing temporary file image object created with GD library to parse PNG image' . '<br />'; } | |
| 241 | + imagedestroy($im); | |
| 242 | + | |
| 243 | + | |
| 244 | + //Check signature | |
| 245 | + if(substr($data,0,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) { | |
| 246 | + echo 'Error parsing PNG identifier<br />'; exit; | |
| 247 | + } | |
| 248 | + //Read header chunk | |
| 249 | + if(substr($data,12,4)!='IHDR') { | |
| 250 | + echo 'Incorrect PNG file (no IHDR block found)<br />'; exit; | |
| 251 | + } | |
| 252 | + | |
| 253 | + $w=_fourbytes2int(substr($data,16,4)); | |
| 254 | + $h=_fourbytes2int(substr($data,20,4)); | |
| 255 | + $bpc=ord(substr($data,24,1)); | |
| 256 | + $errpng = false; | |
| 257 | + $pngalpha = false; | |
| 258 | + $channels = 0; | |
| 259 | + | |
| 260 | + echo 'Width: ' .$w . '<br />'; | |
| 261 | + echo 'Height: ' .$h . '<br />'; | |
| 262 | + echo 'BPC (bits per channel): ' .$bpc . '<br />'; | |
| 263 | + | |
| 264 | + $ct=ord(substr($data,25,1)); | |
| 265 | + if($ct==0) { $colspace='DeviceGray'; $channels = 1; } | |
| 266 | + elseif($ct==2) { $colspace='DeviceRGB'; $channels = 3; } | |
| 267 | + elseif($ct==3) { $colspace='Indexed'; $channels = 1; } | |
| 268 | + elseif($ct==4) { $colspace='DeviceGray'; $channels = 1; $errpng = 'alpha channel'; $pngalpha = true; } | |
| 269 | + else { $colspace='DeviceRGB'; $channels = 3; $errpng = 'alpha channel'; $pngalpha = true; } | |
| 270 | + | |
| 271 | + echo 'Colorspace: ' . $colspace. '<br />'; | |
| 272 | + echo 'Channels: ' . $channels. '<br />'; | |
| 273 | + if ($pngalpha) echo 'Alpha channel detected'. '<br />'; | |
| 274 | + | |
| 275 | + if ($ct < 4 && strpos($data,'tRNS')!==false) { echo 'Transparency detected'. '<br />'; $errpng = 'transparency'; $pngalpha = true;} | |
| 276 | + | |
| 277 | + if ($ct == 3 && strpos($data,'iCCP')!==false) { echo 'Indexed plus ICC'. '<br />'; $errpng = 'indexed plus ICC'; } | |
| 278 | + | |
| 279 | + if(ord(substr($data,26,1))!=0) { echo 'compression method not set to zero<br />'; $errpng = 'compression method'; } // only 0 should be specified | |
| 280 | + if(ord(substr($data,27,1))!=0) { echo 'filter method not set to zero<br />'; $errpng = 'filter method'; } // only 0 should be specified | |
| 281 | + if(ord(substr($data,28,1))!=0) { echo 'interlaced file not set to zero<br />'; $errpng = 'interlaced file'; } | |
| 282 | + | |
| 283 | + $j = strpos($data,'pHYs'); | |
| 284 | + if ($j) { | |
| 285 | + //Read resolution | |
| 286 | + $unitSp=ord(substr($data,($j+12),1)); | |
| 287 | + if ($unitSp == 1) { | |
| 288 | + $ppUx=_fourbytes2int(substr($data,($j+4),4)); // horizontal pixels per meter, usually set to zero | |
| 289 | + $ppUx=round($ppUx/1000 *25.4); | |
| 290 | + } | |
| 291 | + echo 'Resolution ppUx: ' . $ppUx. '<br />'; | |
| 292 | + } | |
| 293 | + | |
| 294 | + //Gamma correction | |
| 295 | + $gamma_correction = 0; | |
| 296 | + $gAMA = 0; | |
| 297 | + $j = strpos($data,'gAMA'); | |
| 298 | + if ($j && strpos($data,'sRGB')===false) { // sRGB colorspace - overrides gAMA | |
| 299 | + $gAMA=_fourbytes2int(substr($data,($j+4),4)); // Gamma value times 100000 | |
| 300 | + $gAMA /= 100000; | |
| 301 | + | |
| 302 | + } | |
| 303 | + | |
| 304 | + if ($gAMA) { $gamma_correction = 1/$gAMA; } | |
| 305 | + | |
| 306 | + // Don't need to apply gamma correction if == default i.e. 2.2 | |
| 307 | + if ($gamma_correction > 2.15 && $gamma_correction < 2.25) { $gamma_correction = 0; } | |
| 308 | + | |
| 309 | + if ($gamma_correction) { echo 'Gamma correction detected'. '<br />'; } | |
| 310 | + | |
| 311 | + // NOT supported at present | |
| 312 | + if (strpos($data,'sRGB')!==false) echo 'sRGB colorspace - NOT supported at present'. '<br />'; | |
| 313 | + if (strpos($data,'cHRM')!==false) echo 'Chromaticity and Whitepoint - NOT supported at present'. '<br />'; | |
| 314 | + | |
| 315 | + } | |
| 316 | + | |
| 317 | + else { // PNG image with no need to convert alpha channels, bpc <> 8 etc. | |
| 318 | + //Scan chunks looking for palette, transparency and image data | |
| 319 | + $pal=''; | |
| 320 | + $trns=''; | |
| 321 | + $pngdata=''; | |
| 322 | + $icc = false; | |
| 323 | + $p = 33; | |
| 324 | + do { | |
| 325 | + $n=_fourbytes2int(substr($data,$p,4)); $p += 4; | |
| 326 | + $type=substr($data,$p,4); $p += 4; | |
| 327 | + if ($type=='PLTE') { | |
| 328 | + //Read palette | |
| 329 | + $pal=substr($data,$p,$n); $p += $n; | |
| 330 | + $p += 4; | |
| 331 | + } | |
| 332 | + else if($type=='tRNS') { | |
| 333 | + //Read transparency info | |
| 334 | + $t=substr($data,$p,$n); $p += $n; | |
| 335 | + if ($ct==0) $trns=array(ord(substr($t,1,1))); | |
| 336 | + else if ($ct==2) $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1))); | |
| 337 | + else { | |
| 338 | + $pos=strpos($t,chr(0)); | |
| 339 | + if(is_int($pos)) $trns=array($pos); | |
| 340 | + } | |
| 341 | + $p += 4; | |
| 342 | + } | |
| 343 | + else if ($type=='IDAT') { | |
| 344 | + $pngdata.=substr($data,$p,$n); $p += $n; | |
| 345 | + $p += 4; | |
| 346 | + } | |
| 347 | + else if ($type=='iCCP') { | |
| 348 | + $nullsep = strpos(substr($data,$p,80), chr(0)); | |
| 349 | + $icc = substr($data, ($p+$nullsep+2), ($n-($nullsep+2)) ); | |
| 350 | + // Test if file is gzcompressed | |
| 351 | + if (ord(substr($str, 0, 1)) == 0x1f && ord(substr($str, 1, 1)) == 0x8b) { | |
| 352 | + $icc = @gzuncompress($icc); // Ignored if fails | |
| 353 | + } | |
| 354 | + if ($icc) { | |
| 355 | + echo 'ICC profile present' . '<br />'; | |
| 356 | + if (substr($icc, 36, 4) != 'acsp') { echo 'ICC profile INVALID (no acsp flag)' . '<br />'; $icc = false; } // invalid ICC profile | |
| 357 | + else { | |
| 358 | + $input = substr($icc, 16, 4); | |
| 359 | + $output = substr($icc, 20, 4); | |
| 360 | + echo 'ICC profile Input: ' . $input. '<br />'; | |
| 361 | + echo 'ICC profile Output: ' . $output. '<br />'; | |
| 362 | + // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab | |
| 363 | + if ($input != 'RGB ' || $output != 'XYZ ') { $icc = false; echo 'ICC profile ignored by mPDF' . '<br />'; } | |
| 364 | + } | |
| 365 | + } | |
| 366 | + $p += $n; | |
| 367 | + $p += 4; | |
| 368 | + } | |
| 369 | + | |
| 370 | + | |
| 371 | + else if($type=='IEND') { break; } | |
| 372 | + else if (preg_match('/[a-zA-Z]{4}/',$type)) { $p += $n+4; } | |
| 373 | + else { echo 'Error parsing PNG image data<br />'; } | |
| 374 | + } | |
| 375 | + while($n); | |
| 376 | + if (!$pngdata) { echo 'Error parsing PNG image data - no IDAT data found<br />';} | |
| 377 | + if ($colspace=='Indexed' && empty($pal)) { echo 'Error parsing PNG image data - missing colour palette<br />'; } | |
| 378 | + echo 'PNG Image parsed directly' . '<br />'; | |
| 379 | + | |
| 380 | + } | |
| 381 | + | |
| 382 | + | |
| 383 | + } | |
| 384 | + | |
| 385 | + // GIF | |
| 386 | + else if ($type == 'gif') { | |
| 387 | + } | |
| 388 | + | |
| 389 | + // BMP (Windows Bitmap) | |
| 390 | + else if ($type == 'bmp') { | |
| 391 | + } | |
| 392 | + // WMF | |
| 393 | + else if ($type == 'wmf') { | |
| 394 | + } | |
| 395 | + // UNKNOWN TYPE - try GD imagecreatefromstring | |
| 396 | + else { | |
| 397 | + if (function_exists('gd_info')) { $gd = gd_info(); } | |
| 398 | + else {$gd = array(); } | |
| 399 | + if (isset($gd['PNG Support']) && $gd['PNG Support']) { | |
| 400 | + $im = @imagecreatefromstring($data); | |
| 401 | + if ($im) { echo 'Image type not recognised, but image created from file using GD imagecreate' . '<br />'; } | |
| 402 | + else { echo 'Error parsing image file - image type not recognised, and not supported by GD imagecreate' . '<br />'; } | |
| 403 | + } | |
| 404 | + } | |
| 405 | + | |
| 406 | + | |
| 407 | +exit; | |
| 408 | + | |
| 409 | +//============================================================== | |
| 410 | + | |
| 411 | +function _fourbytes2int($s) { | |
| 412 | + //Read a 4-byte integer from string | |
| 413 | + return (ord($s[0])<<24) + (ord($s[1])<<16) + (ord($s[2])<<8) + ord($s[3]); | |
| 414 | +} | |
| 415 | + | |
| 416 | +function _twobytes2int($s) { // equivalent to _get_ushort | |
| 417 | + //Read a 2-byte integer from string | |
| 418 | + return (ord(substr($s, 0, 1))<<8) + ord(substr($s, 1, 1)); | |
| 419 | +} | |
| 420 | + | |
| 421 | +function _jpgHeaderFromString(&$data) { | |
| 422 | + $p = 4; | |
| 423 | + $p += _twobytes2int(substr($data, $p, 2)); // Length of initial marker block | |
| 424 | + $marker = substr($data, $p, 2); | |
| 425 | + while($marker != chr(255).chr(192) && $marker != chr(255).chr(194) && $p<strlen($data)) { | |
| 426 | + // Start of frame marker (FFC0) or (FFC2) mPDF 4.4.004 | |
| 427 | + $p += (_twobytes2int(substr($data, $p+2, 2))) + 2; // Length of marker block | |
| 428 | + $marker = substr($data, $p, 2); | |
| 429 | + } | |
| 430 | + if ($marker != chr(255).chr(192) && $marker != chr(255).chr(194)) { return false; } | |
| 431 | + return substr($data, $p+2, 10); | |
| 432 | +} | |
| 433 | + | |
| 434 | +function _jpgDataFromHeader($hdr) { | |
| 435 | + $bpc = ord(substr($hdr, 2, 1)); | |
| 436 | + if (!$bpc) { $bpc = 8; } | |
| 437 | + $h = _twobytes2int(substr($hdr, 3, 2)); | |
| 438 | + $w = _twobytes2int(substr($hdr, 5, 2)); | |
| 439 | + $channels = ord(substr($hdr, 7, 1)); | |
| 440 | + if ($channels==3) { $colspace='DeviceRGB'; } | |
| 441 | + elseif($channels==4) { $colspace='DeviceCMYK'; } | |
| 442 | + else { $colspace='DeviceGray'; } | |
| 443 | + return array($w, $h, $colspace, $bpc, $channels); | |
| 444 | +} | |
| 445 | + | |
| 446 | +function file_get_contents_by_curl($url, &$data) { | |
| 447 | + $timeout = 5; | |
| 448 | + $ch = curl_init($url); | |
| 449 | + curl_setopt($ch, CURLOPT_HEADER, 0); | |
| 450 | + curl_setopt($ch, CURLOPT_NOBODY, 0); | |
| 451 | + curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 ); | |
| 452 | + curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , $timeout ); | |
| 453 | + $data = curl_exec($ch); | |
| 454 | + curl_close($ch); | |
| 455 | +} | |
| 456 | + | |
| 457 | + | |
| 458 | +function file_get_contents_by_socket($url, &$data) { | |
| 459 | + // mPDF 5.7.3 | |
| 460 | + $timeout = 1; | |
| 461 | + $p = parse_url($url); | |
| 462 | + $file = $p['path']; | |
| 463 | + if ($p['scheme']=='https') { | |
| 464 | + $prefix = 'ssl://'; | |
| 465 | + $port = ($p['port'] ? $p['port'] : 443); | |
| 466 | + } | |
| 467 | + else { | |
| 468 | + $prefix = ''; | |
| 469 | + $port = ($p['port'] ? $p['port'] : 80); | |
| 470 | + } | |
| 471 | + if ($p['query']) { $file .= '?'.$p['query']; } | |
| 472 | + if(!($fh = @fsockopen($prefix.$p['host'], $port, $errno, $errstr, $timeout))) { return false; } | |
| 473 | + | |
| 474 | + $getstring = | |
| 475 | + "GET ".$file." HTTP/1.0 \r\n" . | |
| 476 | + "Host: ".$p['host']." \r\n" . | |
| 477 | + "Connection: close\r\n\r\n"; | |
| 478 | + fwrite($fh, $getstring); | |
| 479 | + // Get rid of HTTP header | |
| 480 | + $s = fgets($fh, 1024); | |
| 481 | + if (!$s) { return false; } | |
| 482 | + $httpheader .= $s; | |
| 483 | + while (!feof($fh)) { | |
| 484 | + $s = fgets($fh, 1024); | |
| 485 | + if ( $s == "\r\n" ) { break; } | |
| 486 | + } | |
| 487 | + $data = ''; | |
| 488 | + while (!feof($fh)) { | |
| 489 | + $data .= fgets($fh, 1024); | |
| 490 | + } | |
| 491 | + fclose($fh); | |
| 492 | +} | |
| 493 | + | |
| 494 | +//============================================================== | |
| 495 | + | |
| 496 | +function _imageTypeFromString(&$data) { | |
| 497 | + $type = ''; | |
| 498 | + if (substr($data, 6, 4)== 'JFIF' || substr($data, 6, 4)== 'Exif' || substr($data, 0, 2)== chr(255).chr(216)) { // 0xFF 0xD8 | |
| 499 | + $type = 'jpeg'; | |
| 500 | + } | |
| 501 | + else if (substr($data, 0, 6)== "GIF87a" || substr($data, 0, 6)== "GIF89a") { | |
| 502 | + $type = 'gif'; | |
| 503 | + } | |
| 504 | + else if (substr($data, 0, 8)== chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) { | |
| 505 | + $type = 'png'; | |
| 506 | + } | |
| 507 | +/*-- IMAGES-WMF --*/ | |
| 508 | + else if (substr($data, 0, 4)== chr(215).chr(205).chr(198).chr(154)) { | |
| 509 | + $type = 'wmf'; | |
| 510 | + } | |
| 511 | +/*-- END IMAGES-WMF --*/ | |
| 512 | + else if (preg_match('/<svg.*<\/svg>/is',$data)) { | |
| 513 | + $type = 'svg'; | |
| 514 | + } | |
| 515 | + // BMP images | |
| 516 | + else if (substr($data, 0, 2)== "BM") { | |
| 517 | + $type = 'bmp'; | |
| 518 | + } | |
| 519 | + return $type; | |
| 520 | +} | |