php gd image quality - php

I 'm trying to add text on a specific image. Its working perfectly but the quality of image is low especially for papyrus.ttf font. How can i improve the quality of text in the image. But i need high quality to print the output.
Here is my code.. its very simple.
header("Content-Type: image/jpeg");
$im = imagecreatefromjpeg("cosmos.jpg");
$black = ImageColorAllocate($im, 0, 0, 0);
Imagettftext($im, 14, 0, 10, 15, $black, 'papyrus.ttf', "Corey and Lisa ");
Imagettftext($im, 14, 0, 10, 35, $black, 'papyrus.ttf', " 1994, june");
Imagejpeg($im, '', 100);
ImageDestroy($im);
Download: http://wneeds.com/gdtest.zip

If imageTTFText fails in Quality, the next step to try is ImageFTText(). It uses the FreeType library to render fonts, which usually means significantly better quality. It needs to be installed and compiled into PHP to work, which it most often is. Try calling the function and you'll see whether that is the case.
If that doesn't do, the next step is using ImageMagick either through the command line, or through the appropriate PHP extension. But try Freetype first, it could already be enough.

Related

imagefttext() and imagettftext() giving strange results

I have an issue with getting imagefttext() and imagettftext() working in php.
This is a similar question to imagettftext() not working
however I am not given an error. I will simplify my code here to show what the basis of it is.
I have tried each line below.
No errors:
imagefttext($image2, 20, 0, 0, 20, $white , 'Alien-Encounters-Regular', "testing");
imagefttext($image2, 20, 0, 0, 20, $white , 'Alien-Encounters-Regular.ttf', "testing");
imagefttext($image2, 20, 0, 0, 20, $white , './Alien-Encounters-Regular.ttf', "testing");
imagettftext($image2, 20, 0, 0, 20, $white , 'Alien-Encounters-Regular', "testing");
imagettftext($image2, 20, 0, 0, 20, $white , 'Alien-Encounters-Regular.ttf', "testing");
imagettftext($image2, 20, 0, 0, 20, $white , './Alien-Encounters-Regular.ttf', "testing");
All of the above produce a series of white boxes where there should be a letter. To further troubleshoot I took each line above and uploaded it and tried it. I then changed the "A" in the font file name to "a" and none of them worked telling me this is a Unix based server. (caps matter) Below I'll post a working bit of code that produces an image with text.
imagestring( $image2, 4, 10, 5, "testing" , $white );
I know that FreeType is installed to the server else it would not even give me an image at all throwing an error when I try to use it. I have not tried another method of setting the font file as that is not needed in this case. (It reads the file anyway. Else it would give me an error.)
UPDATE: This is now resolved thanks to Elias, I had a small part of code out of about ~1500 lines of code that was a fragment of old code. This code was imagealphablending($image2, false) and imagettftext() as well as imagefttext() do not work with alphablending off (Set to false.) I removed the code and it now works as expected. See below for how it looks now.
These are some issues which might be relevant:
font file not found
the font file cannot be processed
the blending mode is set incorrect (imagealphablending())

PHP imagettftext() - nothing is displaying

Trying to display a font using the GD library. There is indeed an image there, it's just that theres nothing displaying.
PHP:
header('Content-Type: image/png');
$font = $_GET['font'];
// Create the image
$image = imagecreatetruecolor(400, 30);
// Create some colors
$white = imagecolorallocate($image, 255, 255, 255);
$grey = imagecolorallocate($image, 128, 128, 128);
$black = imagecolorallocate($image, 0, 0, 0);
imagefilledrectangle($image, 0, 0, 399, 29, $white);
// The text to draw
$text = 'The Quick Brown Fox Jumps over the Lazy Dog';
$font = '/Aller/' . $font;
// Add the text
imagettftext($image, 20, 0, 10, 20, $black, $font, $text);
imagepng($image);
HTML:
<img src="fontgen.php?font=Aller_Rg.ttf" alt="" />
The font resides in fonts/Aller/Aller_Rg.tff
What am I doing wrong?
The problem seems to be the $font variable. From the documentation:
Depending on which version of the GD library PHP is using, when fontfile does not begin with a leading / then .ttf will be appended to the filename and the library will attempt to search for that filename along a library-defined font path.
When using versions of the GD library lower than 2.0.18, a space character, rather than a semicolon, was used as the 'path separator' for different font files. Unintentional use of this feature will result in the warning message: Warning: Could not find/open font. For these affected versions, the only solution is moving the font to a path which does not contain spaces.
In many cases where a font resides in the same directory as the script using it the following trick will alleviate any include problems.
<?php
// Set the enviroment variable for GD
putenv('GDFONTPATH=' . realpath('.'));
// Name the font to be used (note the lack of the .ttf extension)
$font = 'SomeFont';
?>
You also said that the font resides in fonts/Aller/ directory. Whereas, in your script, there is no reference to the fonts directory.
The code is all correct except this part
$font = '/Aller/' . $font;
It tries the absolute path '/Aller/Aller_Rg.tff' not 'Aller/Aller_Rg.tff'
Changing it to $font = 'Aller/' . $font; should work.
Also you should check the error log, it should mention Invalid font filename
When in doubt remove header('Content-Type: image/png'); for debugging.

