Skip to content

Commit

Permalink
The Image::setOpacity method works much quicker
Browse files Browse the repository at this point in the history
  • Loading branch information
Finesse committed Jan 2, 2017
1 parent f73b320 commit 23043b5
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 45 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ Comments in the code should be written in English.
Please follow ImageTools principles:

* `Image` object is immutable.
* In case of error methods should always throw exceptions, not errors or warnings.
* Methods should always throw exceptions in case of error. Methods mustn't trigger errors or warnings.
6 changes: 3 additions & 3 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Add this to the `composer.json` file:

```json
"require": {
"aiger-team/image-tools": "1.0.*"
"aiger-team/image-tools": "~1.0.7"
}
```

Expand Down Expand Up @@ -107,7 +107,7 @@ $resource = imagecreatetruecolor( 100, 150 );
$image = new Image( $resource );
```

The resource passed to the constructor become an `Image` object own. So the resource can be modified inside the
The resource passed to the constructor becomes an `Image` object own. So the resource can be modified inside the
constructor and the resource will be automatically destroyed on the `Image` object destruction.

### Processing an image
Expand Down Expand Up @@ -142,7 +142,7 @@ details and the list of all methods.

Versions are backward compatible within minor versions. For example versions `1.1.3` and `1.1.5` are backward compatible,
but versions `1.1.3` and `1.2.1` may be not compatible. So we advice you to set specific minor version in the composer
configuration, for example `1.0.*`.
configuration, for example `~1.0.7`.


## License
Expand Down
52 changes: 23 additions & 29 deletions src/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use AigerTeam\ImageTools\Exceptions\FileException;

if ( !defined( 'IMAGETYPE_WEBP' ) ) define( 'IMAGETYPE_WEBP', 117 );
if ( !defined( 'IMAGETYPE_WEBP' )) define( 'IMAGETYPE_WEBP', 117 );

/**
* Class Image
Expand All @@ -17,7 +17,7 @@
* - passing DG resource to the class constructor;
* - calling a method of an ImageFactory object.
*
* @version 1.0.6
* @version 1.0.7
* @author Finesse
* @author maindefine
* @package AigerTeam\ImageTools
Expand Down Expand Up @@ -60,7 +60,7 @@ class Image
protected $isTransparent = false;

/**
* @param resource $bitmap Image DG resource. It becomes this object own. So the resource can be modified and it
* @param resource $bitmap Image DG resource. It becomes this object own. So the resource can be modified here. It
* will be automatically destroyed on this object destruction.
* @param bool $isTransparent Whether image resource has transparent pixels. Not significant argument, it's used
* only when output file format is selected.
Expand Down Expand Up @@ -387,39 +387,30 @@ function rotate( $angle, Array $underlay = null )
*/
function setOpacity( $opacity )
{
if ( !is_numeric( $opacity ) )
if ( !is_numeric( $opacity )) {
throw new \InvalidArgumentException( 'Argument $opacity expected to be number, ' . gettype( $opacity ) . ' given.' );
}

$opacity = max( 0, $opacity );

if ( $opacity == 1 )
if ( $opacity == 1 ) {
return $this;
}

$width = $this->getWidth();
$height = $this->getHeight();
$bitmap = static::copyBitmap( $this->bitmap );

for ( $x = 0; $x < $width; ++$x )
for ( $y = 0; $y < $height; ++$y ) {
$color = imagecolorat( $bitmap, $x, $y );
$transparency = ( $color >> 24 ) & 0x7F;

if ( $transparency == 127 || $opacity > 1 && $transparency == 0 )
continue;

$transparency /= 127;

if ( $opacity < 1 )
$transparency = 1 - (1 - $transparency) * $opacity;
else
$transparency = pow( $transparency, $opacity );
$restLayersOpacity = ceil( $opacity ) - 1;
$firstLayerOpacity = $opacity - $restLayersOpacity;

$color = ( $color & 0xFFFFFF ) | ( (int)round( $transparency * 127 ) << 24 );
imagesetpixel( $bitmap, $x, $y, $color );
}
$bitmap = static::copyBitmap( $this->bitmap );
$transparency = 1 - $firstLayerOpacity;
imagefilter( $bitmap, IMG_FILTER_COLORIZE, 0, 0, 0, 127 * $transparency );

$newImage = static::construct( $bitmap );
$newImage->isTransparent = true;

for ( $i = 0; $i < $restLayersOpacity; ++$i ) {
$newImage = $newImage->insertImage( $this );
}

return $newImage;
}

Expand Down Expand Up @@ -1095,11 +1086,13 @@ protected static function imageType2extension( $type, $includeDot = false )
*/
protected static function copyBitmap( $bitmap )
{
if ( !is_resource( $bitmap ) )
if ( !is_resource( $bitmap )) {
throw new \InvalidArgumentException( 'Argument $bitmap expected to be resource, ' . gettype( $bitmap ) . 'given.' );
}

if ( get_resource_type( $bitmap ) !== 'gd' )
if ( get_resource_type( $bitmap ) !== 'gd' ) {
throw new \InvalidArgumentException( 'The resource from the $bitmap argument is not image resource.' );
}

$width = @imagesx( $bitmap );
$height = @imagesy( $bitmap );
Expand All @@ -1114,8 +1107,9 @@ protected static function copyBitmap( $bitmap )
@imagealphablending( $bitmap2, false );
$result = @imagecopy( $bitmap2, $bitmap, 0, 0, 0, 0, $width, $height );

if ( !$bitmap2 || !$result )
if ( !$bitmap2 || !$result ) {
throw new \Exception( 'Can\'t copy image resource. Perhaps not enough RAM.' );
}

return $bitmap2;
}
Expand Down
24 changes: 12 additions & 12 deletions src/ImageFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*
* Image factory. Creates images by various ways.
*
* @version 1.0.6
* @version 1.0.7
* @author Finesse
* @package AigerTeam\ImageTools
*/
Expand Down Expand Up @@ -75,43 +75,43 @@ public function openFile( $file )
@clearstatcache( true, $file );

// Does file exist?
if ( !file_exists( $file ) || !is_file( $file ) )
if ( !file_exists( $file ) || !is_file( $file ))
throw new FileException( 'Given file doesn\'t exist or not a file.', $file );

// Is it readable?
if ( !is_readable( $file ) )
if ( !is_readable( $file ))
throw new FileException( 'Given file isn\'t readable.', $file );

// Is it image?
$size = getimagesize( $file );
if( $size === false )
throw new ImageFileException( 'Given file isn\'t image.', $file );
if ( $size === false )
throw new ImageFileException( 'Given file isn\'t an image.', $file );

// Retrieve image type
$format = strtolower( substr( $size['mime'], strpos( $size['mime'], '/' ) + 1 ) );
if($format === 'x-ms-bmp')
if ($format === 'x-ms-bmp')
$format = 'wbmp';

// Does function that opens this type exist?
$func = 'imagecreatefrom' . $format;
if( !function_exists( $func ) )
if ( !function_exists( $func ) )
throw new ImageFileException( 'Unknown image type.', $file );

// Open image file
$bitmap = @$func( $file );
if( !$bitmap )
if ( !$bitmap )
throw new ImageFileException( 'Can\'t open image file. Perhaps not enough RAM.', $file );

// Create image object
$image = new Image( $bitmap, in_array( $format, Array( 'png', 'gif' ) ) );

// Rotate non-default oriended JPEG
if(
if (
function_exists( 'exif_read_data' ) &&
is_array( $exif = @exif_read_data( $file, 0, true ) ) &&
isset( $exif[ 'IFD0' ][ 'Orientation' ] )
is_array( $exif = @exif_read_data( $file, 0, true )) &&
isset( $exif[ 'IFD0' ][ 'Orientation' ])
) {
switch( $exif[ 'IFD0' ][ 'Orientation' ] ) {
switch( $exif[ 'IFD0' ][ 'Orientation' ]) {
case 8: $image = $image->rotate( 90 ); break;
case 3: $image = $image->rotate( 180 ); break;
case 6: $image = $image->rotate( -90 ); break;
Expand Down

0 comments on commit 23043b5

Please sign in to comment.