예제 #1
0
 /**
  * 
  * convert an image to a desired size while maintaining its aspect ratio
  * if the image is of type BMP it will be converted into JPEG
  * NOTE: images are only scaled down, so a small image wont be changed (apart for the JPEG quality)
  * the function returns the $target_file after changing its extension
  * @param unknown_type $source_file - Sourct file path
  * @param unknown_type $target_file - Target file path (after converting)
  * @param unknown_type $width - Requested width in pixels
  * @param unknown_type $height - Requested height in pixels
  * @param unknown_type $crop_type - Type of crop to be used [1-4] :
  * 		self::CROP_TYPE_ORIGINAL_ASPECT_RATIO: 	Resize according to the given dimensions while maintaining the original aspect ratio.
  * 		self::CROP_TYPE_WITHIN_BG_COLOR:  		Place the image within the given dimensions and fill the remaining spaces using the given background color.
  * 		self::CROP_TYPE_EXACT_SIZE:				Crop according to the given dimensions while maintaining the original aspect ratio.
  * 												The resulting image may be cover only part of the original image.
  * 		self::CROP_TYPE_UPPER: 					Crops the image so that only the upper part of the image remains.
  * @param unknown_type $bgcolor - backround color (6 hex digits web colorcode)
  * @param unknown_type $force_jpeg - Force the source image file to convert into a Jpeg file 
  * @param unknown_type $quality - Jpeg quality for output [0-100]
  * @param unknown_type $src_x - 1st part of a rectangle to take from original picture (starting from vertical picsal {value} to right end of picture)
  * @param unknown_type $src_y - 2nd part of a rectangle to take from original picture (starting from horizonal picasl {value} downto down end of picture)
  * @param unknown_type $src_w - 3rd part of a rectangle to take from original picture (starting from picsal left end of picture to vertical pixel {value})
  * @param unknown_type $src_h - 4rd part of a rectangle to take from original picture (starting from up end of picture downto horizonal pixesl {value})
  * @return path to targetFile or null if the $source_file is not an image file
  */
 public static function convertImage($source_file, $target_file, $width = self::DEFAULT_THUMBNAIL_WIDTH, $height = self::DEFAULT_THUMBNAIL_HEIGHT, $crop_type = self::CROP_TYPE_ORIGINAL_ASPECT_RATIO, $bgcolor = 0xffffff, $force_jpeg = false, $quality = 0, $src_x = 0, $src_y = 0, $src_w = 0, $src_h = 0, $density = 0, $stripProfiles = false, $thumbParams = null, $format = null)
 {
     if (is_null($thumbParams) || !$thumbParams instanceof kThumbnailParameters) {
         $thumbParams = new kThumbnailParameters();
     }
     if (is_string($bgcolor) && strpos($bgcolor, '0x') === false) {
         $bgcolor = hexdec('0x' . $bgcolor);
     }
     // check if the source file is not an image file
     if (!file_exists($source_file) || filesize($source_file) === 0 || getimagesize($source_file) === false) {
         KalturaLog::log("convertImage - failed to get image size [{$source_file}] while creating [{$target_file}]");
         return null;
     }
     // change target file extension if needed
     list($source_width, $source_height, $type, $attr) = getimagesize($source_file);
     if ($type == IMAGETYPE_BMP) {
         // convert bmp to jpeg
         $type = IMAGETYPE_JPEG;
     }
     if ($force_jpeg) {
         $ext = self::imageExtByType($type);
         if ($thumbParams->getSupportAnimatedThumbnail() && $ext == "gif") {
             $target_file = kFile::replaceExt($target_file, "gif");
         } else {
             $target_file = kFile::replaceExt($target_file, "jpg");
             $type = IMAGETYPE_JPEG;
         }
     } else {
         $target_file = kFile::replaceExt($target_file, self::imageExtByType($type));
     }
     if (!is_null($format)) {
         $target_file = kFile::replaceExt($target_file, $format);
     }
     // do convertion
     $status = null;
     $imageCropper = new KImageMagickCropper($source_file, $target_file, kConf::get('bin_path_imagemagick'));
     $status = $imageCropper->crop($quality, $crop_type, $width, $height, $src_x, $src_y, $src_w, $src_h, null, null, $bgcolor, $density, null, $stripProfiles);
     if (!$status) {
         return null;
     }
     return $target_file;
 }