PHP script to render a single transparent pixel (PNG or GIF)

I have to create a PHP that will return an image stream of one transparent dot (PNG or GIF)
Could you point me to an easy to use solution?
Transparent 1x1 PNG:
header('Content-Type: image/png');
echo base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=');
Transparent 1x1 GIF:
header('Content-Type: image/gif');
echo base64_decode('R0lGODlhAQABAJAAAP8AAAAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw==');
In PHP 5.4 and higher it is possible to use hex2bin, which is roughly two times faster than base64_decode (tested with the blank GIF file below). The code to output images would be:
Transparent 1x1 PNG:
header('Content-Type: image/png');
die(hex2bin('89504e470d0a1a0a0000000d494844520000000100000001010300000025db56ca00000003504c5445000000a77a3dda0000000174524e530040e6d8660000000a4944415408d76360000000020001e221bc330000000049454e44ae426082'));
Transparent 1x1 GIF:
header('Content-Type: image/gif');
die(hex2bin('47494638396101000100900000ff000000000021f90405100000002c00000000010001000002020401003b'));
You can easily convert base64 encoded data into hexadecimal:
echo bin2hex(base64_decode($data));
Or a file:
echo bin2hex(base64_decode(file_get_contents($filename)));
However, using the native PHP escape method suggested by #Lukas Liesis is the fastest, about 12.5 times faster than base64_decode, according to my benchmark. And it would work with virtually any version of PHP. Here are the code snippets:
Transparent 1x1 PNG:
header('Content-Type: image/png');
die("\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00\x00\x01\x00\x00\x00\x01\x01\x03\x00\x00\x00\x25\xdb\x56\xca\x00\x00\x00\x03\x50\x4c\x54\x45\x00\x00\x00\xa7\x7a\x3d\xda\x00\x00\x00\x01\x74\x52\x4e\x53\x00\x40\xe6\xd8\x66\x00\x00\x00\x0a\x49\x44\x41\x54\x08\xd7\x63\x60\x00\x00\x00\x02\x00\x01\xe2\x21\xbc\x33\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82");
Transparent 1x1 GIF:
header('Content-Type: image/gif');
die("\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x90\x00\x00\xff\x00\x00\x00\x00\x00\x21\xf9\x04\x05\x10\x00\x00\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x04\x01\x00\x3b");
Creating such a string is easy with regular expressions (as it's done once, it doesn't have to work fast):
echo preg_replace('/../','\\x\0',bin2hex($data));
Or from a file:
echo preg_replace('/../','\\x\0',bin2hex(file_get_contents($filename)));
To answer some people's questions:
You must echo the contents of an image. The Header only shows that are you are returning an image to the browser, instead of normal text. So if you only return a header, it's just a header - no data. However, print out data of an image and done, you just sent an image :)
Reading a file is not good, it could work, but it's better to return raw data like shown in main answer by Sjoerd. This way, you save time and server load not having to process a read operation. Reading from disk is a slow task. Over time, reading from disk has increased in speed with SSD disks, but still, No I/O to disk is better.
I had this code even without base64 decode, but this image has white color:
header('Content-Type: image/gif');
// 1x1px white gif
die("\x47\x49\x46\x38\x37\x61\x1\x0\x1\x0\x80\x0\x0\xfc\x6a\x6c\x0\x0\x0\x2a\x0\x0\x0\x0\x1\x0\x1\x0\x0\x2\x2\x44\x1\x0\x3b");
Maybe someone knows how to convert any file to such data string?
header('Content-Type: image/gif');
printf('%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%', 71, 73, 70, 56, 57, 97, 1, 0, 1, 0, 128, 255, 0, 192, 192, 192, 0, 0, 0, 33, 249, 4, 1, 0, 0, 0, 0, 44, 0, 0, 0, 0, 1, 0, 1, 0, 0, 2, 2, 68, 1, 0, 59);
In Linux you can convert it by typing in console:
hexdump -v -e '"\\\x" 1/1 "%X"' image.gif; echo

