Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1461b6d
Combined the dominant_color_get_dominant_color() and the dominant_col…
pbearne Jun 16, 2022
d7c2b9d
Combined the dominant_color_get_dominant_color() and the dominant_col…
pbearne Jun 16, 2022
d58f2b4
Combined the dominant_color_get_dominant_color() and the dominant_col…
pbearne Jun 16, 2022
2158a17
Update modules/images/dominant-color/load.php
pbearne Jun 20, 2022
198532c
Force hex to 6 characters
spacedmonkey Jun 22, 2022
a6ab609
Merge branch 'trunk' into INITS-976-Avoid_duplicate_execution_of_sett…
spacedmonkey Jun 22, 2022
37b3222
changed code to return WP_error in has_transparency or dominant_color…
pbearne Jun 24, 2022
b01ba33
Update modules/images/dominant-color/load.php
pbearne Jun 24, 2022
c6f0f2b
Update modules/images/dominant-color/load.php
pbearne Jun 24, 2022
ec6e41a
Update modules/images/dominant-color/load.php
pbearne Jun 24, 2022
57ab283
Update modules/images/dominant-color/load.php
pbearne Jun 24, 2022
43e3dd1
Update modules/images/dominant-color/load.php
pbearne Jun 24, 2022
e4b2e03
Update modules/images/dominant-color/load.php
pbearne Jun 24, 2022
1d2e440
Removed magic code for simpler str_pad function
pbearne Jun 24, 2022
43b5268
Improve unit tests.
spacedmonkey Jun 27, 2022
e75e578
Add get_hex_from_rgb function.
spacedmonkey Jun 27, 2022
83d2cce
Remove test for now.
spacedmonkey Jun 27, 2022
3018d7e
Return wp_error.
spacedmonkey Jun 27, 2022
4e130cb
Change message.
spacedmonkey Jun 27, 2022
043feb2
Check to see if the method exists.
spacedmonkey Jun 27, 2022
879a43f
Improve testing.
spacedmonkey Jun 27, 2022
a9acc67
Ignore on multisite.
spacedmonkey Jun 27, 2022
e5f2054
Change function name.
spacedmonkey Jun 28, 2022
14073b6
Apply suggestions from code review
spacedmonkey Jun 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,15 @@ public function get_dominant_color() {
$shorted_image = imagecreatetruecolor( 1, 1 );
imagecopyresampled( $shorted_image, $this->image, 0, 0, 0, 0, 1, 1, imagesx( $this->image ), imagesy( $this->image ) );

$hex = dechex( imagecolorat( $shorted_image, 0, 0 ) );

if ( strlen( $hex ) < 6 ) {
$rgb = imagecolorat( $shorted_image, 0, 0 );
$r = ( $rgb >> 16 ) & 0xFF;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$g = ( $rgb >> 8 ) & 0xFF;
$b = $rgb & 0xFF;
$hex = get_hex_from_rgb( $r, $g, $b );
if ( ! $hex ) {
return new WP_Error( 'image_editor_dominant_color_error', __( 'Dominant color detection failed.', 'performance-lab' ) );
}

return $hex;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ public function get_dominant_color() {
try {
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
// The logic here is resize the image to 1x1 pixel, then get the color of that pixel.
$this->image->setImageColorspace( Imagick::COLORSPACE_RGB );
$this->image->setImageFormat( 'RGB' );
$this->image->resizeImage( 1, 1, Imagick::FILTER_LANCZOS, 1 );
$pixel = $this->image->getImagePixelColor( 0, 0 );
$color = $pixel->getColor();
$hex = get_hex_from_rgb( $color['r'], $color['g'], $color['b'] );
if ( ! $hex ) {
return new WP_Error( 'image_editor_dominant_color_error', __( 'Dominant color detection failed.', 'performance-lab' ) );
}

return dechex( $color['r'] ) . dechex( $color['g'] ) . dechex( $color['b'] );
return $hex;
} catch ( Exception $e ) {
/* translators: %s is the error message. */
return new WP_Error( 'image_editor_dominant_color_error', sprintf( __( 'Dominant color detection failed: %s', 'performance-lab' ), $e->getMessage() ) );
Expand All @@ -63,8 +65,32 @@ public function has_transparency() {
}

try {
// Check if the image has an alpha channel if true, set to has_transparent to true.
return (bool) $this->image->getImageAlphaChannel();
/*
* Check if the image has an alpha channel if false, then it can't have transparency so return early.
*
* Note that Imagick::getImageAlphaChannel() is only available if Imagick
* has been compiled against ImageMagick version 6.4.0 or newer.
*/
if ( is_callable( array( $this->image, 'getImageAlphaChannel' ) ) ) {
if ( ! $this->image->getImageAlphaChannel() ) {
return false;
}
}

// Walk through the pixels and look transparent pixels.
$w = $this->image->getImageWidth();
$h = $this->image->getImageHeight();
for ( $x = 0; $x < $w; $x++ ) {
for ( $y = 0; $y < $h; $y++ ) {
$pixel = $this->image->getImagePixelColor( $x, $y );
$color = $pixel->getColor();
if ( $color['a'] > 0 ) {
return true;
}
}
}
return false;

} catch ( Exception $e ) {
/* translators: %s is the error message */
return new WP_Error( 'image_editor_has_transparency_error', sprintf( __( 'Transparency detection failed: %s', 'performance-lab' ), $e->getMessage() ) );
Expand Down
137 changes: 92 additions & 45 deletions modules/images/dominant-color/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,15 @@
* @return array $metadata The attachment metadata.
*/
function dominant_color_metadata( $metadata, $attachment_id ) {
if ( ! wp_attachment_is_image( $attachment_id ) ) {
return $metadata;
}

$dominant_color = dominant_color_get_dominant_color( $attachment_id );
if ( ! is_wp_error( $dominant_color ) && ! empty( $dominant_color ) ) {
$metadata['dominant_color'] = $dominant_color;
}
$dominant_color_data = _dominant_color_get_dominant_color_data( $attachment_id );
if ( ! is_wp_error( $dominant_color_data ) ) {
if ( isset( $dominant_color_data['dominant_color'] ) ) {
$metadata['dominant_color'] = $dominant_color_data['dominant_color'];
}

$has_transparency = dominant_color_has_transparency( $attachment_id );
if ( ! is_wp_error( $has_transparency ) ) {
$metadata['has_transparency'] = $has_transparency;
if ( isset( $dominant_color_data['has_transparency'] ) ) {
$metadata['has_transparency'] = $dominant_color_data['has_transparency'];
}
}

return $metadata;
Expand Down Expand Up @@ -255,43 +252,15 @@ function dominant_color_set_image_editors() {
* Computes the dominant color of the given attachment image.
*
* @since 1.2.0
* @access private
*
* @param int $attachment_id The attachment ID.
* @return string|WP_Error The dominant color of the image, or WP_Error on error.
* @return array|WP_Error Array with the dominant color and has transparency values or WP_Error on error.
*/
function dominant_color_get_dominant_color( $attachment_id ) {
$file = wp_get_attachment_file_path( $attachment_id );
if ( ! $file ) {
$file = get_attached_file( $attachment_id );
}
add_filter( 'wp_image_editors', 'dominant_color_set_image_editors' );
$editor = wp_get_image_editor( $file );
remove_filter( 'wp_image_editors', 'dominant_color_set_image_editors' );

if ( is_wp_error( $editor ) ) {
return $editor;
}
if ( ! method_exists( $editor, 'get_dominant_color' ) ) {
return new WP_Error( 'unable_to_find_method', __( 'Unable to find get_dominant_color method', 'performance-lab' ) );
}

$dominant_color = $editor->get_dominant_color();
if ( is_wp_error( $dominant_color ) ) {
return $dominant_color;
function _dominant_color_get_dominant_color_data( $attachment_id ) {
if ( ! wp_attachment_is_image( $attachment_id ) ) {
return new WP_Error( 'no_image_found', __( 'Unable to load image.', 'performance-lab' ) );
}

return $dominant_color;
}

/**
* Computes whether the given attachment image has transparency.
*
* @since 1.2.0
*
* @param int $attachment_id The attachment ID.
* @return bool|WP_Error True if the color has transparency or WP_Error on error.
*/
function dominant_color_has_transparency( $attachment_id ) {
$file = wp_get_attachment_file_path( $attachment_id );
if ( ! $file ) {
$file = get_attached_file( $attachment_id );
Expand All @@ -303,15 +272,27 @@ function dominant_color_has_transparency( $attachment_id ) {
if ( is_wp_error( $editor ) ) {
return $editor;
}

if ( ! method_exists( $editor, 'has_transparency' ) ) {
return new WP_Error( 'unable_to_find_method', __( 'Unable to find has_transparency method', 'performance-lab' ) );
}
$has_transparency = $editor->has_transparency();
if ( is_wp_error( $has_transparency ) ) {
return $has_transparency;
}
$dominant_color_data['has_transparency'] = $has_transparency;

if ( ! method_exists( $editor, 'get_dominant_color' ) ) {
return new WP_Error( 'unable_to_find_method', __( 'Unable to find get_dominant_color method', 'performance-lab' ) );
}

$dominant_color = $editor->get_dominant_color();
if ( is_wp_error( $dominant_color ) ) {
return $dominant_color;
}
$dominant_color_data['dominant_color'] = $dominant_color;

return $has_transparency;
return $dominant_color_data;
}

/**
Expand Down Expand Up @@ -339,3 +320,69 @@ function wp_get_attachment_file_path( $attachment_id, $size = 'medium' ) {

return $filepath;
}

/**
* Gets the dominant color for an image attachment.
*
* @since n.e.x.t
*
* @param int $attachment_id Attachment ID for image.
* @return string|null Hex value of dominant color or null if not set.
*/
function dominant_color_get_dominant_color( $attachment_id ) {
if ( ! wp_attachment_is_image( $attachment_id ) ) {
return null;
}
$image_meta = wp_get_attachment_metadata( $attachment_id );
if ( ! is_array( $image_meta ) ) {
return null;
}

if ( ! isset( $image_meta['dominant_color'] ) ) {
return null;
}

return $image_meta['dominant_color'];
}

/**
* Returns whether an image attachment has transparency.
*
* @since n.e.x.t
*
* @param int $attachment_id Attachment ID for image.
* @return bool|null Whether the image has transparency, or null if not set.
*/
function dominant_color_has_transparency( $attachment_id ) {
$image_meta = wp_get_attachment_metadata( $attachment_id );
if ( ! is_array( $image_meta ) ) {
return null;
}

if ( ! isset( $image_meta['has_transparency'] ) ) {
return null;
}

return $image_meta['has_transparency'];
}


/**
* Get Hex color from RGB.
*
* @since n.e.x.t
*
* @param int $red Red 0-255.
* @param int $green Green 0-255.
* @param int $blue Blue 0-255.
*
* @return string|null Hex color or null if error.
*/
function get_hex_from_rgb( $red, $green, $blue ) {
$range = range( 0, 255 );
if ( ! in_array( $red, $range, true ) || ! in_array( $green, $range, true ) || ! in_array( $blue, $range, true ) ) {
return null;
}

return sprintf( '%02x%02x%02x', $red, $green, $blue );
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,60 @@ static function () {
100
);
}

/**
* Test if the function returns the correct color.
*
* @dataProvider provider_get_dominant_color
*
* @covers Dominant_Color_Image_Editor_GD::get_dominant_color
* @covers Dominant_Color_Image_Editor_GD::get_dominant_color
*/
public function test_get_dominant_color( $image_path, $expected_color, $is_wp_error ) {
public function test_get_dominant_color( $image_path, $expected_color, $expected_transparency ) {

$attachment_id = $this->factory->attachment->create_upload_object( $image_path );
wp_maybe_generate_attachment_metadata( get_post( $attachment_id ) );
$color = dominant_color_get_dominant_color( $attachment_id );
if ( ! $is_wp_error ) {
$this->assertContains( $color, $expected_color );
} else {
$this->assertInstanceOf( 'WP_Error', $color );
}

$dominant_color_data = _dominant_color_get_dominant_color_data( $attachment_id );

$this->assertContains( $dominant_color_data['dominant_color'], $expected_color );
$this->assertSame( $dominant_color_data['has_transparency'], $expected_transparency );
}

/**
* Test if the function returns the correct color.
*
* @dataProvider provider_get_has_transparency
* @dataProvider provider_get_dominant_color_invalid_images
*
* @covers ::dominant_color_has_transparency
* @group ms-excluded
*
* @covers Dominant_Color_Image_Editor_GD::get_dominant_color
*/
public function test_dominant_color_get_has_transparency( $image_path, $expected_tranasparency ) {
public function test_get_dominant_color_invalid( $image_path, $expected_color, $expected_transparency ) {

$attachment_id = $this->factory->attachment->create_upload_object( $image_path );
wp_maybe_generate_attachment_metadata( get_post( $attachment_id ) );
$this->assertEquals( $expected_tranasparency, dominant_color_has_transparency( $attachment_id ) );

$dominant_color_data = _dominant_color_get_dominant_color_data( $attachment_id );

$this->assertWPError( $dominant_color_data );
$this->assertStringContainsString( 'image_no_editor', $dominant_color_data->get_error_code() );
}

/**
* Test if the function returns the correct color.
*
* @dataProvider provider_get_dominant_color_none_images
*
* @covers Dominant_Color_Image_Editor_GD::get_dominant_color
*/
public function test_get_dominant_color_none_images( $image_path ) {

$attachment_id = $this->factory->attachment->create_upload_object( $image_path );
wp_maybe_generate_attachment_metadata( get_post( $attachment_id ) );

$dominant_color_data = _dominant_color_get_dominant_color_data( $attachment_id );

$this->assertWPError( $dominant_color_data );
$this->assertStringContainsString( 'no_image_found', $dominant_color_data->get_error_code() );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,57 @@ static function () {
*
* @dataProvider provider_get_dominant_color
*
* @covers Dominant_Color_Image_Editor_GD::get_dominant_color
* @covers Dominant_Color_Image_Editor_GD::get_dominant_color
*/
public function test_get_dominant_color( $image_path, $expected_color, $is_wp_error ) {
public function test_get_dominant_color( $image_path, $expected_color, $expected_transparency ) {

$attachment_id = $this->factory->attachment->create_upload_object( $image_path );
wp_maybe_generate_attachment_metadata( get_post( $attachment_id ) );
$color = dominant_color_get_dominant_color( $attachment_id );
if ( ! $is_wp_error ) {
$this->assertContains( $color, $expected_color );
} else {
$this->assertInstanceOf( 'WP_Error', $color );

$dominant_color_data = _dominant_color_get_dominant_color_data( $attachment_id );

$this->assertContains( $dominant_color_data['dominant_color'], $expected_color );
if ( strpos( $image_path, '.gif' ) ) {
$expected_transparency = true; // all gif have alpha.
}
$this->assertSame( $dominant_color_data['has_transparency'], $expected_transparency );
}

/**
* Test if the function returns the correct color.
*
* @dataProvider provider_get_dominant_color_invalid_images
*
* @group ms-excluded
*
* @covers Dominant_Color_Image_Editor_GD::get_dominant_color
*/
public function test_get_dominant_color_invalid( $image_path, $expected_color, $expected_transparency ) {

$attachment_id = $this->factory->attachment->create_upload_object( $image_path );
wp_maybe_generate_attachment_metadata( get_post( $attachment_id ) );

$dominant_color_data = _dominant_color_get_dominant_color_data( $attachment_id );

$this->assertContains( $dominant_color_data['dominant_color'], $expected_color );
$this->assertSame( $dominant_color_data['has_transparency'], $expected_transparency );
}

/**
* Test if the function returns the correct color.
*
* @dataProvider provider_get_has_transparency
* @dataProvider provider_get_dominant_color_none_images
*
* @covers ::dominant_color_has_transparency
* @covers Dominant_Color_Image_Editor_GD::get_dominant_color
*/
public function test_dominant_color_get_has_transparency( $image_path, $expected_tranasparency ) {
public function test_get_dominant_color_none_images( $image_path ) {

$attachment_id = $this->factory->attachment->create_upload_object( $image_path );
wp_maybe_generate_attachment_metadata( get_post( $attachment_id ) );
$this->assertEquals( $expected_tranasparency, dominant_color_has_transparency( $attachment_id ) );

$dominant_color_data = _dominant_color_get_dominant_color_data( $attachment_id );

$this->assertWPError( $dominant_color_data );
$this->assertStringContainsString( 'no_image_found', $dominant_color_data->get_error_code() );
}
}
Loading