/**
 * Creates the cache folder version of the image, including watermarking
 *
 * @param string $newfilename the name of the file when it is in the cache
 * @param string $imgfile the image name
 * @param array $args the cropping arguments
 * @param bool $allow_watermark set to true if image may be watermarked
 * @param string $theme the current theme
 * @param string $album the album containing the image
 */
function cacheImage($newfilename, $imgfile, $args, $allow_watermark = false, $theme, $album)
{
    @(list($size, $width, $height, $cw, $ch, $cx, $cy, $quality, $thumb, $crop, $thumbstandin, $passedWM, $adminrequest, $effects) = $args);
    // Set the config variables for convenience.
    $image_use_side = getOption('image_use_side');
    $upscale = getOption('image_allow_upscale');
    $allowscale = true;
    $sharpenthumbs = getOption('thumb_sharpen');
    $sharpenimages = getOption('image_sharpen');
    $id = NULL;
    $watermark_use_image = getAlbumInherited($album, 'watermark', $id);
    if (empty($watermark_use_image)) {
        $watermark_use_image = IMAGE_WATERMARK;
    }
    if (!$effects) {
        if ($thumb && getOption('thumb_gray')) {
            $effects = 'gray';
        } else {
            if (getOption('image_gray')) {
                $effects = 'gray';
            }
        }
    }
    $newfile = SERVERCACHE . $newfilename;
    if (DEBUG_IMAGE) {
        debugLog("cacheImage(\$imgfile=" . basename($imgfile) . ", \$newfilename={$newfilename}, \$allow_watermark={$allow_watermark}, \$theme={$theme}) \$size={$size}, \$width={$width}, \$height={$height}, \$cw={$cw}, \$ch={$ch}, \$cx=" . (is_null($cx) ? 'NULL' : $cx) . ", \$cy=" . (is_null($cy) ? 'NULL' : $cy) . ", \$quality={$quality}, \$thumb={$thumb}, \$crop={$crop} \$image_use_side={$image_use_side}; \$upscale={$upscale};");
    }
    // Check for the source image.
    if (!file_exists($imgfile) || !is_readable($imgfile)) {
        imageError(gettext('Image not found or is unreadable.'), 'err-imagenotfound.png');
    }
    $rotate = false;
    if (zp_imageCanRotate() && getOption('auto_rotate')) {
        $rotate = getImageRotation($imgfile);
    }
    if ($im = zp_imageGet($imgfile)) {
        if ($rotate) {
            $im = zp_rotateImage($im, $rotate);
        }
        $w = zp_imageWidth($im);
        $h = zp_imageHeight($im);
        // Give the sizing dimension to $dim
        $ratio_in = '';
        $ratio_out = '';
        $crop = $crop || $cw != 0 || $ch != 0;
        if (!empty($size)) {
            $dim = $size;
            $width = $height = false;
            if ($crop) {
                $dim = $size;
                if (!$ch) {
                    $ch = $size;
                }
                if (!$cw) {
                    $cw = $size;
                }
            }
        } else {
            if (!empty($width) && !empty($height)) {
                $ratio_in = $h / $w;
                $ratio_out = $height / $width;
                if ($ratio_in > $ratio_out) {
                    // image is taller than desired, $height is the determining factor
                    $thumb = true;
                    $dim = $width;
                    if (!$ch) {
                        $ch = $height;
                    }
                } else {
                    // image is wider than desired, $width is the determining factor
                    $dim = $height;
                    if (!$cw) {
                        $cw = $width;
                    }
                }
            } else {
                if (!empty($width)) {
                    $dim = $width;
                    $size = $height = false;
                } else {
                    if (!empty($height)) {
                        $dim = $height;
                        $size = $width = false;
                    } else {
                        // There's a problem up there somewhere...
                        imageError(gettext("Unknown error! Please report to the developers at <a href=\"http://www.zenphoto.org/\">www.zenphoto.org</a>"), 'err-imagegeneral.png');
                    }
                }
            }
        }
        $sizes = propSizes($size, $width, $height, $w, $h, $thumb, $image_use_side, $dim);
        list($neww, $newh) = $sizes;
        if (DEBUG_IMAGE) {
            debugLog("cacheImage:" . basename($imgfile) . ": \$size={$size}, \$width={$width}, \$height={$height}, \$w={$w}; \$h={$h}; \$cw={$cw}, " . "\$ch={$ch}, \$cx={$cx}, \$cy={$cy}, \$quality={$quality}, \$thumb={$thumb}, \$crop={$crop}, \$newh={$newh}, \$neww={$neww}, \$dim={$dim}, " . "\$ratio_in={$ratio_in}, \$ratio_out={$ratio_out} \$upscale={$upscale} \$rotate={$rotate} \$effects={$effects}");
        }
        if (!$upscale && $newh >= $h && $neww >= $w) {
            // image is the same size or smaller than the request
            $neww = $w;
            $newh = $h;
            $allowscale = false;
            if ($crop) {
                if ($width > $neww) {
                    $width = $neww;
                }
                if ($height > $newh) {
                    $height = $newh;
                }
            }
            if (DEBUG_IMAGE) {
                debugLog("cacheImage:no upscale " . basename($imgfile) . ":  \$newh={$newh}, \$neww={$neww}, \$crop={$crop}, \$thumb={$thumb}, \$rotate={$rotate}, watermark=" . $watermark_use_image);
            }
        }
        // Crop the image if requested.
        if ($crop) {
            if ($cw > $ch) {
                $ir = $ch / $cw;
            } else {
                $ir = $cw / $ch;
            }
            if ($size) {
                $neww = $size;
                $newh = $ir * $size;
            } else {
                $neww = $width;
                $newh = $height;
                if ($neww > $newh) {
                    if ($newh === false) {
                        $newh = $ir * $neww;
                    }
                } else {
                    if ($neww === false) {
                        $neww = $ir * $newh;
                    }
                }
            }
            if (is_null($cx) && is_null($cy)) {
                // scale crop to max of image
                // set crop scale factor
                $cf = 1;
                if ($cw) {
                    $cf = min($cf, $cw / $neww);
                }
                if ($ch) {
                    $cf = min($cf, $ch / $newh);
                }
                //	set the image area of the crop (use the most image possible, rule of thirds positioning)
                if (!$cw || $w / $cw * $ch > $h) {
                    $cw = round($h / $ch * $cw * $cf);
                    $ch = round($h * $cf);
                    $cx = round(($w - $cw) / 3);
                } else {
                    $ch = round($w / $cw * $ch * $cf);
                    $cw = round($w * $cf);
                    $cy = round(($h - $ch) / 3);
                }
            } else {
                // custom crop
                if (!$cw || $cw > $w) {
                    $cw = $w;
                }
                if (!$ch || $ch > $h) {
                    $ch = $h;
                }
            }
            // force the crop to be within the image
            if ($cw + $cx > $w) {
                $cx = $w - $cw;
            }
            if ($cx < 0) {
                $cw = $cw + $cx;
                $cx = 0;
            }
            if ($ch + $cy > $h) {
                $cy = $h - $ch;
            }
            if ($cy < 0) {
                $ch = $ch + $cy;
                $cy = 0;
            }
            if (DEBUG_IMAGE) {
                debugLog("cacheImage:crop " . basename($imgfile) . ":\$size={$size}, \$width={$width}, \$height={$height}, \$cw={$cw}, \$ch={$ch}, \$cx={$cx}, \$cy={$cy}, \$quality={$quality}, \$thumb={$thumb}, \$crop={$crop}, \$rotate={$rotate}");
            }
            $newim = zp_createImage($neww, $newh);
            zp_resampleImage($newim, $im, 0, 0, $cx, $cy, $neww, $newh, $cw, $ch);
        } else {
            if ($allowscale) {
                $sizes = propSizes($size, $width, $height, $w, $h, $thumb, $image_use_side, $dim);
                list($neww, $newh) = $sizes;
            }
            if (DEBUG_IMAGE) {
                debugLog("cacheImage:no crop " . basename($imgfile) . ":\$size={$size}, \$width={$width}, \$height={$height}, \$dim={$dim}, \$neww={$neww}; \$newh={$newh}; \$quality={$quality}, \$thumb={$thumb}, \$crop={$crop}, \$rotate={$rotate}; \$allowscale={$allowscale};");
            }
            $newim = zp_createImage($neww, $newh);
            zp_resampleImage($newim, $im, 0, 0, 0, 0, $neww, $newh, $w, $h);
        }
        $imgEffects = explode(',', $effects);
        if (in_array('gray', $imgEffects)) {
            zp_imageGray($newim);
        }
        if ($thumb && $sharpenthumbs || !$thumb && $sharpenimages) {
            zp_imageUnsharpMask($newim, getOption('sharpen_amount'), getOption('sharpen_radius'), getOption('sharpen_threshold'));
        }
        $watermark_image = false;
        if ($passedWM) {
            if ($passedWM != NO_WATERMARK) {
                $watermark_image = getWatermarkPath($passedWM);
                if (!file_exists($watermark_image)) {
                    $watermark_image = SERVERPATH . '/' . ZENFOLDER . '/images/imageDefault.png';
                }
            }
        } else {
            if ($allow_watermark) {
                $watermark_image = $watermark_use_image;
                if ($watermark_image) {
                    if ($watermark_image != NO_WATERMARK) {
                        $watermark_image = getWatermarkPath($watermark_image);
                        if (!file_exists($watermark_image)) {
                            $watermark_image = SERVERPATH . '/' . ZENFOLDER . '/images/imageDefault.png';
                        }
                    }
                }
            }
        }
        if ($watermark_image) {
            $offset_h = getOption('watermark_h_offset') / 100;
            $offset_w = getOption('watermark_w_offset') / 100;
            $watermark = zp_imageGet($watermark_image);
            $watermark_width = zp_imageWidth($watermark);
            $watermark_height = zp_imageHeight($watermark);
            $imw = zp_imageWidth($newim);
            $imh = zp_imageHeight($newim);
            $nw = sqrt($imw * $imh * $percent * ($watermark_width / $watermark_height));
            $nh = $nw * ($watermark_height / $watermark_width);
            $percent = getOption('watermark_scale') / 100;
            $r = sqrt($imw * $imh * $percent / ($watermark_width * $watermark_height));
            if (!getOption('watermark_allow_upscale')) {
                $r = min(1, $r);
            }
            $nw = round($watermark_width * $r);
            $nh = round($watermark_height * $r);
            if ($nw != $watermark_width || $nh != $watermark_height) {
                $watermark = zp_imageResizeAlpha($watermark, $nw, $nh);
            }
            // Position Overlay in Bottom Right
            $dest_x = max(0, floor(($imw - $nw) * $offset_w));
            $dest_y = max(0, floor(($imh - $nh) * $offset_h));
            if (DEBUG_IMAGE) {
                debugLog("Watermark:" . basename($imgfile) . ": \$offset_h={$offset_h}, \$offset_w={$offset_w}, \$watermark_height={$watermark_height}, \$watermark_width={$watermark_width}, \$imw={$imw}, \$imh={$imh}, \$percent={$percent}, \$r={$r}, \$nw={$nw}, \$nh={$nh}, \$dest_x={$dest_x}, \$dest_y={$dest_y}");
            }
            zp_copyCanvas($newim, $watermark, $dest_x, $dest_y, 0, 0, $nw, $nh);
            zp_imageKill($watermark);
        }
        // Create the cached file (with lots of compatibility)...
        mkdir_recursive(dirname($newfile));
        if (zp_imageOutput($newim, getSuffix($newfile), $newfile, $quality)) {
            //	successful save of cached image
            if (getOption('ImbedIPTC') && getSuffix($newfilename) == 'jpg') {
                // the imbed function works only with JPEG images
                $iptc_data = zp_imageIPTC($imgfile);
                if (empty($iptc_data)) {
                    global $_zp_extra_filetypes;
                    //	because we are doing the require in a function!
                    if (!$_zp_extra_filetypes) {
                        $_zp_extra_filetypes = array();
                    }
                    require_once dirname(__FILE__) . '/functions.php';
                    //	it is ok to increase memory footprint now since the image processing is complete
                    $gallery = new Gallery();
                    $iptc = array('1#090' => chr(0x1b) . chr(0x25) . chr(0x47), '2#115' => $gallery->getTitle());
                    $imgfile = str_replace(ALBUM_FOLDER_SERVERPATH, '', $imgfile);
                    $imagename = basename($imgfile);
                    $albumname = dirname($imgfile);
                    $image = newImage(new Album(new Gallery(), $albumname), $imagename);
                    $copyright = $image->getCopyright();
                    if (empty($copyright)) {
                        $copyright = getOption('default_copyright');
                    }
                    if (!empty($copyright)) {
                        $iptc['2#116'] = $copyright;
                    }
                    $credit = $image->getCredit();
                    if (!empty($credit)) {
                        $iptc['2#110'] = $credit;
                    }
                    foreach ($iptc as $tag => $string) {
                        $tag_parts = explode('#', $tag);
                        $iptc_data .= iptc_make_tag($tag_parts[0], $tag_parts[1], $string);
                    }
                } else {
                    if (GRAPHICS_LIBRARY == 'Imagick' && IMAGICK_RETAIN_PROFILES) {
                        //	Imageick has preserved the metadata
                        $iptc_data = false;
                    }
                }
                if ($iptc_data) {
                    $content = iptcembed($iptc_data, $newfile);
                    $fw = fopen($newfile, 'w');
                    fwrite($fw, $content);
                    fclose($fw);
                    clearstatcache();
                }
            }
            if (DEBUG_IMAGE) {
                debugLog('Finished:' . basename($imgfile));
            }
        } else {
            if (DEBUG_IMAGE) {
                debugLog('cacheImage: failed to create ' . $newfile);
            }
        }
        @chmod($newfile, 0666 & CHMOD_VALUE);
        zp_imageKill($newim);
        zp_imageKill($im);
    }
}
Exemple #2
0
 /**
  * Parses Exif/IPTC data
  *
  */
 function updateMetaData()
 {
     global $_zp_exifvars, $_zp_gallery;
     if ($_zp_exifvars) {
         require_once dirname(__FILE__) . '/exif/exif.php';
         $IPTCtags = array('SKIP' => '2#000', 'ObjectType' => '2#003', 'ObjectAttr' => '2#004', 'ObjectName' => '2#005', 'EditStatus' => '2#007', 'EditorialUpdate' => '2#008', 'Urgency' => '2#010', 'SubRef' => '2#012', 'Category' => '2#015', 'SuppCategory' => '2#020', 'FixtureID' => '2#022', 'Keywords' => '2#025', 'ContentLocationCode' => '2#026', 'ContentLocationName' => '2#027', 'ReleaseDate' => '2#030', 'ReleaseTime' => '2#035', 'ExpireDate' => '2#037', 'ExpireTime' => '2#038', 'SpecialInstru' => '2#040', 'ActionAdvised' => '2#042', 'RefService' => '2#045', 'RefDate' => '2#047', 'RefNumber' => '2#050', 'DateCreated' => '2#055', 'TimeCreated' => '2#060', 'DigitizeDate' => '2#062', 'DigitizeTime' => '2#063', 'OriginatingProgram' => '2#065', 'ProgramVersion' => '2#070', 'ObjectCycle' => '2#075', 'ByLine' => '2#080', 'ByLineTitle' => '2#085', 'City' => '2#090', 'SubLocation' => '2#092', 'State' => '2#095', 'LocationCode' => '2#100', 'LocationName' => '2#101', 'TransmissionRef' => '2#103', 'ImageHeadline' => '2#105', 'ImageCredit' => '2#110', 'Source' => '2#115', 'Copyright' => '2#116', 'Contact' => '2#118', 'ImageCaption' => '2#120', 'ImageCaptionWriter' => '2#122', 'ImageType' => '2#130', 'Orientation' => '2#131', 'LangID' => '2#135', 'Subfile' => '8#010');
         $this->set('hasMetadata', 0);
         foreach ($_zp_exifvars as $field => $exifvar) {
             $this->set($field, NULL);
         }
         $result = array();
         if (get_class($this) == 'Image') {
             $localpath = $this->localpath;
         } else {
             $localpath = $this->getThumbImageFile();
         }
         if (!empty($localpath)) {
             // there is some kind of image to get metadata from
             $exifraw = read_exif_data_protected($localpath);
             if (isset($exifraw['ValidEXIFData'])) {
                 $this->set('hasMetadata', 1);
                 foreach ($_zp_exifvars as $field => $exifvar) {
                     $exif = NULL;
                     if (isset($exifraw[$exifvar[0]][$exifvar[1]])) {
                         $exif = trim(sanitize($exifraw[$exifvar[0]][$exifvar[1]], 1));
                     } else {
                         if (isset($exifraw[$exifvar[0]]['MakerNote'][$exifvar[1]])) {
                             $exif = trim(sanitize($exifraw[$exifvar[0]]['MakerNote'][$exifvar[1]], 1));
                         }
                     }
                     $this->set($field, $exif);
                 }
             }
             /* check IPTC data */
             $iptcdata = zp_imageIPTC($localpath);
             if (!empty($iptcdata)) {
                 $iptc = iptcparse($iptcdata);
                 if ($iptc) {
                     $this->set('hasMetadata', 1);
                     $characterset = self::getIPTCTag('1#090', $iptc);
                     if (!$characterset) {
                         $characterset = getOption('IPTC_encoding');
                     } else {
                         if (substr($characterset, 0, 1) == chr(27)) {
                             // IPTC escape encoding
                             $characterset = substr($characterset, 1);
                             if ($characterset == '%G') {
                                 $characterset = 'UTF-8';
                             } else {
                                 // we don't know, need to understand the IPTC standard here. In the mean time, default it.
                                 $characterset = getOption('IPTC_encoding');
                             }
                         } else {
                             if ($characterset == 'UTF8') {
                                 $characterset = 'UTF-8';
                             }
                         }
                     }
                     // Extract IPTC fields of interest
                     foreach ($_zp_exifvars as $field => $exifvar) {
                         if ($exifvar[0] == 'IPTC') {
                             $datum = self::getIPTCTag($IPTCtags[$exifvar[1]], $iptc);
                             $this->set($field, $this->prepIPTCString($datum, $characterset));
                         }
                     }
                     /* iptc keywords (tags) */
                     if ($_zp_exifvars['IPTCKeywords'][5]) {
                         $datum = self::getIPTCTagArray($IPTCtags['Keywords'], $iptc);
                         if (is_array($datum)) {
                             $tags = array();
                             $result['tags'] = array();
                             foreach ($datum as $item) {
                                 $tags[] = $this->prepIPTCString(sanitize($item, 3), $characterset);
                             }
                             $this->setTags($tags);
                         }
                     }
                 }
             }
         }
         /* "import" metadata into database fields as makes sense */
         /* ZenPhoto20 Image Rotation */
         $this->set('rotation', substr(trim(self::fetchMetadata('EXIFOrientation'), '!'), 0, 1));
         /* ZenPhoto20 "date" field population */
         if ($date = self::fetchMetadata('IPTCDateCreated')) {
             if (strlen($date) > 8) {
                 $time = substr($date, 8);
             } else {
                 /* got date from IPTC, now must get time */
                 $time = $this->get('IPTCTimeCreated');
             }
             $date = substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2);
             if (!empty($time)) {
                 $date = $date . ' ' . substr($time, 0, 2) . ':' . substr($time, 2, 2) . ':' . substr($time, 4, 2);
             }
         }
         if (empty($date)) {
             $date = self::fetchMetadata('EXIFDateTime');
         }
         if (empty($date)) {
             $date = self::fetchMetadata('EXIFDateTimeOriginal');
         }
         if (empty($date)) {
             $date = self::fetchMetadata('EXIFDateTimeDigitized');
         }
         if (empty($date)) {
             $this->setDateTime(strftime('%Y-%m-%d %H:%M:%S', $this->filemtime));
         } else {
             $this->setDateTime($date);
         }
         /* ZenPhoto20 "title" field population */
         $title = self::fetchMetadata('IPTCObjectName');
         if (empty($title)) {
             $title = self::fetchMetadata('IPTCImageHeadline');
         }
         if (empty($title)) {
             $title = self::fetchMetadata('EXIFDescription');
             //EXIF title [sic]
         }
         if (!empty($title)) {
             if (getoption('transform_newlines')) {
                 $title = nl2br($title);
             }
             $this->setTitle($title);
         }
         /* ZenPhoto20 "description" field population */
         $desc = self::fetchMetadata('IPTCImageCaption');
         if (!empty($desc)) {
             if (getoption('transform_newlines')) {
                 $desc = nl2br($desc);
             }
             $this->setDesc($desc);
         }
         //	ZenPhoyo20 GPS data
         foreach (array('EXIFGPSLatitude', 'EXIFGPSLongitude') as $source) {
             $data = self::fetchMetadata($source);
             if (!empty($data)) {
                 $ref = strtoupper($this->get($source . 'Ref'));
                 $this->set($source, self::toDMS($data, $ref));
                 if (in_array($ref, array('S', 'W'))) {
                     $data = '-' . $data;
                 }
                 $this->set(substr($source, 4), $data);
             }
         }
         $alt = self::fetchMetadata('EXIFGPSAltitude');
         if (!empty($alt)) {
             if (self::fetchMetadata('EXIFGPSAltitudeRef') == '-') {
                 $alt = -$alt;
             }
             $this->set('GPSAltitude', $alt);
         }
         //	simple field imports
         $import = array('location' => 'IPTCSubLocation', 'city' => 'IPTCCity', 'state' => 'IPTCState', 'country' => 'IPTCLocationName', 'copyright' => 'IPTCCopyright');
         foreach ($import as $key => $source) {
             $data = self::fetchMetadata($source);
             $this->set($key, $data);
         }
         /* ZenPhoto20 "credit" field population */
         $credit = self::fetchMetadata('IPTCByLine');
         if (empty($credit)) {
             $credit = self::fetchMetadata('IPTCImageCredit');
         }
         if (empty($credit)) {
             $credit = self::fetchMetadata('IPTCSource');
         }
         if (!empty($credit)) {
             $this->setCredit($credit);
         }
         zp_apply_filter('image_metadata', $this);
         $alb = $this->album;
         if (is_object($alb)) {
             if (!$this->get('owner')) {
                 $this->setOwner($alb->getOwner());
             }
             $save = false;
             if (strtotime($alb->getUpdatedDate()) < strtotime($this->getDateTime())) {
                 $alb->setUpdatedDate($this->getDateTime());
                 $save = true;
             }
             if (is_null($albdate = $alb->getDateTime()) || $_zp_gallery->getAlbumUseImagedate() && strtotime($albdate) < strtotime($this->getDateTime())) {
                 $alb->setDateTime($this->getDateTime());
                 //  not necessarily the right one, but will do. Can be changed in Admin
                 $save = true;
             }
             if ($save) {
                 $alb->save();
             }
         }
     }
 }
 /**
  * Parses Exif/IPTC data
  *
  */
 function updateMetaData()
 {
     require_once dirname(__FILE__) . '/exif/exif.php';
     global $_zp_exifvars;
     $IPTCtags = array('SKIP' => '2#000', 'ObjectType' => '2#003', 'ObjectAttr' => '2#004', 'ObjectName' => '2#005', 'EditStatus' => '2#007', 'EditorialUpdate' => '2#008', 'Urgency' => '2#010', 'SubRef' => '2#012', 'Category' => '2#015', 'SuppCategory' => '2#020', 'FixtureID' => '2#022', 'Keywords' => '2#025', 'ContentLocCode' => '2#026', 'ContentLocName' => '2#027', 'ReleaseDate' => '2#030', 'ReleaseTime' => '2#035', 'ExpireDate' => '2#037', 'ExpireTime' => '2#038', 'SpecialInstru' => '2#040', 'ActionAdvised' => '2#042', 'RefService' => '2#045', 'RefDate' => '2#047', 'RefNumber' => '2#050', 'DateCreated' => '2#055', 'TimeCreated' => '2#060', 'DigitizeDate' => '2#062', 'DigitizeTime' => '2#063', 'OriginatingProgram' => '2#065', 'ProgramVersion' => '2#070', 'ObjectCycle' => '2#075', 'ByLine' => '2#080', 'ByLineTitle' => '2#085', 'City' => '2#090', 'SubLocation' => '2#092', 'State' => '2#095', 'LocationCode' => '2#100', 'LocationName' => '2#101', 'TransmissionRef' => '2#103', 'ImageHeadline' => '2#105', 'ImageCredit' => '2#110', 'Source' => '2#115', 'Copyright' => '2#116', 'Contact' => '2#118', 'ImageCaption' => '2#120', 'ImageCaptionWriter' => '2#122', 'ImageType' => '2#130', 'Orientation' => '2#131', 'LangID' => '2#135', 'Subfile' => '8#010');
     $this->set('hasMetadata', 0);
     $result = array();
     if (get_class($this) == '_Image') {
         $localpath = $this->localpath;
     } else {
         $localpath = $this->getThumbImageFile();
     }
     $xdate = $this->getDateTime();
     if (!empty($localpath)) {
         // there is some kind of image to get metadata from
         $exifraw = read_exif_data_protected($localpath);
         if (isset($exifraw['ValidEXIFData'])) {
             $this->set('hasMetadata', 1);
             foreach ($_zp_exifvars as $field => $exifvar) {
                 if (isset($exifraw[$exifvar[0]][$exifvar[1]])) {
                     $exif = trim(sanitize($exifraw[$exifvar[0]][$exifvar[1]], 1));
                     $this->set($field, $exif);
                 } else {
                     if (isset($exifraw[$exifvar[0]]['MakerNote'][$exifvar[1]])) {
                         $exif = trim(sanitize($exifraw[$exifvar[0]]['MakerNote'][$exifvar[1]], 1));
                         $this->set($field, $exif);
                     }
                 }
             }
         }
         /* check IPTC data */
         $iptcdata = zp_imageIPTC($localpath);
         if (!empty($iptcdata)) {
             $iptc = iptcparse($iptcdata);
             if ($iptc) {
                 $this->set('hasMetadata', 1);
                 $characterset = $this->getIPTCTag('1#090', $iptc);
                 if (!$characterset) {
                     $characterset = getOption('IPTC_encoding');
                 } else {
                     if (substr($characterset, 0, 1) == chr(27)) {
                         // IPTC escape encoding
                         $characterset = substr($characterset, 1);
                         if ($characterset == '%G') {
                             $characterset = 'UTF-8';
                         } else {
                             // we don't know, need to understand the IPTC standard here. In the mean time, default it.
                             $characterset = getOption('IPTC_encoding');
                         }
                     } else {
                         if ($characterset == 'UTF8') {
                             $characterset = 'UTF-8';
                         }
                     }
                 }
                 // Extract IPTC fields of interest
                 foreach ($_zp_exifvars as $field => $exifvar) {
                     if ($exifvar[0] == 'IPTC') {
                         $datum = $this->getIPTCTag($IPTCtags[$exifvar[1]], $iptc);
                         $this->set($field, $this->prepIPTCString($datum, $characterset));
                     }
                 }
                 /* iptc keywords (tags) */
                 $datum = $this->getIPTCTagArray('2#025', $iptc);
                 if (is_array($datum)) {
                     $tags = array();
                     $result['tags'] = array();
                     foreach ($datum as $item) {
                         $tags[] = $this->prepIPTCString(sanitize($item, 3), $characterset);
                     }
                     $this->setTags($tags);
                 }
             }
         }
     }
     /* "import" metadata into Zenphoto fields as makes sense */
     zp_apply_filter('image_metadata', $this);
     /* iptc date */
     $date = $this->get('IPTCDateCreated');
     if (!empty($date)) {
         if (strlen($date) > 8) {
             $time = substr($date, 8);
         } else {
             /* got date from IPTC, now must get time */
             $time = $this->get('IPTCTimeCreated');
         }
         $date = substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2);
         if (!empty($time)) {
             $date = $date . ' ' . substr($time, 0, 2) . ':' . substr($time, 2, 2) . ':' . substr($time, 4, 2);
         }
     }
     /* EXIF date */
     if (empty($date)) {
         $date = $this->get('EXIFDateTime');
     }
     if (empty($date)) {
         $date = $this->get('EXIFDateTimeOriginal');
     }
     if (empty($date)) {
         $date = $this->get('EXIFDateTimeDigitized');
     }
     if (!empty($date)) {
         $xdate = $date;
         $this->setDateTime($date);
     }
     /* iptc title */
     $title = $this->get('IPTCObjectName');
     if (empty($title)) {
         $title = $this->get('IPTCImageHeadline');
     }
     //EXIF title [sic]
     if (empty($title)) {
         $title = $this->get('EXIFDescription');
     }
     if (!empty($title)) {
         $this->setTitle($title);
     }
     /* iptc description */
     $desc = $this->get('IPTCImageCaption');
     if (!empty($desc)) {
         $this->setDesc($desc);
     }
     /* iptc location, state, country */
     $loc = $this->get('IPTCSubLocation');
     if (!empty($loc)) {
         $this->setLocation($loc);
     }
     $city = $this->get('IPTCCity');
     if (!empty($city)) {
         $this->setCity($city);
     }
     $state = $this->get('IPTCState');
     if (!empty($state)) {
         $this->setState($state);
     }
     $country = $this->get('IPTCLocationName');
     if (!empty($country)) {
         $this->setCountry($country);
     }
     /* iptc credit */
     $credit = $this->get('IPTCByLine');
     if (empty($credit)) {
         $credit = $this->get('IPTCImageCredit');
     }
     if (empty($credit)) {
         $credit = $this->get('IPTCSource');
     }
     if (!empty($credit)) {
         $this->setCredit($credit);
     }
     /* iptc copyright */
     $this->setCopyright($this->get('IPTCCopyright'));
     $x = $this->getTitle();
     if (empty($x)) {
         $this->set('title', $this->getDefaultTitle());
     }
     if (empty($xdate)) {
         $this->set('date', strftime('%Y-%m-%d %H:%M:%S', $this->get('mtime')));
     }
     $alb = $this->album;
     if (!is_null($alb)) {
         $save = false;
         if (strtotime($alb->getUpdatedDate()) < strtotime($this->getDateTime())) {
             $alb->setUpdatedDate($this->getDateTime());
             $save = true;
         }
         if (is_null($albdate = $alb->getDateTime()) || $this->album->gallery->getAlbumUseImagedate() && strtotime($albdate) < strtotime($this->getDateTime())) {
             $this->album->setDateTime($this->getDateTime());
             //  not necessarily the right one, but will do. Can be changed in Admin
             $save = true;
         }
         if ($save) {
             $this->album->save();
         }
     }
 }