PHP 5: how to write utf-8 binary data - image - to output?

I have a Ubuntu server and PHP5, and the PHP script files, and all output are in UTF-8.
I'm trying to send an image to the output stream, but just garbled chinese characters shows up in the output:
$im = imagecreatetruecolor(120, 20);
$text_color = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 1, 5, 5, 'A Simple Text String', $text_color);
header('Content-type: image/jpeg');
imagejpeg($im);
imagedestroy($im);
any suggestions?
Your code works perfectly fine on my machine :
<?php
$im = imagecreatetruecolor(120, 20);
$text_color = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 1, 5, 5, 'A Simple Text String', $text_color);
header('Content-type: image/jpeg');
imagejpeg($im);
imagedestroy($im);
die;
?>
Are you sure you are not outputing anything before or after that code ? Even any kind of whitespace would be a source of troubles.
Or maybe your script is doing something else somewhere ?
If it still doesn't work, maybe trying with imagettftext, to use a "better" / more complete font than the ones used by imagestring might help ?
Using something like this, for instance :
$font = '/usr/share/fonts/truetype/msttcorefonts/arial.ttf';
imagettftext($im, 20, 0, 10, 20, $text_color, $font, 'A Simple éléphant String');
BTW, did you try without those line :
header('Content-type: image/jpeg');
imagejpeg($im);
imagedestroy($im);
If there is an error/warning/notice, removing those lines might help you seeing those.
And, as a sidenote : using JPEG for images that contain some text generally doesn't give great results, as JPEG is a destructive compression mechanism. Using PNG, in that kind of situation, might get you better results ;-)
Try removing the UTF-8 byte order mark, because it gets prepended to the contents of your JPEG image, rendering it invalid.

What is a good easy class to change text to images

As many of you may already know I have been having issues with another site copying text from my site. The data is sports results that at first are not fully accurate because data is submitted at the event and people have to type in people's hand writing that can be difficult to read as well as other issues related to transferring data. Currently I am stuffing the text with fake text. It is working in part very well. They are still copying the text, but they are removing the fake text manually (which takes them about 2 hours longer hehe). I want to make it even more difficult for them. I would like to change some of the text automatically to images. This will require them to type these portions out. What is a good premade class for this?
I suppose you could use the GD library, that is bundled with PHP, to generate images from text.
Something like this, for instance, might do (adapted from the example given on the page of imagettftext) :
header('Content-type: image/png');
// Create the image
$im = imagecreatetruecolor(400, 30);
// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, 399, 29, $white);
// The text to draw
$text = 'Hello, World!';
// Replace path by your own font path
$font = '/usr/share/fonts/truetype/msttcorefonts/verdana.ttf';
// Add some shadow to the text
imagettftext($im, 20, 0, 11, 21, $grey, $font, $text);
// Add the text
imagettftext($im, 20, 0, 10, 20, $black, $font, $text);
// Using imagepng() results in clearer text compared with imagejpeg()
imagepng($im);
imagedestroy($im);
die;
But note that using images instead of text has some drawbacks :
on the server side, it requires more work
on the client side :
it'll take more time to load
it will not necessarily use the same fonts as the rest of the site (possibly depending of the brower's configuration)
fonts will not necessarily have the same size as the rest of the site (same note)
using images might not be good for people who zoom -- especially people who don't see well.
How about adding some form of disclaimer to the text ("this text created by xyz.com, on dd/mm/yyyy, for more up-to-date information visit our site")? Use their use of your text as a promotional tool for your own site. Also, get in touch with them, see if they'd be interested in using your site via some form of API, this reduces their workload and allows you a little more control over their use (at least in theory).
My argument is that if the stuff you're writing up is factual there's no copyright infringement (so far as I can tell), and they may appeal to a different audience than your own, so you may as well use them as a promotional tool to broaden your own audience.

Categories