1
0
mirror of https://github.com/mosbth/cimage.git synced 2025-08-26 17:14:27 +02:00

Compare commits

..

15 Commits

Author SHA1 Message Date
Mikael Roos
80610b31b9 generated new bundles 2015-10-21 01:13:36 +02:00
Mikael Roos
b639220d05 prepare to tag v0.7.7 2015-10-21 01:13:18 +02:00
Mikael Roos
ee9fdb8474 One can now add a HTTP header for Cache-Control in the config file, #109. 2015-10-21 01:12:10 +02:00
Mikael Roos
db5ce71926 Added hook in img,php before CImage is called, #123. 2015-10-21 00:51:56 +02:00
Mikael Roos
1bf57fe8ef Added hook in img,php before CImage is called, #123. 2015-10-21 00:51:48 +02:00
Mikael Roos
8c89166967 Added configuration for default jpeg quality and png compression in the config file, #107. 2015-10-21 00:30:01 +02:00
Mikael Roos
ce8ec325d3 Strip comments and whitespace in imgs.php. 2015-10-21 00:13:56 +02:00
Mikael Roos
ca9b4a4ce6 webroot/img/issue117/img.php?src=issue117%2Ftri_original.png 2015-10-21 00:05:14 +02:00
Mikael Roos
7c0f37628f Adding option &status to get an overview of the installed ond configured utilities, #116. 2015-10-21 00:04:37 +02:00
Mikael Roos
5fe8e399a1 * Added option to decide if resample or resize when copying images internally. &no-resample makes resize, instead of resample as is default.
* Verbose now correctly states if transparent color is detected.
* Removed that source png-files, containing less than 255 colors, is always saved as palette images since this migth depend on processing of the image.
2015-10-20 13:46:01 +02:00
Mikael Roos
9620c1eb75 Adding testcase for issue #117 2015-10-20 13:45:16 +02:00
Mikael Roos
f721ef4b35 Adding save-as as part of the generated cache filename, #121. 2015-10-20 10:26:09 +02:00
Mikael Roos
37b39fbecf Add extra fileds to json-response, #114. 2015-10-20 10:04:37 +02:00
Mikael Roos
553d2f3db1 Add header for Content-Length, #111. 2015-10-18 18:34:42 +02:00
Mikael Roos
9e2bd27c6e Add check for postprocessing tools in path in webroot/check_system.php, #104. 2015-10-18 18:13:12 +02:00
16 changed files with 1255 additions and 4751 deletions

View File

