Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Black background on resize/rotate for transparent images #236
$img = new \claviska\SimpleImage(); $img ->fromFile('png-32.png') ->thumbnail(100, 80) ->toFile('thumbnail.png');
SimpleImage: latest (3.3.3)
PHP version: PHP 7.2.12 (cli) (built: Nov 6 2018 15:26:22) ( NTS )
GD library Version: 2.2.5
local setup works:
It works like expected on my localhost with Xampp, PHP 7.2 and
GD Version: bundled (2.1.0 compatible)
I found a code snippet in SimpleImage for transparent gif files, modified it a bit and added it to the
What I really want to do:
This was referenced
Nov 22, 2018
This looks good at a glance, but I'd really like to get some more feedback from other users before making this change to the
In the past, I've fixed edge cases like this that ended up created problems for existing users. The GD transparency issue has been a game of whack-a-mole. (I think this is an area where tests could really help.)
I understand... and I never used gd or SimpleImage before. So I don't know, what could be possible in certain scenarios. I read a few issues, digged a bit in the code and just found my simple fix.
It looks like the issue could be here with a fix for the next gd release (2.2.6):
So maybe it would be better to check against the gd version instead of gif/png... pseudo code:
Do you have an overview about working and not working gd versions?
I don't, and unfortunately this is exactly why PHP+GD is a pain to work with:
So not all "2.2.6" versions are the same. Plus, as your host stated, it's not exactly the easiest thing to pick the GD version you want to use with PHP so that makes things even harder to test.
I did some research...
There is hope, but not much, that libgd will be added to the php dependencies instead of bundling it. So maybe it's possible to have ONE gd version in the future.
I found some interesting constants to check the version and I wrote a simple test file. The test said, the crop function doesn't work with gif files, too. So my PR is not complete yet.
left: Xampp, right: remote, specs like above
content of testfile:
<!doctype html> <html><head></head><body> <?php require_once('SimpleImage.php'); $img = new \claviska\SimpleImage(); $img->fromFile('stripes.png'); $img->crop(10, 10, 40, 40); $img->toFile('thumb.png'); $img = new \claviska\SimpleImage(); $img->fromFile('stripes.gif'); $img->crop(10, 10, 40, 40); $img->toFile('thumb.gif'); // echo '<pre>' . print_r(get_defined_constants(), true) . '</pre>'; // echo '<pre>' . print_r(gd_info(), true) . '</pre>'; echo "PHP_VERSION:" . '<pre>' . print_r(PHP_VERSION, true) . '</pre>'; echo "PHP_OS:" . '<pre>' . print_r(PHP_OS, true) . '</pre>'; echo "gd_info()['GD Version']:" . '<pre>' . print_r(gd_info()['GD Version'], true) . '</pre>'; echo "GD_BUNDLED:" . '<pre>' . print_r(GD_BUNDLED, true) . '</pre>'; echo "GD_VERSION:" . '<pre>' . print_r(GD_VERSION, true) . '</pre>'; ?> <p>command:</p> <pre>$img->crop(10, 10, 40, 40);</pre> <div><p>png</p> <img src="stripes.png"> <img src="thumb.png"> </div> <div><p>gif</p> <img src="stripes.gif"> <img src="thumb.gif"> </div> </body></html>
Now I'm not sure, what to do next. My goal is to fix (all) transparent gif and png issues - at least in the
Everything I know about gd is what I read about it today and 4 days ago. This is probably not enough to write a consistent version check. Adding a check for gif and png in the crop function would be easy. I can do some more tests with other functions, too. But I'm very limited to a small set of test hosts.
Can you point me in a direction, please? Otherwise I would try to write a workaround for my specific needs and wait/hope for a fix in an upcoming PHP version with libgd 2.2.6.
I wrote a simple test file here: https://github.com/raffaelj/SimpleImageTest/
The tests are with the original lib without my modification to crop. The code should be self-explanatory.
Just add a new line to the test array
$tests = [ // ['method' => ['arg1', 'arg2'] ], ['crop' => [10, 10, 40, 40]], ['rotate' => [45, 'green']], ['resize' => [40, 80]], ['thumbnail' => [60, 60, 'center']], ['sketch' => ], ];
or add different images to the input directory.
Have a look at the screenshots. The results are weird...
I don't get it...
I wish I could...I've been dealing with this one and off for years. Sometimes, I can reproduce it and fix it (and it usually ends up bungling somebody else's version). Other times, I can't reproduce it at all regardless of the version. I've come to the conclusion that it's something to do with the way PHP bundles GD, but I don't know enough about the internals to even guess.
It's gotten to the point where we have a reasonably high effectiveness, but there's always another edge case popping up.
If we can't find a proper fix, my suggestion is to use the library as-is and, in your own code, add a method that works for your particular instance. You won't be able to chain it, but at least 1) it will work and 2) you won't have to rely on a modified version of the library. Just make sure it returns a SimpleImage object and you should be fine.
I updated the test repo. Now the output is a bit better and I added two more screenshots from different hosts. I also started a call in the Cockpit Communitiy Forum to help with tests on different hosts. So hopefully you have a base to work with soon.
It shouldn't be too hard to write a fix for Cockpit (on my instance). It uses only
added a commit
Nov 29, 2018
I wrote some more for multiple edge cases... libgd is annoying. Everytime I thought, it would work, another image had artefacts or was completely empty.
So obviously crop and resize have to work in harmony with 1bit and 8bit transparent gifs and sometimes only for bundled/non-bundled versions.
Here are the screenshots from my latest commit. It looks promising.
Works for me. What do you think?
I gave it another try and now I think, I'm on the right way.
I added some checks to skip the copy-to-new-image process when it's not necessary.
I also updated the test repo with gif files with all bitrates. The complicated ones are
first one on localhost with bundled gd, second on remote with libgd
I digged again into the code and I want to share my conclusions and theories.
Gif files don't have alpha channels, they have one color in the palette, which is used as alpha. So they can't be handled like png files
A theory, why rotate leads to losing transparency: If you rotate a black rectangle, the edges turn gray and the whole color palette moves/gets bigger. So the position of the original transparent pixel moves, too. Not sure about this, but I realized a difference when rotating a black square with Illustrator and exporting it. The color palette was bigger with a few gray values.
I found a very simple gd image class to crop and resize and I wanted to know, how the author fixed the gif transparency issue (docs).
It looks nice, crop and resize work on bundled and libgd. But it turns black when calling crop and resize in one run. It also loses transparency with 1bit-transparent-white gif files.
I tried a rewrite with this approach, fixed the 1bit-white-bug - and lost the transparency in thumbnails again (crop + resize = 2x truecolorimage = weird_imagecolortransparent).
It was very interesting to learn a lot about the gd extension and about transparent gif files.
@claviska Nice work. Your library has a lot of useful functions.
It is really frustrating. Everytime I think, it works - the images on the other host have artefacts or turn black. So - it was interesting, but I have to go now and search for another workaround instead to display my transparent thumbnails on a non-bundled system.