예제 #2
0
 public static function resizeEntryImage(entry $entry, $version, $width, $height, $type, $bgcolor = "ffffff", $crop_provider = null, $quality = 0, $src_x = 0, $src_y = 0, $src_w = 0, $src_h = 0, $vid_sec = -1, $vid_slice = 0, $vid_slices = -1, $orig_image_path = null, $density = 0, $stripProfiles = false, $thumbParams = null, $format = null)
 {
     if (is_null($thumbParams) || !$thumbParams instanceof kThumbnailParameters) {
         $thumbParams = new kThumbnailParameters();
     }
     $contentPath = myContentStorage::getFSContentRootPath();
     $entry_status = $entry->getStatus();
     $thumbName = $entry->getId() . "_{$width}_{$height}_{$type}_{$crop_provider}_{$bgcolor}_{$quality}_{$src_x}_{$src_y}_{$src_w}_{$src_h}_{$vid_sec}_{$vid_slice}_{$vid_slices}_{$entry_status}";
     if ($orig_image_path) {
         $thumbName .= '_oip_' . basename($orig_image_path);
     }
     if ($density) {
         $thumbName .= "_dns_{$density}";
     }
     if ($stripProfiles) {
         $thumbName .= "_stp_{$stripProfiles}";
     }
     $entryThumbFilename = $entry->getThumbnail() ? $entry->getThumbnail() : "0.jpg";
     if ($entry->getStatus() != entryStatus::READY || @$entryThumbFilename[0] == '&') {
         $thumbName .= "_NOCACHE_";
     }
     // we remove the & from the template thumb otherwise getGeneralEntityPath will drop $tempThumbName from the final path
     $entryThumbFilename = str_replace("&", "", $entryThumbFilename);
     //create final path for thumbnail created
     $finalBasePath = myContentStorage::getGeneralEntityPath("entry/tempthumb", $entry->getIntId(), $thumbName, $entryThumbFilename, $version);
     $finalThumbPath = $contentPath . $finalBasePath;
     //Add unique id to the proccesing file path to avoid file being overwritten when several identical (with same parameters) calls are made before the final thumbnail is created
     $thumbName .= "_" . uniqid() . "_";
     //create path for processing thumbnail request
     $processingBasePath = myContentStorage::getGeneralEntityPath("entry/tempthumb", $entry->getIntId(), $thumbName, $entryThumbFilename, $version);
     $processingThumbPath = $contentPath . $processingBasePath;
     if (!is_null($format)) {
         $finalThumbPath = kFile::replaceExt($finalThumbPath, $format);
         $processingThumbPath = kFile::replaceExt($processingThumbPath, $format);
     }
     if (file_exists($finalThumbPath) && @filesize($finalThumbPath)) {
         header("X-Kaltura:cached-thumb-exists," . md5($finalThumbPath));
         return $finalThumbPath;
     }
     if ($orig_image_path === null || !file_exists($orig_image_path)) {
         $orig_image_path = self::getLocalImageFilePathByEntry($entry, $version);
     }
     // remark added so ffmpeg will try to load the thumbnail from the original source
     if ($entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_IMAGE && !file_exists($orig_image_path)) {
         throw new kFileSyncException('no ready filesync on current DC', kFileSyncException::FILE_DOES_NOT_EXIST_ON_CURRENT_DC);
     }
     // check a request for animated thumbs without a concrete vid_slice
     // in which case we'll create all the frames as one wide image
     $multi = $vid_slice == -1 && $vid_slices != -1;
     $count = $multi ? $vid_slices : 1;
     $im = null;
     if ($multi) {
         $vid_slice = 0;
     }
     while ($count--) {
         if ($entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_VIDEO && ($vid_sec != -1 || $vid_slices != -1) || !file_exists($orig_image_path)) {
             if ($vid_sec != -1) {
                 $calc_vid_sec = min($vid_sec, floor($entry->getLengthInMsecs() / 1000));
             } else {
                 if ($vid_slices != -1) {
                     $calc_vid_sec = floor($entry->getLengthInMsecs() / $vid_slices * min($vid_slice, $vid_slices) / 1000);
                 } else {
                     if ($entry->getStatus() != entryStatus::READY && $entry->getLengthInMsecs() == 0) {
                         $calc_vid_sec = $entry->getPartner() && $entry->getPartner()->getDefThumbOffset() ? $entry->getPartner()->getDefThumbOffset() : 3;
                     } else {
                         $calc_vid_sec = $entry->getBestThumbOffset();
                     }
                 }
             }
             $capturedThumbName = $entry->getId() . "_sec_{$calc_vid_sec}";
             $capturedThumbPath = $contentPath . myContentStorage::getGeneralEntityPath("entry/tempthumb", $entry->getIntId(), $capturedThumbName, $entry->getThumbnail(), $version);
             $orig_image_path = $capturedThumbPath . "temp_1.jpg";
             // if we already captured the frame at that second, dont recapture, just use the existing file
             if (!file_exists($orig_image_path)) {
                 // limit creation of more than XX ffmpeg image extraction processes
                 if (kConf::hasParam("resize_thumb_max_processes_ffmpeg") && trim(exec("ps -e -ocmd|awk '{print \$1}'|grep -c " . kConf::get("bin_path_ffmpeg"))) > kConf::get("resize_thumb_max_processes_ffmpeg")) {
                     KExternalErrors::dieError(KExternalErrors::TOO_MANY_PROCESSES);
                 }
                 // creating the thumbnail is a very heavy operation
                 // prevent calling it in parallel for the same thubmnail for 5 minutes
                 $cache = new myCache("thumb-processing", 5 * 60);
                 // 5 minutes
                 $processing = $cache->get($orig_image_path);
                 if ($processing) {
                     KExternalErrors::dieError(KExternalErrors::PROCESSING_CAPTURE_THUMBNAIL);
                 }
                 $cache->put($orig_image_path, true);
                 $flavorAsset = assetPeer::retrieveHighestBitrateByEntryId($entry->getId(), flavorParams::TAG_THUMBSOURCE);
                 if (is_null($flavorAsset)) {
                     $flavorAsset = assetPeer::retrieveOriginalReadyByEntryId($entry->getId());
                     if ($flavorAsset) {
                         $flavorSyncKey = $flavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET);
                         list($fileSync, $local) = kFileSyncUtils::getReadyFileSyncForKey($flavorSyncKey, false, false);
                         if (!$fileSync) {
                             $flavorAsset = null;
                         }
                     }
                     if (is_null($flavorAsset) || !($flavorAsset->hasTag(flavorParams::TAG_MBR) || $flavorAsset->hasTag(flavorParams::TAG_WEB))) {
                         // try the best playable
                         $flavorAsset = assetPeer::retrieveHighestBitrateByEntryId($entry->getId(), null, flavorParams::TAG_SAVE_SOURCE);
                     }
                     if (is_null($flavorAsset)) {
                         // if no READY ORIGINAL entry is available, try to retrieve a non-READY ORIGINAL entry
                         $flavorAsset = assetPeer::retrieveOriginalByEntryId($entry->getId());
                     }
                 }
                 if (is_null($flavorAsset)) {
                     // if no READY ORIGINAL entry is available, try to retrieve a non-READY ORIGINAL entry
                     $flavorAsset = assetPeer::retrieveOriginalByEntryId($entry->getId());
                 }
                 if (is_null($flavorAsset)) {
                     KExternalErrors::dieError(KExternalErrors::FLAVOR_NOT_FOUND);
                 }
                 $flavorSyncKey = $flavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET);
                 $entry_data_path = kFileSyncUtils::getReadyLocalFilePathForKey($flavorSyncKey);
                 if (!$entry_data_path) {
                     // since this is not really being processed on this server, and will probably cause redirect in thumbnailAction
                     // remove from cache so later requests will still get redirected and will not fail on PROCESSING_CAPTURE_THUMBNAIL
                     $cache->remove($orig_image_path);
                     throw new kFileSyncException('no ready filesync on current DC', kFileSyncException::FILE_DOES_NOT_EXIST_ON_CURRENT_DC);
                 }
                 // close db connections as we won't be requiring the database anymore and capturing a thumbnail may take a long time
                 kFile::closeDbConnections();
                 myFileConverter::autoCaptureFrame($entry_data_path, $capturedThumbPath . "temp_", $calc_vid_sec, -1, -1);
                 $cache->remove($orig_image_path);
             }
         }
         // close db connections as we won't be requiring the database anymore and image manipulation may take a long time
         kFile::closeDbConnections();
         // limit creation of more than XX Imagemagick processes
         if (kConf::hasParam("resize_thumb_max_processes_imagemagick") && trim(exec("ps -e -ocmd|awk '{print \$1}'|grep -c " . kConf::get("bin_path_imagemagick"))) > kConf::get("resize_thumb_max_processes_imagemagick")) {
             KExternalErrors::dieError(KExternalErrors::TOO_MANY_PROCESSES);
         }
         // resizing (and editing)) an image file that failes results in a long server waiting time
         // prevent this waiting time (of future requests) in case the resizeing failes
         $cache = new myCache("thumb-processing-resize", 5 * 60);
         // 5 minutes
         $processing = $cache->get($orig_image_path);
         if ($processing) {
             KExternalErrors::dieError(KExternalErrors::PROCESSING_CAPTURE_THUMBNAIL);
         }
         kFile::fullMkdir($processingThumbPath);
         if ($crop_provider) {
             $convertedImagePath = myFileConverter::convertImageUsingCropProvider($orig_image_path, $processingThumbPath, $width, $height, $type, $crop_provider, $bgcolor, true, $quality, $src_x, $src_y, $src_w, $src_h, $density, $stripProfiles);
         } else {
             if (!file_exists($orig_image_path) || !filesize($orig_image_path)) {
                 KExternalErrors::dieError(KExternalErrors::IMAGE_RESIZE_FAILED);
             }
             $imageSizeArray = getimagesize($orig_image_path);
             if ($thumbParams->getSupportAnimatedThumbnail() && is_array($imageSizeArray) && $imageSizeArray[2] === IMAGETYPE_GIF) {
                 $processingThumbPath = kFile::replaceExt($processingThumbPath, "gif");
                 $finalThumbPath = kFile::replaceExt($finalThumbPath, "gif");
             }
             $convertedImagePath = myFileConverter::convertImage($orig_image_path, $processingThumbPath, $width, $height, $type, $bgcolor, true, $quality, $src_x, $src_y, $src_w, $src_h, $density, $stripProfiles, $thumbParams, $format);
         }
         // die if resize operation failed and add failed resizing to cache
         if ($convertedImagePath === null || !@filesize($convertedImagePath)) {
             $cache->put($orig_image_path, true);
             KExternalErrors::dieError(KExternalErrors::IMAGE_RESIZE_FAILED);
         }
         // if resizing secceded remove from cache of failed resizing
         if ($cache->get($orig_image_path)) {
             $cache->remove($orig_image_path, true);
         }
         if ($multi) {
             list($w, $h, $type, $attr, $srcIm) = myFileConverter::createImageByFile($processingThumbPath);
             if (!$im) {
                 $im = imagecreatetruecolor($w * $vid_slices, $h);
             }
             imagecopy($im, $srcIm, $w * $vid_slice, 0, 0, 0, $w, $h);
             imagedestroy($srcIm);
             ++$vid_slice;
         }
     }
     if ($multi) {
         imagejpeg($im, $processingThumbPath);
         imagedestroy($im);
     }
     kFile::fullMkdir($finalThumbPath);
     kFile::moveFile($processingThumbPath, $finalThumbPath);
     return $finalThumbPath;
 }
    public function operate(kOperator $operator = null, $inFilePath, $configFilePath = null)
    {
        KalturaLog::debug("document : operator [" . print_r($operator, true) . "] inFilePath [{$inFilePath}]");
        if ($configFilePath) {
            $configFilePath = realpath($configFilePath);
        }
        // bypassing PDF Creator for source PDF files
        $inputExtension = strtolower(pathinfo($inFilePath, PATHINFO_EXTENSION));
        if ($inputExtension == 'pdf' && !$this->data->flavorParamsOutput->readonly) {
            KalturaLog::notice('Bypassing PDF Creator for source PDF files');
            if (!@copy($inFilePath, $this->outFilePath)) {
                $error = '';
                if (function_exists('error_get_last')) {
                    $error = error_get_last();
                }
                throw new KOperationEngineException('Cannot copy PDF file [' . $this->inFilePath . '] to [' . $this->outFilePath . '] - [' . $error . ']');
            } else {
                // PDF input file copied as is to output file
                return true;
            }
        }
        // renaming with unique name to allow conversion 2 conversions of same input file to be done together (PDF+SWF)
        $tmpUniqInFilePath = dirname($inFilePath) . '/' . uniqid() . '_' . basename($inFilePath);
        $realInFilePath = '';
        $uniqueName = false;
        if (@copy($inFilePath, $tmpUniqInFilePath)) {
            $realInFilePath = realpath($tmpUniqInFilePath);
            $uniqueName = true;
        } else {
            KalturaLog::notice('Could not rename input file [' . $inFilePath . '] with a unique name [' . $tmpUniqInFilePath . ']');
            $realInFilePath = realpath($inFilePath);
        }
        $filePrefix = file_get_contents($realInFilePath, false, null, 0, strlen(self::OLD_OFFICE_SIGNATURE));
        $path_info = pathinfo($realInFilePath);
        $ext = $path_info['extension'];
        $newOfficeExtensions = array('pptx', 'docx', 'xlsx');
        $ext = strtolower($ext);
        //checks if $realInFilePath is an old office document with a new extension ('pptx|docx|xlsx')
        //if $realInFilePath is not the fileSync itself ($uniqueName = true) , rename the file by removing the 'x' from the extension.
        if ($uniqueName && in_array($ext, $newOfficeExtensions) && $filePrefix == self::OLD_OFFICE_SIGNATURE) {
            $RealInFilePathWithoutX = substr($realInFilePath, 0, -1);
            if (rename($realInFilePath, $RealInFilePathWithoutX)) {
                KalturaLog::notice("renamed file [{$realInFilePath}] to [{$RealInFilePathWithoutX}]");
                $realInFilePath = $RealInFilePathWithoutX;
            }
        }
        $finalOutputPath = $this->outFilePath;
        if ($inputExtension == 'pdf' && $this->data->flavorParamsOutput->readonly == true) {
            $tmpFile = $this->outFilePath . '.pdf';
        } else {
            $tmpFile = kFile::replaceExt(basename($realInFilePath), 'pdf');
            $tmpFile = dirname($this->outFilePath) . '/' . $tmpFile;
        }
        $this->outFilePath = $tmpFile;
        // Create popups log file
        $killPopupsPath = $this->getKillPopupsPath();
        if (file_exists($killPopupsPath)) {
            unlink($killPopupsPath);
        }
        // Test file type
        $errorMsg = $this->checkFileType($realInFilePath, $this->SUPPORTED_FILE_TYPES);
        if (!is_null($errorMsg)) {
            $this->data->engineMessage = $errorMsg;
        }
        parent::operate($operator, $realInFilePath, $configFilePath);
        $this->outFilePath = $finalOutputPath;
        if ($uniqueName) {
            @unlink($tmpUniqInFilePath);
        }
        $sleepTimes = KBatchBase::$taskConfig->fileExistReties;
        if (!$sleepTimes) {
            $sleepTimes = self::DEFAULT_SLEEP_TIMES;
        }
        $sleepSeconds = KBatchBase::$taskConfig->fileExistInterval;
        if (!$sleepSeconds) {
            $sleepSeconds = self::DEFAULT_SLEEP_SECONDS;
        }
        // sleeping while file not ready, since PDFCreator exists a bit before the file is actually ready
        while (!file_exists(realpath($tmpFile)) && $sleepTimes > 0) {
            sleep($sleepSeconds);
            $sleepTimes--;
            clearstatcache();
        }
        // Read popup log file
        if (file_exists($killPopupsPath)) {
            $data = file_get_contents($killPopupsPath);
            $data = trim($data);
            if (!empty($data)) {
                KalturaLog::notice("Convert popups warnings - " . $data);
                if (is_null($this->message)) {
                    $this->message = $data;
                } else {
                    $this->message .= $data;
                }
            }
            unlink($killPopupsPath);
        }
        if (!file_exists(realpath($tmpFile))) {
            throw new kTemporaryException('Temp PDF Creator file not found [' . $tmpFile . '] output file [' . $this->outFilePath . '] 
					Convert Engine message [' . $this->message . ']');
        } else {
            KalturaLog::notice('document temp  found [' . $tmpFile . '] output file [' . $this->outFilePath . ']');
        }
        $this->validateOutput($inFilePath, realpath($tmpFile));
        $fileUnlockRetries = KBatchBase::$taskConfig->params->fileUnlockRetries;
        if (!$fileUnlockRetries) {
            $fileUnlockRetries = self::DEFAULT_FILE_UNLOCK_RETRIES;
        }
        $fileUnlockInterval = KBatchBase::$taskConfig->params->fileUnlockInterval;
        if (!$fileUnlockInterval) {
            $fileUnlockInterval = self::DEFAULT_FILE_UNLOCK_INTERVAL;
        }
        $tmpFile = realpath($tmpFile);
        while (!rename($tmpFile, $this->outFilePath) && $fileUnlockRetries > 0) {
            sleep($fileUnlockInterval);
            $fileUnlockRetries--;
            clearstatcache();
        }
        if (!file_exists($this->outFilePath)) {
            $error = '';
            if (function_exists('error_get_last')) {
                $error = error_get_last();
            }
            throw new KOperationEngineException('Cannot rename file [' . $tmpFile . '] to [' . $this->outFilePath . '] - [' . $error . ']');
        }
        return true;
    }
 public function operate(kOperator $operator = null, $inFilePath, $configFilePath = null)
 {
     KalturaLog::debug("document : operator [" . print_r($operator, true) . "] inFilePath [{$inFilePath}]");
     if ($configFilePath) {
         $configFilePath = realpath($configFilePath);
     }
     // bypassing PDF Creator for source PDF files
     $inputExtension = strtolower(pathinfo($inFilePath, PATHINFO_EXTENSION));
     if ($inputExtension == 'pdf' && !$this->flavorParamsOutput->readonly) {
         KalturaLog::notice('Bypassing PDF Creator for source PDF files');
         if (!@copy($inFilePath, $this->outFilePath)) {
             $error = '';
             if (function_exists('error_get_last')) {
                 $error = error_get_last();
             }
             throw new KOperationEngineException('Cannot copy PDF file [' . $this->inFilePath . '] to [' . $this->outFilePath . '] - [' . $error . ']');
         } else {
             // PDF input file copied as is to output file
             return;
         }
     }
     // renaming with unique name to allow conversion 2 conversions of same input file to be done together (PDF+SWF)
     $tmpUniqInFilePath = dirname($inFilePath) . '/' . uniqid() . '_' . basename($inFilePath);
     $realInFilePath = '';
     $uniqueName = false;
     if (@copy($inFilePath, $tmpUniqInFilePath)) {
         $realInFilePath = realpath($tmpUniqInFilePath);
         $uniqueName = true;
     } else {
         KalturaLog::notice('Could not rename input file [' . $inFilePath . '] with a unique name [' . $tmpUniqInFilePath . ']');
         $realInFilePath = realpath($inFilePath);
     }
     parent::operate($operator, $realInFilePath, $configFilePath);
     if ($uniqueName) {
         @unlink($tmpUniqInFilePath);
     }
     //TODO: RENAME - will not be needed once PDFCreator can work with a configurations file
     if ($inputExtension == 'pdf' && $this->flavorParamsOutput->readonly == true) {
         $tmpFile = $this->outFilePath . '.pdf';
     } else {
         $tmpFile = kFile::replaceExt(basename($realInFilePath), 'pdf');
         $tmpFile = dirname($this->outFilePath) . '/' . $tmpFile;
     }
     // sleeping while file not ready, since PDFCreator exists a bit before the file is actually ready
     $sleepTimes = 50;
     $sleepSeconds = 3;
     while (!file_exists(realpath($tmpFile)) && $sleepTimes > 0) {
         sleep($sleepSeconds);
         $sleepTimes--;
         clearstatcache();
     }
     if (!file_exists(realpath($tmpFile))) {
         throw new kTemporaryException('Temp PDF Creator file not found [' . $tmpFile . '] output file [' . $this->outFilePath . ']');
     } else {
         KalturaLog::notice('document temp  found [' . $tmpFile . '] output file [' . $this->outFilePath . ']');
     }
     //TODO: RENAME - will not be needed once PDFCreator can work with a configurations file
     $tmpFile = realpath($tmpFile);
     while (!rename($tmpFile, $this->outFilePath) && $sleepTimes > 0) {
         sleep($sleepSeconds);
         $sleepTimes--;
         clearstatcache();
     }
     if (!file_exists($this->outFilePath)) {
         $error = '';
         if (function_exists('error_get_last')) {
             $error = error_get_last();
         }
         throw new KOperationEngineException('Cannot rename file [' . $tmpFile . '] to [' . $this->outFilePath . '] - [' . $error . ']');
     }
 }
 public static function resizeEntryImage(entry $entry, $version, $width, $height, $type, $bgcolor = "ffffff", $crop_provider = null, $quality = 0, $src_x = 0, $src_y = 0, $src_w = 0, $src_h = 0, $vid_sec = -1, $vid_slice = 0, $vid_slices = -1, $orig_image_path = null, $density = 0, $stripProfiles = false, $thumbParams = null)
 {
     if (is_null($thumbParams) || !$thumbParams instanceof kThumbnailParameters) {
         $thumbParams = new kThumbnailParameters();
     }
     $contentPath = myContentStorage::getFSContentRootPath();
     $entry_status = $entry->getStatus();
     $tempThumbName = $entry->getId() . "_{$width}_{$height}_{$type}_{$crop_provider}_{$bgcolor}_{$quality}_{$src_x}_{$src_y}_{$src_w}_{$src_h}_{$vid_sec}_{$vid_slice}_{$vid_slices}_{$entry_status}";
     if ($orig_image_path) {
         $tempThumbName .= '_oip_' . basename($orig_image_path);
     }
     if ($density) {
         $tempThumbName .= "_dns_{$density}";
     }
     if ($stripProfiles) {
         $tempThumbName .= "_stp_{$stripProfiles}";
     }
     $entryThumbFilename = $entry->getThumbnail() ? $entry->getThumbnail() : "0.jpg";
     if ($entry->getStatus() != entryStatus::READY || @$entryThumbFilename[0] == '&') {
         $tempThumbName .= "_NOCACHE_";
     }
     // we remove the & from the template thumb otherwise getGeneralEntityPath will drop $tempThumbName from the final path
     $entryThumbFilename = str_replace("&", "", $entryThumbFilename);
     $basePath = myContentStorage::getGeneralEntityPath("entry/tempthumb", $entry->getIntId(), $tempThumbName, $entryThumbFilename, $version);
     $tempThumbPath = $contentPath . $basePath;
     if (file_exists($tempThumbPath) && @filesize($tempThumbPath)) {
         header("X-Kaltura:cached-thumb-exists," . md5($tempThumbPath));
         return $tempThumbPath;
     }
     if ($orig_image_path === null || !file_exists($orig_image_path)) {
         $sub_type = $entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_IMAGE ? entry::FILE_SYNC_ENTRY_SUB_TYPE_DATA : entry::FILE_SYNC_ENTRY_SUB_TYPE_THUMB;
         $orig_image_key = $entry->getSyncKey($sub_type, $version);
         $orig_image_path = kFileSyncUtils::getReadyLocalFilePathForKey($orig_image_key);
     }
     // remark added so ffmpeg will try to load the thumbnail from the original source
     if ($entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_IMAGE && !file_exists($orig_image_path)) {
         throw new kFileSyncException('no ready filesync on current DC', kFileSyncException::FILE_DOES_NOT_EXIST_ON_CURRENT_DC);
     }
     // check a request for animated thumbs without a concrete vid_slice
     // in which case we'll create all the frames as one wide image
     $multi = $vid_slice == -1 && $vid_slices != -1;
     $count = $multi ? $vid_slices : 1;
     $im = null;
     if ($multi) {
         $vid_slice = 0;
     }
     while ($count--) {
         if ($entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_VIDEO && ($vid_sec != -1 || $vid_slices != -1) || !file_exists($orig_image_path)) {
             if ($vid_sec != -1) {
                 $calc_vid_sec = min($vid_sec, floor($entry->getLengthInMsecs() / 1000));
             } else {
                 if ($vid_slices != -1) {
                     $calc_vid_sec = floor($entry->getLengthInMsecs() / $vid_slices * min($vid_slice, $vid_slices) / 1000);
                 } else {
                     if ($entry->getStatus() != entryStatus::READY && $entry->getLengthInMsecs() == 0) {
                         $calc_vid_sec = $entry->getPartner() && $entry->getPartner()->getDefThumbOffset() ? $entry->getPartner()->getDefThumbOffset() : 3;
                     } else {
                         $calc_vid_sec = $entry->getBestThumbOffset();
                     }
                 }
             }
             $capturedThumbName = $entry->getId() . "_sec_{$calc_vid_sec}";
             $capturedThumbPath = $contentPath . myContentStorage::getGeneralEntityPath("entry/tempthumb", $entry->getIntId(), $capturedThumbName, $entry->getThumbnail(), $version);
             $orig_image_path = $capturedThumbPath . "temp_1.jpg";
             // if we already captured the frame at that second, dont recapture, just use the existing file
             if (!file_exists($orig_image_path)) {
                 // creating the thumbnail is a very heavy operation
                 // prevent calling it in parallel for the same thubmnail for 5 minutes
                 $cache = new myCache("thumb-processing", 5 * 60);
                 // 5 minutes
                 $processing = $cache->get($orig_image_path);
                 if ($processing) {
                     KExternalErrors::dieError(KExternalErrors::PROCESSING_CAPTURE_THUMBNAIL);
                 }
                 $cache->put($orig_image_path, true);
                 $flavorAsset = assetPeer::retrieveHighestBitrateByEntryId($entry->getId(), flavorParams::TAG_THUMBSOURCE);
                 if (is_null($flavorAsset)) {
                     $flavorAsset = assetPeer::retrieveOriginalReadyByEntryId($entry->getId());
                     if (is_null($flavorAsset) || !($flavorAsset->hasTag(flavorParams::TAG_MBR) || $flavorAsset->hasTag(flavorParams::TAG_WEB))) {
                         // try the best playable
                         $flavorAsset = assetPeer::retrieveHighestBitrateByEntryId($entry->getId());
                     }
                     if (is_null($flavorAsset)) {
                         // if no READY ORIGINAL entry is available, try to retrieve a non-READY ORIGINAL entry
                         $flavorAsset = assetPeer::retrieveOriginalByEntryId($entry->getId());
                     }
                 }
                 if (is_null($flavorAsset)) {
                     // if no READY ORIGINAL entry is available, try to retrieve a non-READY ORIGINAL entry
                     $flavorAsset = assetPeer::retrieveOriginalByEntryId($entry->getId());
                 }
                 if (is_null($flavorAsset)) {
                     KExternalErrors::dieError(KExternalErrors::FLAVOR_NOT_FOUND);
                 }
                 $flavorSyncKey = $flavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET);
                 $entry_data_path = kFileSyncUtils::getReadyLocalFilePathForKey($flavorSyncKey);
                 $entry_data_wams_asset_id = kFileSyncUtils::getWamsAssetIdForKey($flavorSyncKey);
                 if (!$entry_data_path) {
                     // since this is not really being processed on this server, and will probably cause redirect in thumbnailAction
                     // remove from cache so later requests will still get redirected and will not fail on PROCESSING_CAPTURE_THUMBNAIL
                     $cache->remove($orig_image_path);
                     throw new kFileSyncException('no ready filesync on current DC', kFileSyncException::FILE_DOES_NOT_EXIST_ON_CURRENT_DC);
                 }
                 if (!empty($entry_data_wams_asset_id)) {
                     $thumbMaker = new KWAMSThumbnailMaker($entry_data_wams_asset_id, $orig_image_path);
                     if (!$thumbMaker->createThumbnail($calc_vid_sec, -1, -1)) {
                         if (!$thumbMaker->createThumbnail(0, -1, -1)) {
                             $kalturaPath = realpath(dirname(__FILE__) . '/../../../../');
                             copy($kalturaPath . '/res/broken_thumb.jpg', $orig_image_path);
                         }
                     }
                 } else {
                     myFileConverter::autoCaptureFrame($entry_data_path, $capturedThumbPath . "temp_", $calc_vid_sec, -1, -1);
                 }
                 $cache->remove($orig_image_path);
             }
         }
         // resizing (and editing)) an image file that failes results in a long server waiting time
         // prevent this waiting time (of future requests) in case the resizeing failes
         $cache = new myCache("thumb-processing-resize", 5 * 60);
         // 5 minutes
         $processing = $cache->get($orig_image_path);
         if ($processing) {
             KExternalErrors::dieError(KExternalErrors::PROCESSING_CAPTURE_THUMBNAIL);
         }
         kFile::fullMkdir($tempThumbPath);
         if ($crop_provider) {
             $convertedImagePath = myFileConverter::convertImageUsingCropProvider($orig_image_path, $tempThumbPath, $width, $height, $type, $crop_provider, $bgcolor, true, $quality, $src_x, $src_y, $src_w, $src_h, $density, $stripProfiles);
         } else {
             if (!file_exists($orig_image_path)) {
                 KExternalErrors::dieError(KExternalErrors::IMAGE_RESIZE_FAILED);
             }
             $imageSizeArray = getimagesize($orig_image_path);
             if ($thumbParams->getSupportAnimatedThumbnail() && is_array($imageSizeArray) && $imageSizeArray[2] === IMAGETYPE_GIF) {
                 $tempThumbPath = kFile::replaceExt($tempThumbPath, "gif");
             }
             $convertedImagePath = myFileConverter::convertImage($orig_image_path, $tempThumbPath, $width, $height, $type, $bgcolor, true, $quality, $src_x, $src_y, $src_w, $src_h, $density, $stripProfiles, $thumbParams);
         }
         // die if resize operation failed and add failed resizing to cache
         if ($convertedImagePath === null || !@filesize($convertedImagePath)) {
             $cache->put($orig_image_path, true);
             KExternalErrors::dieError(KExternalErrors::IMAGE_RESIZE_FAILED);
         }
         // if resizing secceded remove from cache of failed resizing
         if ($cache->get($orig_image_path)) {
             $cache->remove($orig_image_path, true);
         }
         if ($multi) {
             list($w, $h, $type, $attr, $srcIm) = myFileConverter::createImageByFile($tempThumbPath);
             if (!$im) {
                 $im = imagecreatetruecolor($w * $vid_slices, $h);
             }
             imagecopy($im, $srcIm, $w * $vid_slice, 0, 0, 0, $w, $h);
             imagedestroy($srcIm);
             ++$vid_slice;
         }
     }
     if ($multi) {
         imagejpeg($im, $tempThumbPath);
         imagedestroy($im);
     }
     return $tempThumbPath;
 }