/**
 * Creates the cache folder version of the image, including watermarking
 *
 * @param string $newfilename the name of the file when it is in the cache
 * @param string $imgfile the image name
 * @param array $args the cropping arguments
 * @param bool $allow_watermark set to true if image may be watermarked
 * @param string $theme the current theme
 * @param string $album the album containing the image
 */
function cacheImage($newfilename, $imgfile, $args, $allow_watermark = false, $theme, $album)
{
    global $_zp_gallery;
    try {
        @(list($size, $width, $height, $cw, $ch, $cx, $cy, $quality, $thumb, $crop, $thumbstandin, $passedWM, $adminrequest, $effects) = $args);
        // Set the config variables for convenience.
        $image_use_side = getOption('image_use_side');
        $upscale = getOption('image_allow_upscale');
        $allowscale = true;
        $sharpenthumbs = getOption('thumb_sharpen');
        $sharpenimages = getOption('image_sharpen');
        $id = $im = NULL;
        $watermark_use_image = getAlbumInherited($album, 'watermark', $id);
        if (empty($watermark_use_image)) {
            $watermark_use_image = IMAGE_WATERMARK;
        }
        if (!$effects) {
            if ($thumb && getOption('thumb_gray')) {
                $effects = 'gray';
            } else {
                if (getOption('image_gray')) {
                    $effects = 'gray';
                }
            }
        }
        $newfile = SERVERCACHE . $newfilename;
        mkdir_recursive(dirname($newfile), FOLDER_MOD);
        if (DEBUG_IMAGE) {
            debugLog("cacheImage(\$imgfile=" . basename($imgfile) . ", \$newfilename={$newfilename}, \$allow_watermark={$allow_watermark}, \$theme={$theme}) \$size={$size}, \$width={$width}, \$height={$height}, \$cw={$cw}, \$ch={$ch}, \$cx=" . (is_null($cx) ? 'NULL' : $cx) . ", \$cy=" . (is_null($cy) ? 'NULL' : $cy) . ", \$quality={$quality}, \$thumb={$thumb}, \$crop={$crop} \$image_use_side={$image_use_side}; \$upscale={$upscale});");
        }
        // Check for the source image.
        if (!file_exists($imgfile) || !is_readable($imgfile)) {
            imageError('404 Not Found', sprintf(gettext('Image %s not found or is unreadable.'), filesystemToInternal($imgfile)), 'err-imagenotfound.png');
        }
        $rotate = false;
        if (zp_imageCanRotate()) {
            $rotate = getImageRotation($imgfile);
        }
        $s = getSuffix($imgfile);
        if (function_exists('exif_thumbnail') && getOption('use_embedded_thumb') && ($s == 'jpg' || $s == 'jpeg')) {
            $im = exif_thumbnail($imgfile, $tw, $th, $tt);
            if ($im) {
                if ($size) {
                    $big_enough = $tw >= $size && $th >= $size;
                } else {
                    $big_enough = $tw >= $width && $th >= $height;
                }
                if ($big_enough) {
                    $im = zp_imageFromString($im);
                    if (DEBUG_IMAGE && $im) {
                        debugLog(sprintf(gettext('Using %1$ux%2$u %3$s thumbnail image.'), $tw, $th, image_type_to_mime_type($tt)));
                    }
                } else {
                    $im = false;
                }
            } else {
                $im = false;
            }
        }
        if (!$im) {
            $im = zp_imageGet($imgfile);
        }
        if (!$im) {
            imageError('404 Not Found', sprintf(gettext('Image %s not renderable (imageGet).'), filesystemToInternal($imgfile)), 'err-failimage.png');
        }
        if ($rotate) {
            if (DEBUG_IMAGE) {
                debugLog("cacheImage:rotate->{$rotate}");
            }
            $im = zp_rotateImage($im, $rotate);
            if (!$im) {
                imageError('404 Not Found', sprintf(gettext('Image %s not rotatable.'), filesystemToInternal($imgfile)), 'err-failimage.png');
            }
        }
        $w = zp_imageWidth($im);
        $h = zp_imageHeight($im);
        // Give the sizing dimension to $dim
        $ratio_in = '';
        $ratio_out = '';
        $crop = $crop || $cw != 0 || $ch != 0;
        if (!empty($size)) {
            $dim = $size;
            if ($crop) {
                $dim = $size;
                if (!$ch) {
                    $ch = $size;
                }
                if (!$cw) {
                    $cw = $size;
                }
                $width = $cw;
                $height = $ch;
                $size = false;
            } else {
                $width = $height = false;
            }
        } else {
            if (!empty($width) && !empty($height)) {
                $ratio_in = $h / $w;
                $ratio_out = $height / $width;
                if ($ratio_in > $ratio_out) {
                    // image is taller than desired, $height is the determining factor
                    $thumb = true;
                    $dim = $width;
                    if (!$ch) {
                        $ch = $height;
                    }
                } else {
                    // image is wider than desired, $width is the determining factor
                    $dim = $height;
                    if (!$cw) {
                        $cw = $width;
                    }
                }
            } else {
                if (!empty($width)) {
                    $dim = $width;
                    $size = $height = false;
                } else {
                    if (!empty($height)) {
                        $dim = $height;
                        $size = $width = false;
                    } else {
                        // There's a problem up there somewhere...
                        imageError('404 Not Found', sprintf(gettext('Unknown error processing %s! Please report to the <a href="' . GITHUB . '/issues">developers</a>'), filesystemToInternal($imgfile)), 'err-imagegeneral.png');
                    }
                }
            }
        }
        $sizes = propSizes($size, $width, $height, $w, $h, $thumb, $image_use_side, $dim);
        list($neww, $newh) = $sizes;
        if (DEBUG_IMAGE) {
            debugLog("cacheImage:" . basename($imgfile) . ": \$size={$size}, \$width={$width}, \$height={$height}, \$w={$w}; \$h={$h}; \$cw={$cw}, " . "\$ch={$ch}, \$cx={$cx}, \$cy={$cy}, \$quality={$quality}, \$thumb={$thumb}, \$crop={$crop}, \$newh={$newh}, \$neww={$neww}, \$dim={$dim}, " . "\$ratio_in={$ratio_in}, \$ratio_out={$ratio_out} \$upscale={$upscale} \$rotate={$rotate} \$effects={$effects}");
        }
        if (!$upscale && $newh >= $h && $neww >= $w) {
            // image is the same size or smaller than the request
            $neww = $w;
            $newh = $h;
            $allowscale = false;
            if ($crop) {
                if ($width > $neww) {
                    $width = $neww;
                }
                if ($height > $newh) {
                    $height = $newh;
                }
            }
            if (DEBUG_IMAGE) {
                debugLog("cacheImage:no upscale " . basename($imgfile) . ":  \$newh={$newh}, \$neww={$neww}, \$crop={$crop}, \$thumb={$thumb}, \$rotate={$rotate}, watermark=" . $watermark_use_image);
            }
        }
        $watermark_image = false;
        if ($passedWM) {
            if ($passedWM != NO_WATERMARK) {
                $watermark_image = getWatermarkPath($passedWM);
                if (!file_exists($watermark_image)) {
                    $watermark_image = SERVERPATH . '/' . ZENFOLDER . '/images/imageDefault.png';
                }
            }
        } else {
            if ($allow_watermark) {
                $watermark_image = $watermark_use_image;
                if ($watermark_image) {
                    if ($watermark_image != NO_WATERMARK) {
                        $watermark_image = getWatermarkPath($watermark_image);
                        if (!file_exists($watermark_image)) {
                            $watermark_image = SERVERPATH . '/' . ZENFOLDER . '/images/imageDefault.png';
                        }
                    }
                }
            }
        }
        // Crop the image if requested.
        if ($crop) {
            if ($cw > $ch) {
                $ir = $ch / $cw;
            } else {
                $ir = $cw / $ch;
            }
            if ($size) {
                $neww = $size;
                $newh = $ir * $size;
            } else {
                $neww = $width;
                $newh = $height;
                if ($neww > $newh) {
                    if ($newh === false) {
                        $newh = $ir * $neww;
                    }
                } else {
                    if ($neww === false) {
                        $neww = $ir * $newh;
                    }
                }
            }
            if (is_null($cx) && is_null($cy)) {
                // scale crop to max of image
                // set crop scale factor
                $cf = 1;
                if ($cw) {
                    $cf = min($cf, $cw / $neww);
                }
                if ($ch) {
                    $cf = min($cf, $ch / $newh);
                }
                //	set the image area of the crop (use the most image possible, rule of thirds positioning)
                if (!$cw || $w / $cw * $ch > $h) {
                    $cw = round($h / $ch * $cw * $cf);
                    $ch = round($h * $cf);
                    $cx = round(($w - $cw) / 3);
                } else {
                    $ch = round($w / $cw * $ch * $cf);
                    $cw = round($w * $cf);
                    $cy = round(($h - $ch) / 3);
                }
            } else {
                // custom crop
                if (!$cw || $cw > $w) {
                    $cw = $w;
                }
                if (!$ch || $ch > $h) {
                    $ch = $h;
                }
            }
            // force the crop to be within the image
            if ($cw + $cx > $w) {
                $cx = $w - $cw;
            }
            if ($cx < 0) {
                $cw = $cw + $cx;
                $cx = 0;
            }
            if ($ch + $cy > $h) {
                $cy = $h - $ch;
            }
            if ($cy < 0) {
                $ch = $ch + $cy;
                $cy = 0;
            }
            if (DEBUG_IMAGE) {
                debugLog("cacheImage:crop " . basename($imgfile) . ":\$size={$size}, \$width={$width}, \$height={$height}, \$cw={$cw}, \$ch={$ch}, \$cx={$cx}, \$cy={$cy}, \$quality={$quality}, \$thumb={$thumb}, \$crop={$crop}, \$rotate={$rotate}");
            }
            $newim = zp_createImage($neww, $newh);
            if (!zp_resampleImage($newim, $im, 0, 0, $cx, $cy, $neww, $newh, $cw, $ch)) {
                imageError('404 Not Found', sprintf(gettext('Image %s not renderable (resample).'), filesystemToInternal($imgfile)), 'err-failimage.png');
            }
        } else {
            if ($newh >= $h && $neww >= $w && !$rotate && !$effects && !$watermark_image && (!$upscale || $newh == $h && $neww == $w)) {
                // we can just use the original!
                if (SYMLINK && @symlink($imgfile, $newfile)) {
                    if (DEBUG_IMAGE) {
                        debugLog("cacheImage:symlink original " . basename($imgfile) . ":\$size={$size}, \$width={$width}, \$height={$height}, \$dim={$dim}, \$neww={$neww}; \$newh={$newh}; \$quality={$quality}, \$thumb={$thumb}, \$crop={$crop}, \$rotate={$rotate}; \$allowscale={$allowscale};");
                    }
                    clearstatcache();
                    return true;
                } else {
                    if (@copy($imgfile, $newfile)) {
                        if (DEBUG_IMAGE) {
                            debugLog("cacheImage:copy original " . basename($imgfile) . ":\$size={$size}, \$width={$width}, \$height={$height}, \$dim={$dim}, \$neww={$neww}; \$newh={$newh}; \$quality={$quality}, \$thumb={$thumb}, \$crop={$crop}, \$rotate={$rotate}; \$allowscale={$allowscale};");
                        }
                        clearstatcache();
                        return true;
                    }
                }
            }
            if ($allowscale) {
                $sizes = propSizes($size, $width, $height, $w, $h, $thumb, $image_use_side, $dim);
                list($neww, $newh) = $sizes;
            }
            if (DEBUG_IMAGE) {
                debugLog("cacheImage:no crop " . basename($imgfile) . ":\$size={$size}, \$width={$width}, \$height={$height}, \$dim={$dim}, \$neww={$neww}; \$newh={$newh}; \$quality={$quality}, \$thumb={$thumb}, \$crop={$crop}, \$rotate={$rotate}; \$allowscale={$allowscale};");
            }
            $newim = zp_createImage($neww, $newh);
            if (!zp_resampleImage($newim, $im, 0, 0, 0, 0, $neww, $newh, $w, $h)) {
                imageError('404 Not Found', sprintf(gettext('Image %s not renderable (resample).'), filesystemToInternal($imgfile)), 'err-failimage.png');
            }
            if ($thumb && $sharpenthumbs || !$thumb && $sharpenimages) {
                if (!zp_imageUnsharpMask($newim, getOption('sharpen_amount'), getOption('sharpen_radius'), getOption('sharpen_threshold'))) {
                    imageError('404 Not Found', sprintf(gettext('Image %s not renderable (unsharp).'), filesystemToInternal($imgfile)), 'err-failimage.png');
                }
            }
        }
        $imgEffects = explode(',', $effects);
        if (in_array('gray', $imgEffects)) {
            zp_imageGray($newim);
        }
        if ($watermark_image) {
            $offset_h = getOption('watermark_h_offset') / 100;
            $offset_w = getOption('watermark_w_offset') / 100;
            $percent = getOption('watermark_scale') / 100;
            $watermark = zp_imageGet($watermark_image);
            if (!$watermark) {
                imageError('404 Not Found', sprintf(gettext('Watermark %s not renderable.'), $watermark_image), 'err-failimage.png');
            }
            $watermark_width = zp_imageWidth($watermark);
            $watermark_height = zp_imageHeight($watermark);
            $imw = zp_imageWidth($newim);
            $imh = zp_imageHeight($newim);
            $nw = sqrt($imw * $imh * $percent * ($watermark_width / $watermark_height));
            $nh = $nw * ($watermark_height / $watermark_width);
            $r = sqrt($imw * $imh * $percent / ($watermark_width * $watermark_height));
            if (!getOption('watermark_allow_upscale')) {
                $r = min(1, $r);
            }
            $nw = round($watermark_width * $r);
            $nh = round($watermark_height * $r);
            if ($nw != $watermark_width || $nh != $watermark_height) {
                $watermark = zp_imageResizeAlpha($watermark, $nw, $nh);
                if (!$watermark) {
                    imageError('404 Not Found', sprintf(gettext('Watermark %s not resizeable.'), $watermark_image), 'err-failimage.png');
                }
            }
            // Position Overlay in Bottom Right
            $dest_x = max(0, floor(($imw - $nw) * $offset_w));
            $dest_y = max(0, floor(($imh - $nh) * $offset_h));
            if (DEBUG_IMAGE) {
                debugLog("Watermark:" . basename($imgfile) . ": \$offset_h={$offset_h}, \$offset_w={$offset_w}, \$watermark_height={$watermark_height}, \$watermark_width={$watermark_width}, \$imw={$imw}, \$imh={$imh}, \$percent={$percent}, \$r={$r}, \$nw={$nw}, \$nh={$nh}, \$dest_x={$dest_x}, \$dest_y={$dest_y}");
            }
            if (!zp_copyCanvas($newim, $watermark, $dest_x, $dest_y, 0, 0, $nw, $nh)) {
                imageError('404 Not Found', sprintf(gettext('Image %s not renderable (copycanvas).'), filesystemToInternal($imgfile)), 'err-failimage.png');
            }
            zp_imageKill($watermark);
        }
        // Create the cached file (with lots of compatibility)...
        @chmod($newfile, 0777);
        if (zp_imageOutput($newim, getSuffix($newfile), $newfile, $quality)) {
            //	successful save of cached image
            if (getOption('ImbedIPTC') && getSuffix($newfilename) == 'jpg' && GRAPHICS_LIBRARY != 'Imagick') {
                // the imbed function works only with JPEG images
                global $_zp_images_classes;
                //	because we are doing the require in a function!
                require_once dirname(__FILE__) . '/functions.php';
                //	it is ok to increase memory footprint now since the image processing is complete
                $iptc = array('1#090' => chr(0x1b) . chr(0x25) . chr(0x47), '2#115' => $_zp_gallery->getTitle());
                $iptc_data = zp_imageIPTC($imgfile);
                if ($iptc_data) {
                    $iptc_data = iptcparse($iptc_data);
                    if ($iptc_data) {
                        $iptc = array_merge($iptc_data, $iptc);
                    }
                }
                $imgfile = str_replace(ALBUM_FOLDER_SERVERPATH, '', $imgfile);
                $imagename = basename($imgfile);
                $albumname = dirname($imgfile);
                $image = newImage(newAlbum($albumname), $imagename);
                $copyright = $image->getCopyright();
                if (empty($copyright)) {
                    $copyright = getOption('default_copyright');
                }
                if (!empty($copyright)) {
                    $iptc['2#116'] = $copyright;
                }
                $credit = $image->getCredit();
                if (!empty($credit)) {
                    $iptc['2#110'] = $credit;
                }
                $iptc_result = '';
                foreach ($iptc as $tag => $string) {
                    $tag_parts = explode('#', $tag);
                    if (is_array($string)) {
                        foreach ($string as $element) {
                            $iptc_result .= iptc_make_tag($tag_parts[0], $tag_parts[1], $element);
                        }
                    } else {
                        $iptc_result .= iptc_make_tag($tag_parts[0], $tag_parts[1], $string);
                    }
                }
                $content = iptcembed($iptc_result, $newfile);
                $fw = fopen($newfile, 'w');
                fwrite($fw, $content);
                fclose($fw);
                clearstatcache();
            }
            @chmod($newfile, FILE_MOD);
            if (DEBUG_IMAGE) {
                debugLog('Finished:' . basename($imgfile));
            }
        } else {
            if (DEBUG_IMAGE) {
                debugLog('cacheImage: failed to create ' . $newfile);
            }
            imageError('404 Not Found', sprintf(gettext('cacheImage: failed to create %s'), $newfile), 'err-failimage.png');
        }
        @chmod($newfile, FILE_MOD);
        zp_imageKill($newim);
        zp_imageKill($im);
    } catch (Exception $e) {
        debugLog('cacheImage(' . $newfilename . ') exception: ' . $e->getMessage());
        imageError('404 Not Found', sprintf(gettext('cacheImage(%1$s) exception: %2$s'), $newfilename, $e->getMessage()), 'err-failimage.png');
        return false;
    }
    clearstatcache();
    return true;
}