3

I need to trim an image such that the transparent area around the image is removed. However, the image has some inner transparent area also which is getting colored on running the following function:

$image = imagecreatefrompng('path/to/image.png');
$trimmed = imagecropauto($image, IMG_CROP_DEFAULT); 

imagepng($trimmed);

The above code is able to trim the outer transparent area, but the inner transparent area is also getting affected. How to trim only the outer area, similar to how Photoshop's trim option works on images?

Expected result

Current result

Original image is available at https://yp-media.s3.amazonaws.com/Designs_Inners_and_Outers/Cushions/Inners/test_design.png.

(Stackoverflow converts/transform the image when adding it to the question, which looses the transparency. See below:)

Original Image

Progman
  • 16,827
  • 6
  • 33
  • 48
dc09
  • 386
  • 2
  • 17
  • If you save the image as a jpeg (After completing the Crop action), transparent dots should remain white. Did this method work for you? – DarkShade May 20 '23 at 12:10
  • I have added images showing the expected result and current result. I need to save as png as I need transparency for further image processing. – dc09 May 20 '23 at 12:12
  • Original image can be accessed here - https://yp-media.s3.amazonaws.com/Designs_Inners_and_Outers/Cushions/Inners/test_design.png – dc09 May 20 '23 at 12:26
  • 1
    I have added the original image, but it is automatically getting converted to jpg on uploading to stackoverflow. – dc09 May 20 '23 at 12:37
  • Issue is reproducible with PHP 8.1.16, GD Version => bundled (2.1.0 compatible), libJPEG Version => 6b, libPNG Version => 1.6.39 – Progman May 20 '23 at 16:04
  • @F.Müller When the original PNG file gets uploaded to imgur via the image upload widget of the editor, it gets converted to a JPG file (for whatever reason). – Progman May 20 '23 at 18:00
  • @Progman How and why would they do that? The other images are PNG's too - just hover over them or click on them and see for yourself. PNG is a different format than JPG it would mean losing data. – F. Müller May 20 '23 at 18:03
  • @F.Müller imgur might convert the image from PNG to JPG because of the size, see https://stackoverflow.com/questions/71639217/imgur-changes-image-format and https://imgur.userecho.com/en/communities/1/topics/107-png-file-changes-to-jpg-when-uploaded – Progman May 20 '23 at 18:27
  • @Progman Maybe, but op uploaded other png's also from imgur so ... who knows. It must have been the size (the file was ~2.5k X 2.5k pixels in size, so ...) - I see no other reason for this. Anyway, can you test the updated solution again? It must work. Please prove me wrong. – F. Müller May 20 '23 at 18:29
  • 1
    Just checked https://help.imgur.com/hc/en-us/articles/115000083326-What-files-can-I-upload-Is-there-a-size-limit- and it mentions, that (anonymous) images over 1MB get compressed, most likely to a JPG file. The other PNG files in this question are smaller, but the original `test_design.png` PNG file has a size of 1.5MB, so it gets compressed/changed. – Progman May 20 '23 at 18:34
  • @Progman Okay, so there we have it. Fair enough. Anyway, please have a look at the updated code and see if it works for you now - if you have any more details why it does not work for you - please let me know. – F. Müller May 20 '23 at 18:39
  • @dc09 Please [edit] your question to include the PHP version and the GD version(s) your host is using. You find these information via `phpinfo()` (check the "gd" section) and/or asking the host provider you are using. – Progman May 20 '23 at 18:49
  • @dc09 The issue seems to be the export of your file (see the updated answer). – F. Müller May 20 '23 at 22:25
  • gd sucks. can you use an alternative like imagemagick? – chiliNUT May 21 '23 at 01:05

1 Answers1

0

TLDR; Your PNG has been exported using a Palette (e.g. 256 colors) to reduce the overall file size. It is possible that the transparency information may not be preserved accurately. This is because the palette-based color reduction technique is primarily designed for preserving color information and not transparency. To ensure that transparency is maintained, it is generally recommended to export PNG images with full color support (32-bit RGBA) instead of using a palette with limited colors.

comparison

You may try the RGBA format and the code that you find further down below.


Disclaimer: I'm using PHP 8.1.6 along with libPNG: 1.6.37 on macOS (Intel, Ventura 13.2.1 (22D68)) and it works just fine.

Preconditions:

I've ensured that your frames are 100% transparent first in Affinity Photo I've manually deleted these areas with a flood-fill tool. I've also exported the image with the default settings. If I use your image, I'll end up with an alpha value of 229.

reconstruct

Display in browser / mime-type:

