Пример #1
0
 /**
  * Get width and height from the bmp header.
  *
  * @param File $image
  * @param string $filename
  * @return array
  */
 function getImageSize($image, $filename)
 {
     $f = fopen($filename, 'rb');
     if (!$f) {
         return false;
     }
     $header = fread($f, 54);
     fclose($f);
     // Extract binary form of width and height from the header
     $w = substr($header, 18, 4);
     $h = substr($header, 22, 4);
     // Convert the unsigned long 32 bits (little endian):
     try {
         $w = wfUnpack('V', $w, 4);
         $h = wfUnpack('V', $h, 4);
     } catch (Exception $e) {
         return false;
     }
     return [$w[1], $h[1]];
 }
Пример #2
0
 /**
  * Metadata for a given XCF file
  *
  * Will return false if file magic signature is not recognized
  * @author Hexmode
  * @author Hashar
  *
  * @param string $filename Full path to a XCF file
  * @return bool|array Metadata Array just like PHP getimagesize()
  */
 static function getXCFMetaData($filename)
 {
     # Decode master structure
     $f = fopen($filename, 'rb');
     if (!$f) {
         return false;
     }
     # The image structure always starts at offset 0 in the XCF file.
     # So we just read it :-)
     $binaryHeader = fread($f, 26);
     fclose($f);
     /**
      * Master image structure:
      *
      * byte[9] "gimp xcf "  File type magic
      * byte[4] version      XCF version
      *                        "file" - version 0
      *                        "v001" - version 1
      *                        "v002" - version 2
      * byte    0            Zero-terminator for version tag
      * uint32  width        With of canvas
      * uint32  height       Height of canvas
      * uint32  base_type    Color mode of the image; one of
      *                         0: RGB color
      *                         1: Grayscale
      *                         2: Indexed color
      *        (enum GimpImageBaseType in libgimpbase/gimpbaseenums.h)
      */
     try {
         $header = wfUnpack("A9magic" . "/a5version" . "/Nwidth" . "/Nheight" . "/Nbase_type", $binaryHeader);
     } catch (Exception $mwe) {
         return false;
     }
     # Check values
     if ($header['magic'] !== 'gimp xcf') {
         wfDebug(__METHOD__ . " '{$filename}' has invalid magic signature.\n");
         return false;
     }
     # TODO: we might want to check for sane values of width and height
     wfDebug(__METHOD__ . ": canvas size of '{$filename}' is {$header['width']} x {$header['height']} px\n");
     return $header;
 }
