public function defaultValueIfNotFound()
 {
     $this->assertNull(ExifData::fromFile($this->resourceAsFile('iptc-only.jpg'), null));
 }
 /**
  * Returns an ExifData instance or NULL if this image does not contain 
  * EXIF Data
  * 
  * @return img.util.ExifData
  */
 public function exifData()
 {
     if (!($seg = $this->segmentsOf('img.io.ExifSegment'))) {
         return null;
     }
     // Populate ExifData instance from ExifSegment's raw data
     with($data = new ExifData(), $raw = $seg[0]->rawData());
     $data->setFileName($this->source);
     $data->setFileSize(-1);
     $data->setMimeType('image/jpeg');
     $data->setMake(null === ($l = self::lookup($raw, 'Make')) ? null : trim($l));
     $data->setModel(null === ($l = self::lookup($raw, 'Model')) ? null : trim($l));
     $data->setSoftware(null === ($l = self::lookup($raw, 'Software')) ? null : trim($l));
     $exif = $raw['Exif_IFD_Pointer']['data'];
     if ($sof = $this->segmentsOf('img.io.SOFNSegment')) {
         $data->setWidth($sof[0]->width());
         $data->setHeight($sof[0]->height());
     } else {
         $data->setWidth(self::lookup($exif, 'ExifImageWidth'));
         $data->setHeight(self::lookup($exif, 'ExifImageLength'));
     }
     // Aperture is either a FNumber (use directly), otherwise calculate from value
     if (null === ($a = self::lookup($exif, 'FNumber'))) {
         if (null === ($a = self::lookup($exif, 'ApertureValue', 'MaxApertureValue'))) {
             $data->setApertureFNumber(null);
         } else {
             sscanf($a, '%d/%d', $n, $frac);
             $data->setApertureFNumber(sprintf('f/%.1F', exp($n / $frac * log(2) * 0.5)));
         }
     } else {
         sscanf($a, '%d/%d', $n, $frac);
         $data->setApertureFNumber(sprintf('f/%.1F', $n / $frac));
     }
     $data->setExposureTime(self::lookup($exif, 'ExposureTime'));
     $data->setExposureProgram(self::lookup($exif, 'ExposureProgram'));
     $data->setMeteringMode(self::lookup($exif, 'MeteringMode'));
     $data->setIsoSpeedRatings(self::lookup($exif, 'ISOSpeedRatings'));
     // Sometimes white balance is in MAKERNOTE - e.g. FUJIFILM's Finepix
     if (null !== ($w = self::lookup($exif, 'WhiteBalance'))) {
         $data->setWhiteBalance($w);
     } else {
         if (isset($exif['MakerNote']) && null !== ($w = self::lookup($exif['MakerNote']['data'], 'WhiteBalance'))) {
             $data->setWhiteBalance($w);
         } else {
             $data->setWhiteBalance(null);
         }
     }
     // Extract focal length. Some models store "80" as "80/1", rip off
     // the divisor "1" in this case.
     if (null !== ($l = self::lookup($exif, 'FocalLength'))) {
         sscanf($l, '%d/%d', $n, $frac);
         $data->setFocalLength(1 == $frac ? $n : $n . '/' . $frac);
     } else {
         $data->setFocalLength(null);
     }
     // Check for Flash and flashUsed keys
     if (null !== ($f = self::lookup($exif, 'Flash'))) {
         $data->setFlash($f);
     } else {
         $data->setFlash(null);
     }
     if (null !== ($date = self::lookup($exif, 'DateTimeOriginal', 'DateTimeDigitized', 'DateTime'))) {
         $t = sscanf($date, '%4d:%2d:%2d %2d:%2d:%2d');
         $data->setDateTime(new \util\Date(mktime($t[3], $t[4], $t[5], $t[1], $t[2], $t[0])));
     }
     if (null !== ($o = self::lookup($exif, 'Orientation'))) {
         $data->setOrientation($o);
     } else {
         $data->setOrientation($data->width / $data->height > 1.0 ? 1 : 5);
     }
     return $data;
 }