The browser adds some styles and classes to the image when rendering with header('Content-Type: image/png') (default styles in the browser). We have only requested the browser to render the isolated image, but the browser adds some more stuff to make it look "good" - see the DOM in the screenshots.

In Firefox for example you can see this "transparent" class that is added - it adds a background (I have disabled this in the first screenshot). If we change it to red you can see that the background now is red so the frames are red too because they are 100% transparent.

preview-1 preview-2

So how do we fix this? Depends on what you are trying to do. Basically, you can just render your own HTML-Document instead of using the mime-type: image/png so there is no browser default.

E.g.

<?php

// ini_set("display_errors", 1);
// error_reporting(-1);

$image = imagecreatefrompng('./test-img.png');
imagealphablending($image, true); // Make sure the alpha channel is supported

$trimmed = imagecropauto($image, IMG_CROP_SIDES);

$generatedImagePath = './test-img-generated.png';

if ($trimmed !== false) {
  imagesavealpha($trimmed, true); // Make sure the alpha channel gets exported when you save it
  imagepng($trimmed, $generatedImagePath);
} else {
  echo "Failed to crop the image.";
}

imagedestroy($image);  // Frees memory prior to PHP 8.0
imagedestroy($trimmed); // ...

?>
<!DOCTYPE html>
<html>
<body style="background: transparent; background-image: url('./pattern.jpg')">
  <img src="<?php echo $generatedImagePath; ?>" style="width: 480px; aspect-ratio: 1;">
</body>
</html>

Renders:

prove

F. Müller
  • 3,969
  • 8
  • 38
  • 49
  • 1
    This is still giving the same output as shown in the question - the sides are getting trimmed but the inner transparent area is also getting colored. Also, I understand that the dotted pattern is jus a representation, the output with your code and my initial code is leading to inner transparent area getting colored. – dc09 May 20 '23 at 14:17
  • @dc09 I've added some images and additional explanations to the solution based on my previous comment. – F. Müller May 20 '23 at 15:26
  • @F.Müller Could you add the PHP version and GD version(s) you are using to your answer? I tried the same code and it still generates the faulty image as described by the OP. – Progman May 20 '23 at 16:23
  • @Progman As I said it is based on the browser styles you cannot change it unless you render a HTML document where you include it. I use PHP 8.1 with the built-in GD lib. – F. Müller May 20 '23 at 16:26
  • @F.Müller I tried your solution and it does not work *on my host* (linux 5.10.74-gentoo). I'm running PHP 8.1.16, GD Version => bundled (2.1.0 compatible), libJPEG Version => 6b, libPNG Version => 1.6.39 (and I guess with libgd 2.3.3-r3). But that is my host and other hosts have different versions. Maybe OP has a similar host setting. That's why I asked for a detailed listing of the specific versions you are using, maybe the problem might be due to different lib versions or even a different OS (if that is relevant at all). – Progman May 20 '23 at 18:44
  • @Progman Uhm what do you mean by "does not work on my host". What is the issue then? Does it throw errors when you add the two commented lines? When you right-click on the file and download it - does it have transparency when you open it in an image-editor? Did you try the updated version of my code or the old one? I'm on macOS, PHP 8.1.6, GD Version bundled (2.1.0 compatible), libJPEG Version => 9 compatible, libPNG Version => 1.6.37 – F. Müller May 20 '23 at 18:53
  • @F.Müller It produce the same faulty image described by the OP. I tested both versions. – Progman May 20 '23 at 18:58
  • @Progman Am I understanding you correctly? So it is not only a visual issue for you, but when you download the image, it also has no transparency to it when you open it with GIMP, Photoshop, Affinity Photo, etc.? If so, you might be correct with the assumption that it could be a version issue or bug. – F. Müller May 20 '23 at 19:03
  • @F.Müller actually, GIMP as well as KolourPaint, shows an alpha value of 229 from the previous transparent areas of the original image, after your code or OPs code is used, see https://imgur.com/a/jKGWg6Z. Not sure what's going on here... – Progman May 20 '23 at 19:17
  • @F.Müller It is unclear what you are talking about. The inner areas/frames **are** already empty/transparent, see https://imgur.com/a/8Rz6sPl (not sure why imgur detected my screenshot as "mature"...). What/where have you deleted something? Where was the original image not 100% transparent? – Progman May 20 '23 at 21:08
  • @Progman My bad, that seems not to be the issue. It must be the export of Affinity Photo that fixed the alpha for me. I've uploaded the file here: https://file.io/RTi4Hjg0gud1 can you try and see if it makes any difference? – F. Müller May 20 '23 at 21:38
  • @Progman The original uses a different export format: https://imgur.com/498QQcx which is "Palette" instead of "RGB with Alpha". – F. Müller May 20 '23 at 21:50