Пример #3
0
 /**
  * Metadata for a given XCF file
  *
  * Will return false if file magic signature is not recognized
  * @author Hexmode
  * @author Hashar
  *
  * @param string $filename Full path to a XCF file
  * @return bool|array metadata array just like PHP getimagesize()
  */
 static function getXCFMetaData($filename)
 {
     # Decode master structure
     $f = fopen($filename, 'rb');
     if (!$f) {
         return false;
     }
     # The image structure always starts at offset 0 in the XCF file.
     # So we just read it :-)
     $binaryHeader = fread($f, 26);
     fclose($f);
     # Master image structure:
     #
     # byte[9] "gimp xcf "  File type magic
     # byte[4] version      XCF version
     #                        "file" - version 0
     #                        "v001" - version 1
     #                        "v002" - version 2
     # byte    0            Zero-terminator for version tag
     # uint32  width        With of canvas
     # uint32  height       Height of canvas
     # uint32  base_type    Color mode of the image; one of
     #                         0: RGB color
     #                         1: Grayscale
     #                         2: Indexed color
     #        (enum GimpImageBaseType in libgimpbase/gimpbaseenums.h)
     try {
         $header = wfUnpack("A9magic" . "/a5version" . "/Nwidth" . "/Nheight" . "/Nbase_type", $binaryHeader);
     } catch (MWException $mwe) {
         return false;
     }
     # Check values
     if ($header['magic'] !== 'gimp xcf') {
         wfDebug(__METHOD__ . " '{$filename}' has invalid magic signature.\n");
         return false;
     }
     # TODO: we might want to check for sane values of width and height
     wfDebug(__METHOD__ . ": canvas size of '{$filename}' is {$header['width']} x {$header['height']} px\n");
     # Forge a return array containing metadata information just like getimagesize()
     # See PHP documentation at: http://www.php.net/getimagesize
     $metadata = array();
     $metadata[0] = $header['width'];
     $metadata[1] = $header['height'];
     $metadata[2] = null;
     # IMAGETYPE constant, none exist for XCF.
     $metadata[3] = sprintf('height="%s" width="%s"', $header['height'], $header['width']);
     $metadata['mime'] = 'image/x-xcf';
     $metadata['channels'] = null;
     $metadata['bits'] = 8;
     # Always 8-bits per color
     assert('7 == count($metadata); # return array must contains 7 elements just like getimagesize() return');
     return $metadata;
 }
 /**
  * This reads the photoshop image resource.
  * Currently it only compares the iptc/iim hash
  * with the stored hash, which is used to determine the precedence
  * of the iptc data. In future it may extract some other info, like
  * url of copyright license.
  *
  * This should generally be called by BitmapMetadataHandler::doApp13()
  *
  * @param string $app13 Photoshop psir app13 block from jpg.
  * @throws MWException (It gets caught next level up though)
  * @return string If the iptc hash is good or not. One of 'iptc-no-hash',
  *   'iptc-good-hash', 'iptc-bad-hash'.
  */
 public static function doPSIR($app13)
 {
     if (!$app13) {
         throw new MWException("No App13 segment given");
     }
     // First compare hash with real thing
     // 0x404 contains IPTC, 0x425 has hash
     // This is used to determine if the iptc is newer than
     // the xmp data, as xmp programs update the hash,
     // where non-xmp programs don't.
     $offset = 14;
     // skip past PHOTOSHOP 3.0 identifier. should already be checked.
     $appLen = strlen($app13);
     $realHash = "";
     $recordedHash = "";
     // the +12 is the length of an empty item.
     while ($offset + 12 <= $appLen) {
         $valid = true;
         if (substr($app13, $offset, 4) !== '8BIM') {
             // its supposed to be 8BIM
             // but apparently sometimes isn't esp. in
             // really old jpg's
             $valid = false;
         }
         $offset += 4;
         $id = substr($app13, $offset, 2);
         // id is a 2 byte id number which identifies
         // the piece of info this record contains.
         $offset += 2;
         // some record types can contain a name, which
         // is a pascal string 0-padded to be an even
         // number of bytes. Most times (and any time
         // we care) this is empty, making it two null bytes.
         $lenName = ord(substr($app13, $offset, 1)) + 1;
         // we never use the name so skip it. +1 for length byte
         if ($lenName % 2 == 1) {
             $lenName++;
         }
         // pad to even.
         $offset += $lenName;
         // now length of data (unsigned long big endian)
         $lenData = wfUnpack('Nlen', substr($app13, $offset, 4), 4);
         // PHP can take issue with very large unsigned ints and make them negative.
         // Which should never ever happen, as this has to be inside a segment
         // which is limited to a 16 bit number.
         if ($lenData['len'] < 0) {
             throw new MWException("Too big PSIR (" . $lenData['len'] . ')');
         }
         $offset += 4;
         // 4bytes length field;
         // this should not happen, but check.
         if ($lenData['len'] + $offset > $appLen) {
             throw new MWException("PSIR data too long. (item length=" . $lenData['len'] . "; offset={$offset}; total length={$appLen})");
         }
         if ($valid) {
             switch ($id) {
                 case "":
                     // IPTC block
                     $realHash = md5(substr($app13, $offset, $lenData['len']), true);
                     break;
                 case "%":
                     $recordedHash = substr($app13, $offset, $lenData['len']);
                     break;
             }
         }
         // if odd, add 1 to length to account for
         // null pad byte.
         if ($lenData['len'] % 2 == 1) {
             $lenData['len']++;
         }
         $offset += $lenData['len'];
     }
     if (!$realHash || !$recordedHash) {
         return 'iptc-no-hash';
     } elseif ($realHash === $recordedHash) {
         return 'iptc-good-hash';
     } else {
         /*$realHash !== $recordedHash */
         return 'iptc-bad-hash';
     }
 }