@@ -63,6 +63,13 @@ class CImage
/**
* Add HTTP headers for outputing image.
*/
private $HTTPHeader = array();
/**
* Default background color, red, green, blue, alpha.
*
@@ -382,12 +389,21 @@ class CImage
/*
* output to ascii can take som options as an array.
* Output to ascii can take som options as an array.
*/
private $asciiOptions = array();
/*
* Image copy strategy, defaults to RESAMPLE.
*/
const RESIZE = 1;
const RESAMPLE = 2;
private $copyStrategy = NULL;
/**
* Properties, the class is mutable and the method setOptions()
* decides (partly) what properties are created.
@@ -600,6 +616,26 @@ class CImage
/**
* Normalize the file extension.
*
* @param string $extension of image file or skip to use internal.
*
* @return string $extension as a normalized file extension.
*/
private function normalizeFileExtension($extension = null)
{
$extension = strtolower($extension ? $extension : $this->extension);
if ($extension == 'jpeg') {
$extension = 'jpg';
}
return $extension;
}
/**
* Download a remote image and return path to its local copy.
*
@@ -1279,6 +1315,14 @@ class CImage
$rotateBefore = $this->rotateBefore ? "_rb{$this->rotateBefore}" : null;
$rotateAfter = $this->rotateAfter ? "_ra{$this->rotateAfter}" : null;
$saveAs = $this->normalizeFileExtension();
$saveAs = $saveAs ? "_$saveAs" : null;
$copyStrat = null;
if ($this->copyStrategy === self::RESIZE) {
$copyStrat = "_rs";
}
$width = $this->newWidth;
$height = $this->newHeight;
@@ -1336,7 +1380,7 @@ class CImage
. $quality . $filters . $sharpen . $emboss . $blur . $palette
. $optimize . $compress
. $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor
. $convolve;
. $convolve . $copyStrat . $saveAs;
return $this->setTarget($file, $base);
}
@@ -1401,6 +1445,7 @@ class CImage
throw new Exception("Could not load image.");
}
/* Removed v0.7.7
if (image_type_to_mime_type($this->fileType) == 'image/png') {
$type = $this->getPngType();
$hasFewColors = imagecolorstotal($this->image);
@@ -1412,14 +1457,15 @@ class CImage
$this->palette = true;
}
}
*/
if ($this->verbose) {
$this->log("Image successfully loaded from file.");
$this->log("### Image successfully loaded from file.");
$this->log(" imageistruecolor() : " . (imageistruecolor($this->image) ? 'true' : 'false'));
$this->log(" imagecolorstotal() : " . imagecolorstotal($this->image));
$this->log(" Number of colors in image = " . $this->colorsTotal($this->image));
$index = imagecolortransparent($this->image);
$this->log(" Detected transparent color = " . ($index > 0 ? implode(", ", imagecolorsforindex($this->image, $index)) : "NONE") . " at index = $index");
$this->log(" Detected transparent color = " . ($index >= 0 ? implode(", ", imagecolorsforindex($this->image, $index)) : "NONE") . " at index = $index");
}
return $this;
@@ -1430,44 +1476,80 @@ class CImage
/**
* Get the type of PNG image.
*
* @param string $filename to use instead of default.
*
* @return int as the type of the png-image
*
*/
private function getPngType()
public function getPngType($filename = null)
{
$pngType = ord(file_get_contents($this->pathToImage, false, null, 25, 1));
$filename = $filename ? $filename : $this->pathToImage;
$pngType = ord(file_get_contents($filename, false, null, 25, 1));
if ($this->verbose) {
$this->log("Checking png type of: " . $filename);
$this->log($this->getPngTypeAsString($pngType));
}
return $pngType;
}
/**
* Get the type of PNG image as a verbose string.
*
* @param integer $type to use, default is to check the type.
* @param string $filename to use instead of default.
*
* @return int as the type of the png-image
*
*/
private function getPngTypeAsString($pngType = null, $filename = null)
{
if ($filename || !$pngType) {
$pngType = $this->getPngType($filename);
}
$index = imagecolortransparent($this->image);
$transparent = null;
if ($index != -1) {
$transparent = " (transparent)";
}
switch ($pngType) {
case self::PNG_GREYSCALE:
$this->log("PNG is type 0, Greyscale.");
$text = "PNG is type 0, Greyscale$transparent";
break;
case self::PNG_RGB:
$this->log("PNG is type 2, RGB");
$text = "PNG is type 2, RGB$transparent";
break;
case self::PNG_RGB_PALETTE:
$this->log("PNG is type 3, RGB with palette");
$text = "PNG is type 3, RGB with palette$transparent";
break;
case self::PNG_GREYSCALE_ALPHA:
$this->Log("PNG is type 4, Greyscale with alpha channel");
$text = "PNG is type 4, Greyscale with alpha channel";
break;
case self::PNG_RGB_ALPHA:
$this->Log("PNG is type 6, RGB with alpha channel (PNG 32-bit)");
$text = "PNG is type 6, RGB with alpha channel (PNG 32-bit)";
break;
default:
$this->Log("PNG is UNKNOWN type, is it really a PNG image?");
$text = "PNG is UNKNOWN type, is it really a PNG image?";
}
return $pngType;
return $text;
}
/**
* Calculate number of colors in an image.
*
@@ -1503,7 +1585,7 @@ class CImage
*/
public function preResize()
{
$this->log("Pre-process before resizing");
$this->log("### Pre-process before resizing");
// Rotate image
if ($this->rotateBefore) {
@@ -1536,6 +1618,39 @@ class CImage
/**
* Resize or resample the image while resizing.
*
* @param int $strategy as CImage::RESIZE or CImage::RESAMPLE
*
* @return $this
*/
public function setCopyResizeStrategy($strategy)
{
$this->copyStrategy = $strategy;
return $this;
}
/**
* Resize and or crop the image.
*
* @return void
*/
public function imageCopyResampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
{
if($this->copyStrategy == self::RESIZE) {
$this->log("Copy by resize");
imagecopyresized($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
} else {
$this->log("Copy by resample");
imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
}
}
/**
* Resize and or crop the image.
*
@@ -1544,7 +1659,7 @@ class CImage
public function resize()
{
$this->log("Starting to Resize()");
$this->log("### Starting to Resize()");
$this->log("Upscale = '$this->upscale'");
// Only use a specified area of the image, $this->offset is defining the area to use
@@ -1604,7 +1719,7 @@ class CImage
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
$imgPreCrop = $this->CreateImageKeepTransparency($this->cropWidth, $this->cropHeight);
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopyresampled($imgPreCrop, $this->image, 0, 0, 0, 0, $this->cropWidth, $this->cropHeight, $this->width, $this->height);
$this->imageCopyResampled($imgPreCrop, $this->image, 0, 0, 0, 0, $this->cropWidth, $this->cropHeight, $this->width, $this->height);
imagecopy($imageResized, $imgPreCrop, 0, 0, $cropX, $cropY, $this->newWidth, $this->newHeight);
}
@@ -1643,7 +1758,7 @@ class CImage
} else {
$imgPreFill = $this->CreateImageKeepTransparency($this->fillWidth, $this->fillHeight);
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopyresampled($imgPreFill, $this->image, 0, 0, 0, 0, $this->fillWidth, $this->fillHeight, $this->width, $this->height);
$this->imageCopyResampled($imgPreFill, $this->image, 0, 0, 0, 0, $this->fillWidth, $this->fillHeight, $this->width, $this->height);
imagecopy($imageResized, $imgPreFill, $posX, $posY, 0, 0, $this->fillWidth, $this->fillHeight);
}
@@ -1689,7 +1804,7 @@ class CImage
}
} else {
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopyresampled($imageResized, $this->image, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->width, $this->height);
$this->imageCopyResampled($imageResized, $this->image, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->width, $this->height);
$this->image = $imageResized;
$this->width = $this->newWidth;
$this->height = $this->newHeight;
@@ -1708,7 +1823,7 @@ class CImage
*/
public function postResize()
{
$this->log("Post-process after resizing");
$this->log("### Post-process after resizing");
// Rotate image
if ($this->rotateAfter) {
@@ -2168,10 +2283,11 @@ class CImage
*/
protected function getTargetImageExtension()
{
// switch on mimetype
if (isset($this->extension)) {
return strtolower($this->extension);
} else {
return image_type_to_extension($this->fileType);
return substr(image_type_to_extension($this->fileType), 1);
}
}
@@ -2200,7 +2316,9 @@ class CImage
is_writable($this->saveFolder)
or $this->raiseError('Target directory is not writable.');
switch($this->getTargetImageExtension()) {
$type = $this->getTargetImageExtension();
$this->Log("Saving image as " . $type);
switch($type) {
case 'jpeg':
case 'jpg':
@@ -2294,8 +2412,6 @@ class CImage
return $this;
}
$alias = $alias . "." . $this->getTargetImageExtension();
if (is_readable($alias)) {
unlink($alias);
}
@@ -2313,11 +2429,28 @@ class CImage
/**
* Add HTTP header for putputting together with image.
*
* @param string $type the header type such as "Cache-Control"
* @param string $value the value to use
*
* @return void
*/
public function addHTTPHeader($type, $value)
{
$this->HTTPHeader[$type] = $value;
}
/**
* Output image to browser using caching.
*
* @param string $file to read and output, default is to use $this->cacheFileName
* @param string $format set to json to output file as json object with details
* @param string $file to read and output, default is to
* use $this->cacheFileName
* @param string $format set to json to output file as json
* object with details
*
* @return void
*/
@@ -2354,6 +2487,10 @@ class CImage
header('Last-Modified: ' . $gmdate . " GMT");
}
foreach($this->HTTPHeader as $key => $val) {
header("$key: $val");
}
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $lastModified) {
if ($this->verbose) {
@@ -2366,8 +2503,16 @@ class CImage
} else {
// Get details on image
$info = getimagesize($file);
!empty($info) or $this->raiseError("The file doesn't seem to be an image.");
$mime = $info['mime'];
$size = filesize($file);
if ($this->verbose) {
$this->log("Last modified: " . $gmdate . " GMT");
$this->log("Last-Modified: " . $gmdate . " GMT");
$this->log("Content-type: " . $mime);
$this->log("Content-length: " . $size);
$this->verboseOutput();
if (is_null($this->verboseFileName)) {
@@ -2375,12 +2520,8 @@ class CImage
}
}
// Get details on image
$info = getimagesize($file);
!empty($info) or $this->raiseError("The file doesn't seem to be an image.");
$mime = $info['mime'];
header('Content-type: ' . $mime);
header("Content-type: $mime");
header("Content-length: $size");
readfile($file);
}
@@ -2421,6 +2562,18 @@ class CImage
$details['aspectRatio'] = round($this->width / $this->height, 3);
$details['size'] = filesize($file);
$details['colors'] = $this->colorsTotal($this->image);
$details['includedFiles'] = count(get_included_files());
$details['memoryPeek'] = round(memory_get_peak_usage()/1024/1024, 3) . " MB" ;
$details['memoryCurrent'] = round(memory_get_usage()/1024/1024, 3) . " MB";
$details['memoryLimit'] = ini_get('memory_limit');
if (isset($_SERVER['REQUEST_TIME_FLOAT'])) {
$details['loadTime'] = (string) round((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']), 3) . "s";
}
if ($details['mimeType'] == 'image/png') {
$details['pngType'] = $this->getPngTypeAsString(null, $file);
}
$options = null;
if (defined("JSON_PRETTY_PRINT") && defined("JSON_UNESCAPED_SLASHES")) {

View File

@@ -5,6 +5,28 @@ Revision history
[![Build Status](https://scrutinizer-ci.com/g/mosbth/cimage/badges/build.png?b=master)](https://scrutinizer-ci.com/g/mosbth/cimage/build-status/master)
v0.7.7 (2015-10-21)
-------------------------------------
* One can now add a HTTP header for Cache-Control in the config file, #109.
* Added hook in img,php before CImage is called, #123.
* Added configuration for default jpeg quality and png compression in the config file, #107.
* Strip comments and whitespace in imgs.php, #115.
* Bundle imgs.php did not have the correct mode.
* Adding option &status to get an overview of the installed on configured utilities, #116.
* Bug, all files saved as png-files, when not saving as specific file.
* Removed saving filename extension for alias images.
* Added option to decide if resample or resize when copying images internally. `&no-resample` makes resize, instead of resample as is default.
* Verbose now correctly states if transparent color is detected.
* Compare-tool now supports 6 images.
* Added option for dark background in the compare-tool.
* Removed that source png-files, containing less than 255 colors, is always saved as palette images since this migth depend on processing of the image.
* Adding save-as as part of the generated cache filename, #121.
* Add extra fields to json-response, #114.
* Add header for Content-Length, #111.
* Add check for postprocessing tools in path in `webroot/check_system.php`, #104.
v0.7.6 (2015-10-18)
-------------------------------------

View File

@@ -55,7 +55,7 @@ read answer
#
cat webroot/img_header.php > $TARGET_P
cat webroot/img_header.php | sed "s|//'mode' => 'production',|'mode' => 'development',|" > $TARGET_D
cat webroot/img_header.php | sed "s|//'mode' => 'production',|'mode' => 'development',|" > $TARGET_S
cat webroot/img_header.php | sed "s|//'mode' => 'production',|'mode' => 'strict',|" > $TARGET_S
$ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
@@ -77,6 +77,8 @@ $ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
tail -n +2 webroot/img.php | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
$ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
php -w $TARGET_S > tmp && mv tmp $TARGET_S
$ECHO "\nDone."
$ECHO "\n"
$ECHO "\n"

View File

@@ -4,6 +4,12 @@ echo 'Current PHP version: ' . phpversion() . '<br><br>';
echo 'Running on: ' . $_SERVER['SERVER_SOFTWARE'] . '<br><br>';
$no = extension_loaded('exif') ? null : 'NOT';
echo "Extension exif is $no loaded.<br>";
$no = extension_loaded('curl') ? null : 'NOT';
echo "Extension curl is $no loaded.<br>";
$no = extension_loaded('gd') ? null : 'NOT';
echo "Extension gd is $no loaded.<br>";
@@ -11,8 +17,13 @@ if (!$no) {
echo "<pre>", var_dump(gd_info()), "</pre>";
}
$no = extension_loaded('exif') ? null : 'NOT';
echo "Extension exif is $no loaded.<br>";
echo "<strong>Checking path for postprocessing tools</strong>";
$no = extension_loaded('curl') ? null : 'NOT';
echo "Extension curl is $no loaded.<br>";
echo "<br>optipng: ";
system("which optipng");
echo "<br>pngout: ";
system("which pngout");
echo "<br>jpegtran: ";
system("which jpegtran");

View File

@@ -29,7 +29,12 @@ input[type=text] {
.area {
float: left;
padding: 1em;
background-color: #fff;
background-color: #eee;
}
.invert {
background-color: #666;
color: white;
}
.json {
@@ -45,7 +50,7 @@ input[type=text] {
<body>
<h1>Compare images</h1>
<p>Add link to images and visually compare them. Change the link och press return to load the image. <a href="http://dbwebb.se/opensource/cimage">Read more...</a></p>
<p>Add link to images and visually compare them. Change the link och press return to load the image. Add <code>&amp;black</code> to the querystring to get a black background. <a href="http://dbwebb.se/opensource/cimage">Read more...</a></p>
<p><a id="permalink" href="?">Direct link to this setup.</a></p>
@@ -55,8 +60,11 @@ input[type=text] {
<label>Image 2: <input type="text" id="input2" data-id="2"></label> <img id="thumb2"></br>
<label>Image 3: <input type="text" id="input3" data-id="3"></label> <img id="thumb3"></br>
<label>Image 4: <input type="text" id="input4" data-id="4"></label> <img id="thumb4"></br>
<label>Image 5: <input type="text" id="input5" data-id="5"></label> <img id="thumb5"></br>
<label>Image 6: <input type="text" id="input6" data-id="6"></label> <img id="thumb6"></br>
<label><input type="checkbox" id="viewDetails">Show image details</label><br/>
<label><input type="checkbox" id="stack">Stack images?</label>
<label><input type="checkbox" id="stack">Stack images?</label><br/>
<label><input type="checkbox" id="bg">Dark background?</label>
</p>
</form>
@@ -65,6 +73,8 @@ input[type=text] {
<button id="button2" class="button" data-id="2">Image 2</button>
<button id="button3" class="button" data-id="3">Image 3</button>
<button id="button4" class="button" data-id="4">Image 4</button>
<button id="button5" class="button" data-id="5">Image 5</button>
<button id="button6" class="button" data-id="6">Image 6</button>
</div>
<div id="wrap">
@@ -93,6 +103,18 @@ input[type=text] {
<pre id="json4" class="json hidden"></pre>
</div>
<div id="area5" class="area">
<code>Image 5</code><br>
<img id="img5">
<pre id="json5" class="json hidden"></pre>
</div>
<div id="area6" class="area">
<code>Image 6</code><br>
<img id="img6">
<pre id="json6" class="json hidden"></pre>
</div>
</div>
@@ -110,8 +132,11 @@ if (isset($_GET['input1'])) {
"input2": "<?=$_GET['input2']?>",
"input3": "<?=$_GET['input3']?>",
"input4": "<?=$_GET['input4']?>",
"input5": "<?=$_GET['input5']?>",
"input6": "<?=$_GET['input6']?>",
"json": <?=$_GET['json']?>,
"stack": <?=$_GET['stack']?>
"stack": <?=$_GET['stack']?>,
"bg": <?=$_GET['bg']?>
});
<?php
} elseif (isset($script)) {

View File

@@ -0,0 +1,16 @@
<?php
$script = <<<EOD
CImage.compare({
"input1": "../img.php?src=issue117/tri_original.png",
"input2": "../img.php?src=issue117/tri_imageresizing.png",
"input3": "../img.php?src=issue117/tri_cimage.png",
"input4": "../img.php?src=issue117/tri_imagemagick.png",
"input5": "../img.php?src=issue117/tri_original.png&w=190",
"input6": "../img.php?src=issue117/tri_original.png&w=190&no-resample",
"json": true,
"stack": false,
"bg": true
});
EOD;
include __DIR__ . "/compare.php";

View File

@@ -8,7 +8,7 @@
*
*/
$version = "v0.7.6 (2015-10-18)";
$version = "v0.7.7 (2015-10-21)";
@@ -157,6 +157,13 @@ verbose("img.php version = $version");
/**
* status - do a verbose dump of the configuration
*/
$status = getDefined('status', true, false);
/**
* Set mode as strict, production or development.
* Default is production environment.
@@ -178,6 +185,7 @@ if ($mode == 'strict') {
ini_set('display_errors', 0);
ini_set('log_errors', 1);
$verbose = false;
$status = false;
$verboseFile = false;
} elseif ($mode == 'production') {
@@ -186,6 +194,7 @@ if ($mode == 'strict') {
ini_set('display_errors', 0);
ini_set('log_errors', 1);
$verbose = false;
$status = false;
$verboseFile = false;
} elseif ($mode == 'development') {
@@ -558,6 +567,19 @@ verbose("bgColor = $bgColor");
/**
* Do or do not resample image when resizing.
*/
$resizeStrategy = getDefined(array('no-resample'), true, false);
if ($resizeStrategy) {
$img->setCopyResizeStrategy($img::RESIZE);
verbose("Setting = Resize instead of resample");
}
/**
* fill-to-fit, ff - affecting the resulting image width, height and resize options
*/
@@ -627,11 +649,16 @@ verbose("use cache = $useCache");
* quality, q - set level of quality for jpeg images
*/
$quality = get(array('quality', 'q'));
$qualityDefault = getConfig('jpg_quality', null);
is_null($quality)
or ($quality > 0 and $quality <= 100)
or errorPage('Quality out of range');
if (is_null($quality) && !is_null($qualityDefault)) {
$quality = $qualityDefault;
}
verbose("quality = $quality");
@@ -640,12 +667,16 @@ verbose("quality = $quality");
* compress, co - what strategy to use when compressing png images
*/
$compress = get(array('compress', 'co'));
$compressDefault = getConfig('png_compression', null);
is_null($compress)
or ($compress > 0 and $compress <= 9)
or errorPage('Compress out of range');
if (is_null($compress) && !is_null($compressDefault)) {
$compress = $compressDefault;
}
verbose("compress = $compress");
@@ -897,6 +928,146 @@ $cachePath = getConfig('cache_path', __DIR__ . '/../cache/');
/**
* Get the cachepath from config.
*/
$cacheControl = getConfig('cache_control', null);
if ($cacheControl) {
verbose("cacheControl = $cacheControl");
$img->addHTTPHeader("Cache-Control", $cacheControl);
}
/**
* Prepare a dummy image and use it as source image.
*/
$dummyDir = getConfig('dummy_dir', $cachePath. "/" . $dummyFilename);
if ($dummyImage === true) {
is_writable($dummyDir)
or verbose("dummy dir not writable = $dummyDir");
$img->setSaveFolder($dummyDir)
->setSource($dummyFilename, $dummyDir)
->setOptions(
array(
'newWidth' => $newWidth,
'newHeight' => $newHeight,
'bgColor' => $bgColor,
)
)
->setJpegQuality($quality)
->setPngCompression($compress)
->createDummyImage()
->generateFilename(null, false)
->save(null, null, false);
$srcImage = $img->getTarget();
$imagePath = null;
verbose("src (updated) = $srcImage");
}
/**
* Display status
*/
if ($status) {
$text = "img.php version = $version\n";
$text .= "PHP version = " . PHP_VERSION . "\n";
$text .= "Running on: " . $_SERVER['SERVER_SOFTWARE'] . "\n";
$text .= "Allow remote images = $allowRemote\n";
$text .= "Cache writable = " . is_writable($cachePath) . "\n";
$text .= "Cache dummy writable = " . is_writable($dummyDir) . "\n";
$text .= "Alias path writable = " . is_writable($aliasPath) . "\n";
$no = extension_loaded('exif') ? null : 'NOT';
$text .= "Extension exif is $no loaded.<br>";
$no = extension_loaded('curl') ? null : 'NOT';
$text .= "Extension curl is $no loaded.<br>";
$no = extension_loaded('gd') ? null : 'NOT';
$text .= "Extension gd is $no loaded.<br>";
if (!$no) {
$text .= print_r(gd_info(), 1);
}
echo <<<EOD
<!doctype html>
<html lang=en>
<meta charset=utf-8>
<title>CImage status</title>
<pre>$text</pre>
EOD;
exit;
}
/**
* Log verbose details to file
*/
if ($verboseFile) {
$img->setVerboseToFile("$cachePath/log.txt");
}
/**
* Hook after img.php configuration and before processing with CImage
*/
$hookBeforeCImage = getConfig('hook_before_CImage', null);
if (is_callable($hookBeforeCImage)) {
verbose("hookBeforeCImage activated");
$allConfig = $hookBeforeCImage($img, array(
// Options for calculate dimensions
'newWidth' => $newWidth,
'newHeight' => $newHeight,
'aspectRatio' => $aspectRatio,
'keepRatio' => $keepRatio,
'cropToFit' => $cropToFit,
'fillToFit' => $fillToFit,
'crop' => $crop,
'area' => $area,
'upscale' => $upscale,
// Pre-processing, before resizing is done
'scale' => $scale,
'rotateBefore' => $rotateBefore,
'autoRotate' => $autoRotate,
// General processing options
'bgColor' => $bgColor,
// Post-processing, after resizing is done
'palette' => $palette,
'filters' => $filters,
'sharpen' => $sharpen,
'emboss' => $emboss,
'blur' => $blur,
'convolve' => $convolve,
'rotateAfter' => $rotateAfter,
// Output format
'outputFormat' => $outputFormat,
'dpr' => $dpr,
// Other
'postProcessing' => $postProcessing,
));
verbose(print_r($allConfig, 1));
extract($allConfig);
}
/**
* Display image if verbose mode
*/
@@ -924,7 +1095,7 @@ if ($verbose) {
window.getDetails = function (url, id) {
$.getJSON(url, function(data) {
element = document.getElementById(id);
element.innerHTML = "filename: " + data.filename + "\\nmime type: " + data.mimeType + "\\ncolors: " + data.colors + "\\nsize: " + data.size + "\\nwidth: " + data.width + "\\nheigh: " + data.height + "\\naspect-ratio: " + data.aspectRatio;
element.innerHTML = "filename: " + data.filename + "\\nmime type: " + data.mimeType + "\\ncolors: " + data.colors + "\\nsize: " + data.size + "\\nwidth: " + data.width + "\\nheigh: " + data.height + "\\naspect-ratio: " + data.aspectRatio + ( data.pngType ? "\\npng-type: " + data.pngType : '');
});
}
</script>
@@ -934,53 +1105,6 @@ EOD;
/**
* Log verbose details to file
*/
if ($verboseFile) {
$img->setVerboseToFile("$cachePath/log.txt");
}
/**
* Set basic options for image processing.
*/
/**
* Prepare a dummy image and use it as source image.
*/
if ($dummyImage === true) {
$dummyDir = getConfig('dummy_dir', $cachePath. "/" . $dummyFilename);
is_writable($dummyDir)
or verbose("dummy dir not writable = $dummyDir");
$img->setSaveFolder($dummyDir)
->setSource($dummyFilename, $dummyDir)
->setOptions(
array(
'newWidth' => $newWidth,
'newHeight' => $newHeight,
'bgColor' => $bgColor,
)
)
->setJpegQuality($quality)
->setPngCompression($compress)
->createDummyImage()
->generateFilename(null, false)
->save(null, null, false);
$srcImage = $img->getTarget();
$imagePath = null;
verbose("src (updated) = $srcImage");
}
/**
* Load, process and output the image
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -13,6 +13,7 @@ return array(
* Default values:
* mode: 'production'
*/
'mode' => 'development', // 'development', 'strict'
//'mode' => 'production', // 'development', 'strict'
@@ -108,6 +109,47 @@ return array(
/**
* Change the default values for CImage quality and compression used
* when saving images.
*
* Default value:
* jpg_quality: null, integer between 0-100
* png_compression: null, integer between 0-9
*/
//'jpg_quality' => 75,
//'png_compression' => 1,
/**
* A function (hook) can be called after img.php has processed all
* configuration options and before processing the image using CImage.
* The function receives the $img variabel and an array with the
* majority of current settings.
*
* Default value:
* hook_before_CImage: null
*/
/*'hook_before_CImage' => function (CImage $img, Array $allConfig) {
if ($allConfig['newWidth'] > 10) {
$allConfig['newWidth'] *= 2;
}
return $allConfig;
},*/
/**
* Add header for cache control when outputting images.
*
* Default value:
* cache_control: null, or set to string
*/
//'cache_control' => "max-age=86400",
/**
* The name representing a dummy image which is automatically created
* and stored at the defined path. The dummy image can then be used

View File

@@ -982,6 +982,13 @@ class CImage
/**
* Add HTTP headers for outputing image.
*/
private $HTTPHeader = array();
/**
* Default background color, red, green, blue, alpha.
*
@@ -1301,12 +1308,21 @@ class CImage
/*
* output to ascii can take som options as an array.
* Output to ascii can take som options as an array.
*/
private $asciiOptions = array();
/*
* Image copy strategy, defaults to RESAMPLE.
*/
const RESIZE = 1;
const RESAMPLE = 2;
private $copyStrategy = NULL;
/**
* Properties, the class is mutable and the method setOptions()
* decides (partly) what properties are created.
@@ -1519,6 +1535,26 @@ class CImage
/**
* Normalize the file extension.
*
* @param string $extension of image file or skip to use internal.
*
* @return string $extension as a normalized file extension.
*/
private function normalizeFileExtension($extension = null)
{
$extension = strtolower($extension ? $extension : $this->extension);
if ($extension == 'jpeg') {
$extension = 'jpg';
}
return $extension;
}
/**
* Download a remote image and return path to its local copy.
*
@@ -2198,6 +2234,14 @@ class CImage
$rotateBefore = $this->rotateBefore ? "_rb{$this->rotateBefore}" : null;
$rotateAfter = $this->rotateAfter ? "_ra{$this->rotateAfter}" : null;
$saveAs = $this->normalizeFileExtension();
$saveAs = $saveAs ? "_$saveAs" : null;
$copyStrat = null;
if ($this->copyStrategy === self::RESIZE) {
$copyStrat = "_rs";
}
$width = $this->newWidth;
$height = $this->newHeight;
@@ -2255,7 +2299,7 @@ class CImage
. $quality . $filters . $sharpen . $emboss . $blur . $palette
. $optimize . $compress
. $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor
. $convolve;
. $convolve . $copyStrat . $saveAs;
return $this->setTarget($file, $base);
}
@@ -2320,6 +2364,7 @@ class CImage
throw new Exception("Could not load image.");
}
/* Removed v0.7.7
if (image_type_to_mime_type($this->fileType) == 'image/png') {
$type = $this->getPngType();
$hasFewColors = imagecolorstotal($this->image);
@@ -2331,14 +2376,15 @@ class CImage
$this->palette = true;
}
}
*/
if ($this->verbose) {
$this->log("Image successfully loaded from file.");
$this->log("### Image successfully loaded from file.");
$this->log(" imageistruecolor() : " . (imageistruecolor($this->image) ? 'true' : 'false'));
$this->log(" imagecolorstotal() : " . imagecolorstotal($this->image));
$this->log(" Number of colors in image = " . $this->colorsTotal($this->image));
$index = imagecolortransparent($this->image);
$this->log(" Detected transparent color = " . ($index > 0 ? implode(", ", imagecolorsforindex($this->image, $index)) : "NONE") . " at index = $index");
$this->log(" Detected transparent color = " . ($index >= 0 ? implode(", ", imagecolorsforindex($this->image, $index)) : "NONE") . " at index = $index");
}
return $this;
@@ -2349,44 +2395,80 @@ class CImage
/**
* Get the type of PNG image.
*
* @param string $filename to use instead of default.
*
* @return int as the type of the png-image
*
*/
private function getPngType()
public function getPngType($filename = null)
{
$pngType = ord(file_get_contents($this->pathToImage, false, null, 25, 1));
$filename = $filename ? $filename : $this->pathToImage;
$pngType = ord(file_get_contents($filename, false, null, 25, 1));
if ($this->verbose) {
$this->log("Checking png type of: " . $filename);
$this->log($this->getPngTypeAsString($pngType));
}
return $pngType;
}
/**
* Get the type of PNG image as a verbose string.
*
* @param integer $type to use, default is to check the type.
* @param string $filename to use instead of default.
*
* @return int as the type of the png-image
*
*/
private function getPngTypeAsString($pngType = null, $filename = null)
{
if ($filename || !$pngType) {
$pngType = $this->getPngType($filename);
}
$index = imagecolortransparent($this->image);
$transparent = null;
if ($index != -1) {
$transparent = " (transparent)";
}
switch ($pngType) {
case self::PNG_GREYSCALE:
$this->log("PNG is type 0, Greyscale.");
$text = "PNG is type 0, Greyscale$transparent";
break;
case self::PNG_RGB:
$this->log("PNG is type 2, RGB");
$text = "PNG is type 2, RGB$transparent";
break;
case self::PNG_RGB_PALETTE:
$this->log("PNG is type 3, RGB with palette");
$text = "PNG is type 3, RGB with palette$transparent";
break;
case self::PNG_GREYSCALE_ALPHA:
$this->Log("PNG is type 4, Greyscale with alpha channel");
$text = "PNG is type 4, Greyscale with alpha channel";
break;
case self::PNG_RGB_ALPHA:
$this->Log("PNG is type 6, RGB with alpha channel (PNG 32-bit)");
$text = "PNG is type 6, RGB with alpha channel (PNG 32-bit)";
break;
default:
$this->Log("PNG is UNKNOWN type, is it really a PNG image?");
$text = "PNG is UNKNOWN type, is it really a PNG image?";
}
return $pngType;
return $text;
}
/**
* Calculate number of colors in an image.
*
@@ -2422,7 +2504,7 @@ class CImage
*/
public function preResize()
{
$this->log("Pre-process before resizing");
$this->log("### Pre-process before resizing");
// Rotate image
if ($this->rotateBefore) {
@@ -2455,6 +2537,39 @@ class CImage
/**
* Resize or resample the image while resizing.
*
* @param int $strategy as CImage::RESIZE or CImage::RESAMPLE
*
* @return $this
*/
public function setCopyResizeStrategy($strategy)
{
$this->copyStrategy = $strategy;
return $this;
}
/**
* Resize and or crop the image.
*
* @return void
*/
public function imageCopyResampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
{
if($this->copyStrategy == self::RESIZE) {
$this->log("Copy by resize");
imagecopyresized($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
} else {
$this->log("Copy by resample");
imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
}
}
/**
* Resize and or crop the image.
*
@@ -2463,7 +2578,7 @@ class CImage
public function resize()
{
$this->log("Starting to Resize()");
$this->log("### Starting to Resize()");
$this->log("Upscale = '$this->upscale'");
// Only use a specified area of the image, $this->offset is defining the area to use
@@ -2523,7 +2638,7 @@ class CImage
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
$imgPreCrop = $this->CreateImageKeepTransparency($this->cropWidth, $this->cropHeight);
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopyresampled($imgPreCrop, $this->image, 0, 0, 0, 0, $this->cropWidth, $this->cropHeight, $this->width, $this->height);
$this->imageCopyResampled($imgPreCrop, $this->image, 0, 0, 0, 0, $this->cropWidth, $this->cropHeight, $this->width, $this->height);
imagecopy($imageResized, $imgPreCrop, 0, 0, $cropX, $cropY, $this->newWidth, $this->newHeight);
}
@@ -2562,7 +2677,7 @@ class CImage
} else {
$imgPreFill = $this->CreateImageKeepTransparency($this->fillWidth, $this->fillHeight);
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopyresampled($imgPreFill, $this->image, 0, 0, 0, 0, $this->fillWidth, $this->fillHeight, $this->width, $this->height);
$this->imageCopyResampled($imgPreFill, $this->image, 0, 0, 0, 0, $this->fillWidth, $this->fillHeight, $this->width, $this->height);
imagecopy($imageResized, $imgPreFill, $posX, $posY, 0, 0, $this->fillWidth, $this->fillHeight);
}
@@ -2608,7 +2723,7 @@ class CImage
}
} else {
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopyresampled($imageResized, $this->image, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->width, $this->height);
$this->imageCopyResampled($imageResized, $this->image, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->width, $this->height);
$this->image = $imageResized;
$this->width = $this->newWidth;
$this->height = $this->newHeight;
@@ -2627,7 +2742,7 @@ class CImage
*/
public function postResize()
{
$this->log("Post-process after resizing");
$this->log("### Post-process after resizing");
// Rotate image
if ($this->rotateAfter) {
@@ -3087,10 +3202,11 @@ class CImage
*/
protected function getTargetImageExtension()
{
// switch on mimetype
if (isset($this->extension)) {
return strtolower($this->extension);
} else {
return image_type_to_extension($this->fileType);
return substr(image_type_to_extension($this->fileType), 1);
}
}
@@ -3119,7 +3235,9 @@ class CImage
is_writable($this->saveFolder)
or $this->raiseError('Target directory is not writable.');
switch($this->getTargetImageExtension()) {
$type = $this->getTargetImageExtension();
$this->Log("Saving image as " . $type);
switch($type) {
case 'jpeg':
case 'jpg':
@@ -3213,8 +3331,6 @@ class CImage
return $this;
}
$alias = $alias . "." . $this->getTargetImageExtension();
if (is_readable($alias)) {
unlink($alias);
}
@@ -3232,11 +3348,28 @@ class CImage
/**
* Add HTTP header for putputting together with image.
*
* @param string $type the header type such as "Cache-Control"
* @param string $value the value to use
*
* @return void
*/
public function addHTTPHeader($type, $value)
{
$this->HTTPHeader[$type] = $value;
}
/**
* Output image to browser using caching.
*
* @param string $file to read and output, default is to use $this->cacheFileName
* @param string $format set to json to output file as json object with details
* @param string $file to read and output, default is to
* use $this->cacheFileName
* @param string $format set to json to output file as json
* object with details
*
* @return void
*/
@@ -3273,6 +3406,10 @@ class CImage
header('Last-Modified: ' . $gmdate . " GMT");
}
foreach($this->HTTPHeader as $key => $val) {
header("$key: $val");
}
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $lastModified) {
if ($this->verbose) {
@@ -3285,8 +3422,16 @@ class CImage
} else {
// Get details on image
$info = getimagesize($file);
!empty($info) or $this->raiseError("The file doesn't seem to be an image.");
$mime = $info['mime'];
$size = filesize($file);
if ($this->verbose) {
$this->log("Last modified: " . $gmdate . " GMT");
$this->log("Last-Modified: " . $gmdate . " GMT");
$this->log("Content-type: " . $mime);
$this->log("Content-length: " . $size);
$this->verboseOutput();
if (is_null($this->verboseFileName)) {
@@ -3294,12 +3439,8 @@ class CImage
}
}
// Get details on image
$info = getimagesize($file);
!empty($info) or $this->raiseError("The file doesn't seem to be an image.");
$mime = $info['mime'];
header('Content-type: ' . $mime);
header("Content-type: $mime");
header("Content-length: $size");
readfile($file);
}
@@ -3340,6 +3481,18 @@ class CImage
$details['aspectRatio'] = round($this->width / $this->height, 3);
$details['size'] = filesize($file);
$details['colors'] = $this->colorsTotal($this->image);
$details['includedFiles'] = count(get_included_files());
$details['memoryPeek'] = round(memory_get_peak_usage()/1024/1024, 3) . " MB" ;
$details['memoryCurrent'] = round(memory_get_usage()/1024/1024, 3) . " MB";
$details['memoryLimit'] = ini_get('memory_limit');
if (isset($_SERVER['REQUEST_TIME_FLOAT'])) {
$details['loadTime'] = (string) round((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']), 3) . "s";
}
if ($details['mimeType'] == 'image/png') {
$details['pngType'] = $this->getPngTypeAsString(null, $file);
}
$options = null;
if (defined("JSON_PRETTY_PRINT") && defined("JSON_UNESCAPED_SLASHES")) {
@@ -3481,7 +3634,7 @@ EOD;
*
*/
$version = "v0.7.6 (2015-10-18)";
$version = "v0.7.7 (2015-10-21)";
@@ -3630,6 +3783,13 @@ verbose("img.php version = $version");
/**
* status - do a verbose dump of the configuration
*/
$status = getDefined('status', true, false);
/**
* Set mode as strict, production or development.
* Default is production environment.
@@ -3651,6 +3811,7 @@ if ($mode == 'strict') {
ini_set('display_errors', 0);
ini_set('log_errors', 1);
$verbose = false;
$status = false;
$verboseFile = false;
} elseif ($mode == 'production') {
@@ -3659,6 +3820,7 @@ if ($mode == 'strict') {
ini_set('display_errors', 0);
ini_set('log_errors', 1);
$verbose = false;
$status = false;
$verboseFile = false;
} elseif ($mode == 'development') {
@@ -4031,6 +4193,19 @@ verbose("bgColor = $bgColor");
/**
* Do or do not resample image when resizing.
*/
$resizeStrategy = getDefined(array('no-resample'), true, false);
if ($resizeStrategy) {
$img->setCopyResizeStrategy($img::RESIZE);
verbose("Setting = Resize instead of resample");
}
/**
* fill-to-fit, ff - affecting the resulting image width, height and resize options
*/
@@ -4100,11 +4275,16 @@ verbose("use cache = $useCache");
* quality, q - set level of quality for jpeg images
*/
$quality = get(array('quality', 'q'));
$qualityDefault = getConfig('jpg_quality', null);
is_null($quality)
or ($quality > 0 and $quality <= 100)
or errorPage('Quality out of range');
if (is_null($quality) && !is_null($qualityDefault)) {
$quality = $qualityDefault;
}
verbose("quality = $quality");
@@ -4113,12 +4293,16 @@ verbose("quality = $quality");
* compress, co - what strategy to use when compressing png images
*/
$compress = get(array('compress', 'co'));
$compressDefault = getConfig('png_compression', null);
is_null($compress)
or ($compress > 0 and $compress <= 9)
or errorPage('Compress out of range');
if (is_null($compress) && !is_null($compressDefault)) {
$compress = $compressDefault;
}
verbose("compress = $compress");
@@ -4370,6 +4554,146 @@ $cachePath = getConfig('cache_path', __DIR__ . '/../cache/');
/**
* Get the cachepath from config.
*/
$cacheControl = getConfig('cache_control', null);
if ($cacheControl) {
verbose("cacheControl = $cacheControl");
$img->addHTTPHeader("Cache-Control", $cacheControl);
}
/**
* Prepare a dummy image and use it as source image.
*/
$dummyDir = getConfig('dummy_dir', $cachePath. "/" . $dummyFilename);
if ($dummyImage === true) {
is_writable($dummyDir)
or verbose("dummy dir not writable = $dummyDir");
$img->setSaveFolder($dummyDir)
->setSource($dummyFilename, $dummyDir)
->setOptions(
array(
'newWidth' => $newWidth,
'newHeight' => $newHeight,
'bgColor' => $bgColor,
)
)
->setJpegQuality($quality)
->setPngCompression($compress)
->createDummyImage()
->generateFilename(null, false)
->save(null, null, false);
$srcImage = $img->getTarget();
$imagePath = null;
verbose("src (updated) = $srcImage");
}
/**
* Display status
*/
if ($status) {
$text = "img.php version = $version\n";
$text .= "PHP version = " . PHP_VERSION . "\n";
$text .= "Running on: " . $_SERVER['SERVER_SOFTWARE'] . "\n";
$text .= "Allow remote images = $allowRemote\n";
$text .= "Cache writable = " . is_writable($cachePath) . "\n";
$text .= "Cache dummy writable = " . is_writable($dummyDir) . "\n";
$text .= "Alias path writable = " . is_writable($aliasPath) . "\n";
$no = extension_loaded('exif') ? null : 'NOT';
$text .= "Extension exif is $no loaded.<br>";
$no = extension_loaded('curl') ? null : 'NOT';
$text .= "Extension curl is $no loaded.<br>";
$no = extension_loaded('gd') ? null : 'NOT';
$text .= "Extension gd is $no loaded.<br>";
if (!$no) {
$text .= print_r(gd_info(), 1);
}
echo <<<EOD
<!doctype html>
<html lang=en>
<meta charset=utf-8>
<title>CImage status</title>
<pre>$text</pre>
EOD;
exit;
}
/**
* Log verbose details to file
*/
if ($verboseFile) {
$img->setVerboseToFile("$cachePath/log.txt");
}
/**
* Hook after img.php configuration and before processing with CImage
*/
$hookBeforeCImage = getConfig('hook_before_CImage', null);
if (is_callable($hookBeforeCImage)) {
verbose("hookBeforeCImage activated");
$allConfig = $hookBeforeCImage($img, array(
// Options for calculate dimensions
'newWidth' => $newWidth,
'newHeight' => $newHeight,
'aspectRatio' => $aspectRatio,
'keepRatio' => $keepRatio,
'cropToFit' => $cropToFit,
'fillToFit' => $fillToFit,
'crop' => $crop,
'area' => $area,
'upscale' => $upscale,
// Pre-processing, before resizing is done
'scale' => $scale,
'rotateBefore' => $rotateBefore,
'autoRotate' => $autoRotate,
// General processing options
'bgColor' => $bgColor,
// Post-processing, after resizing is done
'palette' => $palette,
'filters' => $filters,
'sharpen' => $sharpen,
'emboss' => $emboss,
'blur' => $blur,
'convolve' => $convolve,
'rotateAfter' => $rotateAfter,
// Output format
'outputFormat' => $outputFormat,
'dpr' => $dpr,
// Other
'postProcessing' => $postProcessing,
));
verbose(print_r($allConfig, 1));
extract($allConfig);
}
/**
* Display image if verbose mode
*/
@@ -4397,7 +4721,7 @@ if ($verbose) {
window.getDetails = function (url, id) {
$.getJSON(url, function(data) {
element = document.getElementById(id);
element.innerHTML = "filename: " + data.filename + "\\nmime type: " + data.mimeType + "\\ncolors: " + data.colors + "\\nsize: " + data.size + "\\nwidth: " + data.width + "\\nheigh: " + data.height + "\\naspect-ratio: " + data.aspectRatio;
element.innerHTML = "filename: " + data.filename + "\\nmime type: " + data.mimeType + "\\ncolors: " + data.colors + "\\nsize: " + data.size + "\\nwidth: " + data.width + "\\nheigh: " + data.height + "\\naspect-ratio: " + data.aspectRatio + ( data.pngType ? "\\npng-type: " + data.pngType : '');
});
}
</script>
@@ -4407,53 +4731,6 @@ EOD;
/**
* Log verbose details to file
*/
if ($verboseFile) {
$img->setVerboseToFile("$cachePath/log.txt");
}
/**
* Set basic options for image processing.
*/
/**
* Prepare a dummy image and use it as source image.
*/
if ($dummyImage === true) {
$dummyDir = getConfig('dummy_dir', $cachePath. "/" . $dummyFilename);
is_writable($dummyDir)
or verbose("dummy dir not writable = $dummyDir");
$img->setSaveFolder($dummyDir)
->setSource($dummyFilename, $dummyDir)
->setOptions(
array(
'newWidth' => $newWidth,
'newHeight' => $newHeight,
'bgColor' => $bgColor,
)
)
->setJpegQuality($quality)
->setPngCompression($compress)
->createDummyImage()
->generateFilename(null, false)
->save(null, null, false);
$srcImage = $img->getTarget();
$imagePath = null;
verbose("src (updated) = $srcImage");
}
/**
* Load, process and output the image
*/

View File

@@ -982,6 +982,13 @@ class CImage
/**
* Add HTTP headers for outputing image.
*/
private $HTTPHeader = array();
/**
* Default background color, red, green, blue, alpha.
*
@@ -1301,12 +1308,21 @@ class CImage
/*
* output to ascii can take som options as an array.
* Output to ascii can take som options as an array.
*/
private $asciiOptions = array();
/*
* Image copy strategy, defaults to RESAMPLE.
*/
const RESIZE = 1;
const RESAMPLE = 2;
private $copyStrategy = NULL;
/**
* Properties, the class is mutable and the method setOptions()
* decides (partly) what properties are created.
@@ -1519,6 +1535,26 @@ class CImage
/**
* Normalize the file extension.
*
* @param string $extension of image file or skip to use internal.
*
* @return string $extension as a normalized file extension.
*/
private function normalizeFileExtension($extension = null)
{
$extension = strtolower($extension ? $extension : $this->extension);
if ($extension == 'jpeg') {
$extension = 'jpg';
}
return $extension;
}
/**
* Download a remote image and return path to its local copy.
*
@@ -2198,6 +2234,14 @@ class CImage
$rotateBefore = $this->rotateBefore ? "_rb{$this->rotateBefore}" : null;
$rotateAfter = $this->rotateAfter ? "_ra{$this->rotateAfter}" : null;
$saveAs = $this->normalizeFileExtension();
$saveAs = $saveAs ? "_$saveAs" : null;
$copyStrat = null;
if ($this->copyStrategy === self::RESIZE) {
$copyStrat = "_rs";
}
$width = $this->newWidth;
$height = $this->newHeight;
@@ -2255,7 +2299,7 @@ class CImage
. $quality . $filters . $sharpen . $emboss . $blur . $palette
. $optimize . $compress
. $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor
. $convolve;
. $convolve . $copyStrat . $saveAs;
return $this->setTarget($file, $base);
}
@@ -2320,6 +2364,7 @@ class CImage
throw new Exception("Could not load image.");
}
/* Removed v0.7.7
if (image_type_to_mime_type($this->fileType) == 'image/png') {
$type = $this->getPngType();
$hasFewColors = imagecolorstotal($this->image);
@@ -2331,14 +2376,15 @@ class CImage
$this->palette = true;
}
}
*/
if ($this->verbose) {
$this->log("Image successfully loaded from file.");
$this->log("### Image successfully loaded from file.");
$this->log(" imageistruecolor() : " . (imageistruecolor($this->image) ? 'true' : 'false'));
$this->log(" imagecolorstotal() : " . imagecolorstotal($this->image));
$this->log(" Number of colors in image = " . $this->colorsTotal($this->image));
$index = imagecolortransparent($this->image);
$this->log(" Detected transparent color = " . ($index > 0 ? implode(", ", imagecolorsforindex($this->image, $index)) : "NONE") . " at index = $index");
$this->log(" Detected transparent color = " . ($index >= 0 ? implode(", ", imagecolorsforindex($this->image, $index)) : "NONE") . " at index = $index");
}
return $this;
@@ -2349,44 +2395,80 @@ class CImage
/**
* Get the type of PNG image.
*
* @param string $filename to use instead of default.
*
* @return int as the type of the png-image
*
*/
private function getPngType()
public function getPngType($filename = null)
{
$pngType = ord(file_get_contents($this->pathToImage, false, null, 25, 1));
$filename = $filename ? $filename : $this->pathToImage;
$pngType = ord(file_get_contents($filename, false, null, 25, 1));
if ($this->verbose) {
$this->log("Checking png type of: " . $filename);
$this->log($this->getPngTypeAsString($pngType));
}
return $pngType;
}
/**
* Get the type of PNG image as a verbose string.
*
* @param integer $type to use, default is to check the type.
* @param string $filename to use instead of default.
*
* @return int as the type of the png-image
*
*/
private function getPngTypeAsString($pngType = null, $filename = null)
{
if ($filename || !$pngType) {
$pngType = $this->getPngType($filename);
}
$index = imagecolortransparent($this->image);
$transparent = null;
if ($index != -1) {
$transparent = " (transparent)";
}
switch ($pngType) {
case self::PNG_GREYSCALE:
$this->log("PNG is type 0, Greyscale.");
$text = "PNG is type 0, Greyscale$transparent";
break;
case self::PNG_RGB:
$this->log("PNG is type 2, RGB");
$text = "PNG is type 2, RGB$transparent";
break;
case self::PNG_RGB_PALETTE:
$this->log("PNG is type 3, RGB with palette");
$text = "PNG is type 3, RGB with palette$transparent";
break;
case self::PNG_GREYSCALE_ALPHA:
$this->Log("PNG is type 4, Greyscale with alpha channel");
$text = "PNG is type 4, Greyscale with alpha channel";
break;
case self::PNG_RGB_ALPHA:
$this->Log("PNG is type 6, RGB with alpha channel (PNG 32-bit)");
$text = "PNG is type 6, RGB with alpha channel (PNG 32-bit)";
break;
default:
$this->Log("PNG is UNKNOWN type, is it really a PNG image?");
$text = "PNG is UNKNOWN type, is it really a PNG image?";
}
return $pngType;
return $text;
}
/**
* Calculate number of colors in an image.
*
@@ -2422,7 +2504,7 @@ class CImage
*/
public function preResize()
{
$this->log("Pre-process before resizing");
$this->log("### Pre-process before resizing");
// Rotate image
if ($this->rotateBefore) {
@@ -2455,6 +2537,39 @@ class CImage
/**
* Resize or resample the image while resizing.
*
* @param int $strategy as CImage::RESIZE or CImage::RESAMPLE
*
* @return $this
*/
public function setCopyResizeStrategy($strategy)
{
$this->copyStrategy = $strategy;
return $this;
}
/**
* Resize and or crop the image.
*
* @return void
*/
public function imageCopyResampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
{
if($this->copyStrategy == self::RESIZE) {
$this->log("Copy by resize");
imagecopyresized($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
} else {
$this->log("Copy by resample");
imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
}
}
/**
* Resize and or crop the image.
*
@@ -2463,7 +2578,7 @@ class CImage
public function resize()
{
$this->log("Starting to Resize()");
$this->log("### Starting to Resize()");
$this->log("Upscale = '$this->upscale'");
// Only use a specified area of the image, $this->offset is defining the area to use
@@ -2523,7 +2638,7 @@ class CImage
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
$imgPreCrop = $this->CreateImageKeepTransparency($this->cropWidth, $this->cropHeight);
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopyresampled($imgPreCrop, $this->image, 0, 0, 0, 0, $this->cropWidth, $this->cropHeight, $this->width, $this->height);
$this->imageCopyResampled($imgPreCrop, $this->image, 0, 0, 0, 0, $this->cropWidth, $this->cropHeight, $this->width, $this->height);
imagecopy($imageResized, $imgPreCrop, 0, 0, $cropX, $cropY, $this->newWidth, $this->newHeight);
}
@@ -2562,7 +2677,7 @@ class CImage
} else {
$imgPreFill = $this->CreateImageKeepTransparency($this->fillWidth, $this->fillHeight);
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopyresampled($imgPreFill, $this->image, 0, 0, 0, 0, $this->fillWidth, $this->fillHeight, $this->width, $this->height);
$this->imageCopyResampled($imgPreFill, $this->image, 0, 0, 0, 0, $this->fillWidth, $this->fillHeight, $this->width, $this->height);
imagecopy($imageResized, $imgPreFill, $posX, $posY, 0, 0, $this->fillWidth, $this->fillHeight);
}
@@ -2608,7 +2723,7 @@ class CImage
}
} else {
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopyresampled($imageResized, $this->image, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->width, $this->height);
$this->imageCopyResampled($imageResized, $this->image, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->width, $this->height);
$this->image = $imageResized;
$this->width = $this->newWidth;
$this->height = $this->newHeight;
@@ -2627,7 +2742,7 @@ class CImage
*/
public function postResize()
{
$this->log("Post-process after resizing");
$this->log("### Post-process after resizing");
// Rotate image
if ($this->rotateAfter) {
@@ -3087,10 +3202,11 @@ class CImage
*/
protected function getTargetImageExtension()
{
// switch on mimetype
if (isset($this->extension)) {
return strtolower($this->extension);
} else {
return image_type_to_extension($this->fileType);
return substr(image_type_to_extension($this->fileType), 1);
}
}
@@ -3119,7 +3235,9 @@ class CImage
is_writable($this->saveFolder)
or $this->raiseError('Target directory is not writable.');
switch($this->getTargetImageExtension()) {
$type = $this->getTargetImageExtension();
$this->Log("Saving image as " . $type);
switch($type) {
case 'jpeg':
case 'jpg':
@@ -3213,8 +3331,6 @@ class CImage
return $this;
}
$alias = $alias . "." . $this->getTargetImageExtension();
if (is_readable($alias)) {
unlink($alias);
}
@@ -3232,11 +3348,28 @@ class CImage
/**
* Add HTTP header for putputting together with image.
*
* @param string $type the header type such as "Cache-Control"
* @param string $value the value to use
*
* @return void
*/
public function addHTTPHeader($type, $value)
{
$this->HTTPHeader[$type] = $value;
}
/**
* Output image to browser using caching.
*
* @param string $file to read and output, default is to use $this->cacheFileName
* @param string $format set to json to output file as json object with details
* @param string $file to read and output, default is to
* use $this->cacheFileName
* @param string $format set to json to output file as json
* object with details
*
* @return void
*/
@@ -3273,6 +3406,10 @@ class CImage
header('Last-Modified: ' . $gmdate . " GMT");
}
foreach($this->HTTPHeader as $key => $val) {
header("$key: $val");
}
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $lastModified) {
if ($this->verbose) {
@@ -3285,8 +3422,16 @@ class CImage
} else {
// Get details on image
$info = getimagesize($file);
!empty($info) or $this->raiseError("The file doesn't seem to be an image.");
$mime = $info['mime'];
$size = filesize($file);
if ($this->verbose) {
$this->log("Last modified: " . $gmdate . " GMT");
$this->log("Last-Modified: " . $gmdate . " GMT");
$this->log("Content-type: " . $mime);
$this->log("Content-length: " . $size);
$this->verboseOutput();
if (is_null($this->verboseFileName)) {
@@ -3294,12 +3439,8 @@ class CImage
}
}
// Get details on image
$info = getimagesize($file);
!empty($info) or $this->raiseError("The file doesn't seem to be an image.");
$mime = $info['mime'];
header('Content-type: ' . $mime);
header("Content-type: $mime");
header("Content-length: $size");
readfile($file);
}
@@ -3340,6 +3481,18 @@ class CImage
$details['aspectRatio'] = round($this->width / $this->height, 3);
$details['size'] = filesize($file);
$details['colors'] = $this->colorsTotal($this->image);
$details['includedFiles'] = count(get_included_files());
$details['memoryPeek'] = round(memory_get_peak_usage()/1024/1024, 3) . " MB" ;
$details['memoryCurrent'] = round(memory_get_usage()/1024/1024, 3) . " MB";
$details['memoryLimit'] = ini_get('memory_limit');
if (isset($_SERVER['REQUEST_TIME_FLOAT'])) {
$details['loadTime'] = (string) round((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']), 3) . "s";
}
if ($details['mimeType'] == 'image/png') {
$details['pngType'] = $this->getPngTypeAsString(null, $file);
}
$options = null;
if (defined("JSON_PRETTY_PRINT") && defined("JSON_UNESCAPED_SLASHES")) {
@@ -3481,7 +3634,7 @@ EOD;
*
*/
$version = "v0.7.6 (2015-10-18)";
$version = "v0.7.7 (2015-10-21)";
@@ -3630,6 +3783,13 @@ verbose("img.php version = $version");
/**
* status - do a verbose dump of the configuration
*/
$status = getDefined('status', true, false);
/**
* Set mode as strict, production or development.
* Default is production environment.
@@ -3651,6 +3811,7 @@ if ($mode == 'strict') {
ini_set('display_errors', 0);
ini_set('log_errors', 1);
$verbose = false;
$status = false;
$verboseFile = false;
} elseif ($mode == 'production') {
@@ -3659,6 +3820,7 @@ if ($mode == 'strict') {
ini_set('display_errors', 0);
ini_set('log_errors', 1);
$verbose = false;
$status = false;
$verboseFile = false;
} elseif ($mode == 'development') {
@@ -4031,6 +4193,19 @@ verbose("bgColor = $bgColor");
/**
* Do or do not resample image when resizing.
*/
$resizeStrategy = getDefined(array('no-resample'), true, false);
if ($resizeStrategy) {
$img->setCopyResizeStrategy($img::RESIZE);
verbose("Setting = Resize instead of resample");
}
/**
* fill-to-fit, ff - affecting the resulting image width, height and resize options
*/
@@ -4100,11 +4275,16 @@ verbose("use cache = $useCache");
* quality, q - set level of quality for jpeg images
*/
$quality = get(array('quality', 'q'));
$qualityDefault = getConfig('jpg_quality', null);
is_null($quality)
or ($quality > 0 and $quality <= 100)
or errorPage('Quality out of range');
if (is_null($quality) && !is_null($qualityDefault)) {
$quality = $qualityDefault;
}
verbose("quality = $quality");
@@ -4113,12 +4293,16 @@ verbose("quality = $quality");
* compress, co - what strategy to use when compressing png images
*/
$compress = get(array('compress', 'co'));
$compressDefault = getConfig('png_compression', null);
is_null($compress)
or ($compress > 0 and $compress <= 9)
or errorPage('Compress out of range');
if (is_null($compress) && !is_null($compressDefault)) {
$compress = $compressDefault;
}
verbose("compress = $compress");
@@ -4370,6 +4554,146 @@ $cachePath = getConfig('cache_path', __DIR__ . '/../cache/');
/**
* Get the cachepath from config.
*/
$cacheControl = getConfig('cache_control', null);
if ($cacheControl) {
verbose("cacheControl = $cacheControl");
$img->addHTTPHeader("Cache-Control", $cacheControl);
}
/**
* Prepare a dummy image and use it as source image.
*/
$dummyDir = getConfig('dummy_dir', $cachePath. "/" . $dummyFilename);
if ($dummyImage === true) {
is_writable($dummyDir)
or verbose("dummy dir not writable = $dummyDir");
$img->setSaveFolder($dummyDir)
->setSource($dummyFilename, $dummyDir)
->setOptions(
array(
'newWidth' => $newWidth,
'newHeight' => $newHeight,
'bgColor' => $bgColor,
)
)
->setJpegQuality($quality)
->setPngCompression($compress)
->createDummyImage()
->generateFilename(null, false)
->save(null, null, false);
$srcImage = $img->getTarget();
$imagePath = null;
verbose("src (updated) = $srcImage");
}
/**
* Display status
*/
if ($status) {
$text = "img.php version = $version\n";
$text .= "PHP version = " . PHP_VERSION . "\n";
$text .= "Running on: " . $_SERVER['SERVER_SOFTWARE'] . "\n";
$text .= "Allow remote images = $allowRemote\n";
$text .= "Cache writable = " . is_writable($cachePath) . "\n";
$text .= "Cache dummy writable = " . is_writable($dummyDir) . "\n";
$text .= "Alias path writable = " . is_writable($aliasPath) . "\n";
$no = extension_loaded('exif') ? null : 'NOT';
$text .= "Extension exif is $no loaded.<br>";
$no = extension_loaded('curl') ? null : 'NOT';
$text .= "Extension curl is $no loaded.<br>";
$no = extension_loaded('gd') ? null : 'NOT';
$text .= "Extension gd is $no loaded.<br>";
if (!$no) {
$text .= print_r(gd_info(), 1);
}
echo <<<EOD
<!doctype html>
<html lang=en>
<meta charset=utf-8>
<title>CImage status</title>
<pre>$text</pre>
EOD;
exit;
}
/**
* Log verbose details to file
*/
if ($verboseFile) {
$img->setVerboseToFile("$cachePath/log.txt");
}
/**
* Hook after img.php configuration and before processing with CImage
*/
$hookBeforeCImage = getConfig('hook_before_CImage', null);
if (is_callable($hookBeforeCImage)) {
verbose("hookBeforeCImage activated");
$allConfig = $hookBeforeCImage($img, array(
// Options for calculate dimensions
'newWidth' => $newWidth,
'newHeight' => $newHeight,
'aspectRatio' => $aspectRatio,
'keepRatio' => $keepRatio,
'cropToFit' => $cropToFit,
'fillToFit' => $fillToFit,
'crop' => $crop,
'area' => $area,
'upscale' => $upscale,
// Pre-processing, before resizing is done
'scale' => $scale,
'rotateBefore' => $rotateBefore,
'autoRotate' => $autoRotate,
// General processing options
'bgColor' => $bgColor,
// Post-processing, after resizing is done
'palette' => $palette,
'filters' => $filters,
'sharpen' => $sharpen,
'emboss' => $emboss,
'blur' => $blur,
'convolve' => $convolve,
'rotateAfter' => $rotateAfter,
// Output format
'outputFormat' => $outputFormat,
'dpr' => $dpr,
// Other
'postProcessing' => $postProcessing,
));
verbose(print_r($allConfig, 1));
extract($allConfig);
}
/**
* Display image if verbose mode
*/
@@ -4397,7 +4721,7 @@ if ($verbose) {
window.getDetails = function (url, id) {
$.getJSON(url, function(data) {
element = document.getElementById(id);
element.innerHTML = "filename: " + data.filename + "\\nmime type: " + data.mimeType + "\\ncolors: " + data.colors + "\\nsize: " + data.size + "\\nwidth: " + data.width + "\\nheigh: " + data.height + "\\naspect-ratio: " + data.aspectRatio;
element.innerHTML = "filename: " + data.filename + "\\nmime type: " + data.mimeType + "\\ncolors: " + data.colors + "\\nsize: " + data.size + "\\nwidth: " + data.width + "\\nheigh: " + data.height + "\\naspect-ratio: " + data.aspectRatio + ( data.pngType ? "\\npng-type: " + data.pngType : '');
});
}
</script>
@@ -4407,53 +4731,6 @@ EOD;
/**
* Log verbose details to file
*/
if ($verboseFile) {
$img->setVerboseToFile("$cachePath/log.txt");
}
/**
* Set basic options for image processing.
*/
/**
* Prepare a dummy image and use it as source image.
*/
if ($dummyImage === true) {
$dummyDir = getConfig('dummy_dir', $cachePath. "/" . $dummyFilename);
is_writable($dummyDir)
or verbose("dummy dir not writable = $dummyDir");
$img->setSaveFolder($dummyDir)
->setSource($dummyFilename, $dummyDir)
->setOptions(
array(
'newWidth' => $newWidth,
'newHeight' => $newHeight,
'bgColor' => $bgColor,
)
)
->setJpegQuality($quality)
->setPngCompression($compress)
->createDummyImage()
->generateFilename(null, false)
->save(null, null, false);
$srcImage = $img->getTarget();
$imagePath = null;
verbose("src (updated) = $srcImage");
}
/**
* Load, process and output the image
*/

File diff suppressed because one or more lines are too long

View File

@@ -25,8 +25,11 @@ window.CImage = (function() {
input2 = document.getElementById("input2"),
input3 = document.getElementById("input3"),
input4 = document.getElementById("input4"),
input5 = document.getElementById("input5"),
input6 = document.getElementById("input6"),
details = document.getElementById("viewDetails"),
stack = document.getElementById("stack"),
bg = document.getElementById("bg"),
permalink = document.getElementById("permalink");
link = "?";
@@ -34,8 +37,11 @@ window.CImage = (function() {
link += "input2=" + encodeURIComponent(input2.value) + "&";
link += "input3=" + encodeURIComponent(input3.value) + "&";
link += "input4=" + encodeURIComponent(input4.value) + "&";
link += "input5=" + encodeURIComponent(input5.value) + "&";
link += "input6=" + encodeURIComponent(input6.value) + "&";
link += "json=" + encodeURIComponent(details.checked) + "&";
link += "stack=" + encodeURIComponent(stack.checked);
link += "stack=" + encodeURIComponent(stack.checked) + "&";
link += "bg=" + encodeURIComponent(bg.checked);
permalink.href = link;
}
@@ -69,7 +75,7 @@ window.CImage = (function() {
area.classList.remove("hidden");
$.getJSON(this.value + "&json", function(data) {
json.innerHTML = "filename: " + data.filename + "\ncolors: " + data.colors + "\nsize: " + data.size + "\nwidth: " + data.width + "\nheigh: " + data.height + "\naspect-ratio: " + data.aspectRatio;
json.innerHTML = "filename: " + data.filename + "\ncolors: " + data.colors + "\nsize: " + data.size + "\nwidth: " + data.width + "\nheigh: " + data.height + "\naspect-ratio: " + data.aspectRatio + "\npng-type: " + data.pngType;
})
.fail(function() {
json.innerHTML = "Details not available."
@@ -95,14 +101,19 @@ window.CImage = (function() {
input2 = document.getElementById("input2"),
input3 = document.getElementById("input3"),
input4 = document.getElementById("input4"),
input5 = document.getElementById("input5"),
input6 = document.getElementById("input6"),
details = document.getElementById("viewDetails"),
stack = document.getElementById("stack"),
bg = document.getElementById("bg"),
buttons = document.getElementById("buttonWrap");
input1.addEventListener("change", compareLoadImage);
input2.addEventListener("change", compareLoadImage);
input3.addEventListener("change", compareLoadImage);
input4.addEventListener("change", compareLoadImage);
input5.addEventListener("change", compareLoadImage);
input6.addEventListener("change", compareLoadImage);
// Toggle json
details.addEventListener("change", function() {
@@ -129,6 +140,23 @@ window.CImage = (function() {
details.dispatchEvent(myEvent);
}
// Toggle background color
bg.addEventListener("change", function() {
var elements = document.querySelectorAll(".area");
forEach(elements, function (index, element) {
element.classList.toggle("invert");
});
});
// Check background
if (options.bg === true) {
bg.setAttribute("checked", "checked");
bg.classList.toggle("invert");
myEvent = new CustomEvent("change");
bg.dispatchEvent(myEvent);
}
// Toggle stack
stack.addEventListener("change", function() {
var element,
@@ -200,11 +228,15 @@ window.CImage = (function() {
input2.value = options.input2 || null;
input3.value = options.input3 || null;
input4.value = options.input4 || null;
input5.value = options.input5 || null;
input6.value = options.input6 || null;
compareLoadImage.call(input1);
compareLoadImage.call(input2);
compareLoadImage.call(input3);
compareLoadImage.call(input4);
compareLoadImage.call(input5);
compareLoadImage.call(input6);
console.log(options);
}