FPDF Text Stroke - php

I'm trying to write some text with stroke in a PDF file using the FPDF PHP class.
I noticed a strange black text border and I don't know how to make it disappear.
I'll show you a simplified code of what i'm doing and the result so you can understand my problem:
require('fpdf/fpdf.php');
$pdf = new FPDF('P','pt',array(250,300));
$pdf->AddPage();
$letter = imagecreatetruecolor(250,300);
imagealphablending($letter, 1);
imagesavealpha($letter, 1);
imagefill($letter, 0, 0, imagecolorallocatealpha($letter, 0, 0, 0, 127));
$border = imagecreatetruecolor(250,300);
imagealphablending($border, 1);
imagesavealpha($border, 1);
imagefill($border, 0, 0, imagecolorallocatealpha($border, 0, 0, 0, 127));
$letter_color = imagecolorallocate($letter, 0, 0, 255);
$border_color = imagecolorallocate($letter, 255, 0, 0);
imagettftext($letter, 350, 0, 25, 250, $letter_color, 'font/times.ttf', 'a');
imagettftext($border, 350, 0, 25, 250, $border_color, 'font/times.ttf', 'a');
imagepng($letter,'letter.png');
imagepng($border,'border.png');
imagedestroy($letter);
imagedestroy($border);
for($j = 0; $j < 10; $j++) {
for($k = 0; $k < 10; $k++) {
$pdf->Image('border.png', $k - 5, $j - 5, 250, 300);
}
}
$pdf->Image('letter.png', 0, 0, 250, 300);
unlink('letter.png');
unlink('border.png');
$pdf->Output();
This is the result: http://postimg.org/image/l97rr0xzr/
How can I solve this?

A little bit late:
I used a function http://www.fpdf.org/en/script/script78.php# in a custom class:
class CustomPdf extends Fpdf
{
public function ClippingText($x, $y, $txt, $outline=false)
{
$op= $outline ? 5 : 7;
$this->_out(sprintf('q BT %.2F %.2F Td %d Tr (%s) Tj ET',
$x*$this->k,
($this->h-$y)*$this->k,
$op,
$this->_escape($txt)));
}
public function strokeText($x, $y, $txt, $outline=true)
{
$this->SetTextColor(46, 52, 120);
$this->Text($x,$y,$txt);
$this->SetDrawColor(186, 236, 253);
$this->SetLineWidth(0.5);
$this->ClippingText($x,$y,$txt,$outline);
}
}
$pdf = new CustomPdf();
.... add pages and fonts and cells
$pdf->strokeText(30,30,'Hola mundo');
results in

The problem is in the imagettftext(), but if I use that function to print letters of the same color in a single image the shadow appears only on the border of the "composition letters". Now I temporary moved the for loop to do what I just explained.
This is the simplified code:
require('fpdf/fpdf.php');
$pdf = new FPDF('P','pt',array(250,300));
$pdf->AddPage();
$letter = imagecreatetruecolor(250,300);
imagealphablending($letter, 1);
imagesavealpha($letter, 1);
imagefill($letter, 0, 0, imagecolorallocatealpha($letter, 0, 0, 0, 127));
$letter_color = imagecolorallocate($letter, 0, 0, 255);
$border_color = imagecolorallocate($letter, 255, 0, 0);
for($j = -5; $j <= 5; $j++) {
for($k = -5; $k <= 5; $k++) {
imagettftext($letter, 350, 0, 25 + $j, 250 + $k, $border_color, 'font/times.ttf', 'a');
}
}
imagettftext($letter, 350, 0, 25, 250, $letter_color, 'font/times.ttf', 'a');
imagepng($letter,'letter.png');
imagedestroy($letter);
$pdf->Image('letter.png', 0, 0, 250, 300);
unlink('letter.png');
$pdf->Output();
This is the result: http://postimg.org/image/s44v2rbqn/
Still looking for how to delete the shadow.
Now that i really understood the problem, I noticed that this is a duplicate. Sorry.
If you know the answer go here: How we can change the font opacity and shadowing in imagettftext function?

Related

PHP GD - image damaged when using imagettftext()

I'am using PHP 7.4, with Symfony 5.2, memory_limit = 1024M in php.ini
I implement an API which put a quote in an image, using imagettftext() method.
My problem is that the image is damaged. It seems to be because of the length of the text.
When the text is short, the result is ok:
image ok
When the text is longer, the image is damaged (color spots appear):
image damaged
Here is my code:
private function createResource(string $imageContent, array $quote)
{
$image = \imagecreatefromstring($imageContent);
$heigh = \imagesy($image);
$width = \imagesx($image);
$text = $quote['quote'];
$charsArray = \str_split($text, 1);
$charsTotalNb = \count($charsArray);
$charsNbPerLine = (int) floor(($width - 50) / 10);
$lineNb = (int) ceil($charsTotalNb / $charsNbPerLine);
$text = \wordwrap($text, $charsNbPerLine, "|", \false);
$quoteHeigh = 60 + $lineNb * 25;
$card = \imagecreatetruecolor($width, $heigh + $quoteHeigh);
$black = \imagecolorallocate($card, 0, 0, 0);
$white = imagecolorallocate($card, 255, 255, 255);
\imagefill($card, 0, 0, $black);
\imagecopymerge($card, $image, 0, 0, 0, 0, $width, $heigh, $quoteHeigh);
\imagedestroy($image);
$font = __DIR__ . '/../../public/fonts/Averia_Serif_Libre.ttf';
\imagettftext($card, 15, 0, 25, $heigh + 30, $white, $font, $text);
$author = $quote['author'];
if (empty($author)) {
$author = 'Anonymous';
}
\imagettftext(
$card,
12,
0,
(int) $width/2,
$heigh + 40 + $lineNb * 25,
$white,
$font,
'-' . $author . '-'
);
for ($i = 0 ; $i < 7 ; $i++ ) {
\imageline($card, 0 + $i, 0 + $i, 0 + $i , \imagesy($card), $black);
\imageline($card, 0, 0 + $i, \imagesx($card) , 0 + $i, $black);
\imageline($card, \imagesx($card) - $i, 0, \imagesx($card) - $i, \imagesy($card), $black);
}
if (empty(\get_resource_type($card))) {
throw new Exception("Error Processing Request in CardService::createCard()");
}
return $card;
}
How fix my problem ? How to remedy the deterioration of the cat's image?
Thanks for your answers.
I found the problem in my code :
The following line is wrong because of the last argument :
\imagecopymerge($card, $image, 0, 0, 0, 0, $width, $heigh, $quoteHeigh);
The correction is :
\imagecopymerge($card, $image, 0, 0, 0, 0, $width, $heigh, 100);
```

Watermarking an existing PDF in Drupal

I'm working on a project in DRUPAL and am trying to programatically add an image to an existing pdf - an "Approved" image for invoices. I've Frankensteined the code from the StackExchange post - How can I add a watermark to an existing PDF file using PHP? - and have managed to get it working outside of Drupal (7.0) but once I port the code over, I get nothing, no errors, no warnings, nadda .... Just wondering if someone out there can help me on this issue, it been driving me nuts for a bit now .... Sorry about the sloppy code....
<?php
global $user;
ob_start();
$filename ="approved_".$user->name.".png";
$file = "2pages.pdf";
$op = 100;
////////////////////////////////////////////////////////////////////////////
require('fpdf.php');
require('fpdi.php');
$text = "Text message for watermark goes here";
$name = uniqid();
$font_size = 5;
$ts=explode("\n",$text);
$width=0;
foreach ($ts as $k=>$string) {
$width=max($width,strlen($string));
}
$width = imagefontwidth($font_size)*$width;
$height = imagefontheight($font_size)*count($ts);
$el=imagefontheight($font_size);
$em=imagefontwidth($font_size);
$img = imagecreatetruecolor($width,$height);
// Background color
$bg = imagecolorallocate($img, 255, 255, 255);
imagefilledrectangle($img, 0, 0,$width ,$height , $bg);
// Font color
$color = imagecolorallocate($img, 0, 0, 0);
foreach ($ts as $k=>$string) {
$len = strlen($string);
$ypos = 0;
for($i=0;$i<$len;$i++){
$xpos = $i * $em;
$ypos = $k * $el;
imagechar($img, $font_size, $xpos, $ypos, $string, $color);
$string = substr($string, 1);
}
}
imagecolortransparent($img, $bg);
$blank = imagecreatetruecolor($width, $height);
$tbg = imagecolorallocate($blank, 255, 255, 255);
imagefilledrectangle($blank, 0, 0,$width ,$height , $tbg);
imagecolortransparent($blank, $tbg);
if ( ($op < 0) OR ($op >100) ){
$op = 100;
}
imagecopymerge($blank, $img, 0, 0, 0, 0, $width, $height, $op);
$pdf = new FPDI();
//********************************************************************
if (file_exists($file)){
$pagecount = $pdf->setSourceFile($file);
} else {
return FALSE;
}
/////////////////////////////////////////
for($i=1; $i <= $pagecount; $i++) {
$tpl = $pdf->importPage($i);
$pdf->addPage();
$pdf->useTemplate($tpl, 1, 1, 0, 0, TRUE);
//Put the watermark
$pdf->Image($filename, 0, 0, 40, 25, 'png');}
/////////////////////////////////////////
return $pdf->Output('test10.pdf', 'F');
////////////////////////////////////////////////////////////////////////////
ob_end_flush();
?>
Of note, I am also open you anyone who may have an alternate method to achieve the same end result
thanks in advance!
So after taking some advise from Marc B, I went through the code and isolated the issue. For those looking for the answer to this question, here's the solution I came up with ... Hope it helps!
<?php
ob_start();
function PlaceWatermark($file, $text, $xxx, $yyy, $op, $outdir) {
global $user;
require('fpdf.php');
require('fpdi.php');
$myfilename = 'approved_'.$user->name.'.png';
// Created Watermark Image
$pdf = new FPDI();
//if (file_exists("./".$file)){
$pagecount = $pdf->setSourceFile($file);
//} else {
// return FALSE;
//}
/////////////////////////////////////////
for($i=1; $i <= $pagecount; $i++) {
$tpl = $pdf->importPage($i);
$pdf->addPage();
$pdf->useTemplate($tpl, 1, 1, 0, 0, TRUE);
//Put the watermark
if (file_exists($myfilename)) {
$pdf->Image($myfilename, 0, 0, 40, 25, 'png');
} else {
$pdf->Image('approved.png', 0, 0, 40, 25, 'png');
}
}
/////////////////////////////////////////
return $pdf->Output('test_output.pdf', 'F');
}
PlaceWatermark("Original.pdf", "", 30, 120, 100,TRUE);
ob_end_flush();
?>

Trying to add text into an image

I'm trying to add 2 line of text. One for the name of the person and the other for the name of the clan.
Could you help me of what I'm doing wrong? I don't get any error message or anything and the image is loading fine.
This is my code:
//Ribbons Image
$ribbons = array(
"ribbons/1STAID.png",
"ribbons/BMT.png",
"ribbons/BRA1A.png",
"ribbons/CCMD.png",
"ribbons/CCMDV2.png",
"ribbons/donator.png",
"ribbons/FTR.png",
"ribbons/GC.png",
"ribbons/GRA1A.png",
"ribbons/IOTP.png",
"ribbons/MEDIC.png",
"ribbons/PHA1A.png",
"ribbons/PILOT.png",
"ribbons/RCT1A.png",
"ribbons/RCT2A.png",
"ribbons/RCT3A.png",
"ribbons/RCT4A.png",
"ribbons/SRA1A.png",
"ribbons/SVR1A.png",
"ribbons/SVR2A.png",
"ribbons/SVR3A.png",
"ribbons/SVR4A.png",
"ribbons/SVR-ALTIS.png",
"ribbons/XOCMD.png",
"ribbons/XOCMDV2.png");
//Rank Image
$rank = imagecreatefrompng("rank/2LT.png");
//Background
$frame = imagecreatefrompng("sign3.png");
//imagecopymergy(output,image,x,y,0,0,w,h,100)
//Adding rank
imagecopymerge($frame, $rank, 30, 30, 0, 0, 10, 25, 100);
//Trying to add the text on the image
$im = imagecreatetruecolor(400, 30);
$white = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, 399, 29, $white);
$text = 'Test...';
$font = 'arial.ttf';
imagettftext($im, 20, 0, 10, 20, $white, $font, $text);
//Adding the ribbon on the image
$z = 0;
$i = 0;
for ($y = 0; $y <= 120; $y += 20) {
$z++;
for ($x = 0; $x <= 150; $x += 50) {
if ($i <= 24) {
$rib = imagecreatefromjpeg($ribbons[$i]);
imagecopymerge($frame, $rib, $x + 375, $y + 50, 0, 0, 50, 20, 100);
}
$i++;
}
}
//Save the image + Display
imagepng($frame, 'generate/test.png');
imagepng($frame);
header('Content-Type: image/png');
Thanks for helping me!
Working code:
//Ribbons Image
$ribbons = array(
"ribbons/1STAID.png",
"ribbons/BMT.png",
"ribbons/BRA1A.png",
"ribbons/CCMD.png",
"ribbons/CCMDV2.png",
"ribbons/donator.png",
"ribbons/FTR.png",
"ribbons/GC.png",
"ribbons/GRA1A.png",
"ribbons/IOTP.png",
"ribbons/MEDIC.png",
"ribbons/PHA1A.png",
"ribbons/PILOT.png",
"ribbons/RCT1A.png",
"ribbons/RCT2A.png",
"ribbons/RCT3A.png",
"ribbons/RCT4A.png",
"ribbons/SRA1A.png",
"ribbons/SVR1A.png",
"ribbons/SVR2A.png",
"ribbons/SVR3A.png",
"ribbons/SVR4A.png",
"ribbons/SVR-ALTIS.png",
"ribbons/XOCMD.png",
"ribbons/XOCMDV2.png");
//Rank Image
$rank = imagecreatefrompng("rank/2LT.png");
//Background
$frame = imagecreatefrompng("sign3.png");
//imagecopymergy(output,image,x,y,0,0,w,h,100)
//Adding rank
imagecopymerge($frame, $rank, 30, 30, 0, 0, 10, 25, 100);
//Trying to add the text on the image
$im = imagecreatetruecolor(50, 30);
$black = imagecolorallocate($im, 0, 0, 0);
$white = imagecolorallocate($im, 0, 82, 255);
imagefilledrectangle($im, 4, 4, 50, 25, $white);
$text = 'Nato Military Corp';
$font = 'arial.ttf';
imagettftext($frame, 12, 0, 450, 220, $white, $font, $text);
//imagecopymerge($frame, $im, 10, 20, 0, 0, 10, 25, 100);
//Adding the ribbon on the image
$z = 0;
$i = 0;
for ($y = 0; $y <= 120; $y += 20) {
$z++;
for ($x = 0; $x <= 150; $x += 50) {
if ($i <= 24) {
$rib = imagecreatefromjpeg($ribbons[$i]);
imagecopymerge($frame, $rib, $x + 375, $y + 50, 0, 0, 50, 20, 100);
}
$i++;
}
}
//Save the image + Display
imagepng($frame, 'generate/test.png');
imagepng($frame);
header('Content-Type: image/png');

How to create transparent background with PHP using GD?

I made an image combining 3 different images, but I need a transparent background, and I don't succeed doing it. This is my final code:
<?php
$meko = $_GET['image'];
$im = $meko;
$bookback = "images/book_back.png";
$mekoCanvas = imagecreatetruecolor(115, 135);
$canvas = imagecreatetruecolor(115, 185);
$bookback = imagecreatefrompng($bookback);
$meko = imagecreatefromjpeg($meko);
imagecopy($mekoCanvas, $meko, 0, 0, 0, 0, 100, 135);
imagecopy($mekoCanvas, $bookback, 100, 0, 0, 0, 15, 135);
$im = $mekoCanvas;
$rH = 50; // Reflection height
$tr = 30; // Starting transparency
$div = 1; // Size of the divider line
$w = 115;
$h = 135;
//$im = imagecreatefromjpeg($im);
$li = imagecreatetruecolor($w, 1);
$bgc = imagecolorallocate($li, 255, 255, 255); // Background color
imagefilledrectangle($li, 0, 0, $w, 1, $bgc);
$bg = imagecreatetruecolor($w, $rH);
$wh = imagecolorallocate($im,255,255,255);
$im = imagerotate($im, -180, $wh);
imagecopyresampled($bg, $im, 0, 0, 0, 0, $w, $h, $w, $h);
$im = $bg;
$bg = imagecreatetruecolor($w, $rH);
for ($x = 0; $x < $w; $x++) {
imagecopy($bg, $im, $x, 0, $w-$x, 0, 1, $rH);
}
$im = $bg;
$in = 100/$rH;
for($i=0; $i<=$rH; $i++){
if($tr>100) $tr = 100;
imagecopymerge($im, $li, 0, $i, 0, 0, $w, 1, $tr);
$tr+=$in;
}
imagecopymerge($im, $li, 0, 0, 0, 0, $w, $div, 100); // Divider
header('content-type: image/jpeg');
imagecopy($canvas, $mekoCanvas, 0, 0, 0, 0, 115, 135);
imagecopy($canvas, $im, 0, 135, 0, 0, 115, 50);
imagejpeg($canvas);
imagedestroy($im);
imagedestroy($li);
?>
and the results is:
click here
You're not telling GD to use alpha in any of your code. That's done with imagesavealpha, imagealphablending, etc...
Try using
imagecolortransparent($im);
http://www.php.net/manual/en/function.imagecolortransparent.php

Combining images in PHP while retaining transparency

Have a look here: http://tyilo.jbusers.com/PNG/progress.php?l=100&p=20
I want to remove the white-thingy at the end of the blue part, but I have tried many different things that didn't work.
If needed the pngs can be found in http://tyilo.jbusers.com/PNG/ folder (http://tyilo.jbusers.com/PNG/Empty.png)
header('Content-type: image/png');
echo imagepng(progressbar($_GET['l'], $_GET['p']));
function progressbar($length, $percentage)
{
$length = round($length / 2) * 2;
$percentage = min(100, max(0, $percentage));
if($length > 0)
{
$bar = imagecreate($length, 14);
$empty = imagecreatefrompng('Empty.png');
$fill = imagecreatefrompng('Fill.png');
$lempty = imagecreatefrompng('LeftEmpty.png');
$lfill = imagecreatefrompng('LeftFill.png');
$rempty = imagecreatefrompng('RightEmpty.png');
$rfill = imagecreatefrompng('RightFill.png');
$emptycaplength = min(7, $length / 2); //5
imagecopy($bar, $lempty, 0, 0, 0, 0, $emptycaplength, 14);
imagecopy($bar, $rempty, $length - $emptycaplength, 0, 7 - $emptycaplength, 0, $emptycaplength, 14);
if($length > 14)
{
imagecopyresized($bar, $empty, 7, 0, 0, 0, $length - 14, 14, 1, 14);
}
$filllength = round(($length * ($percentage / 100)) / 2) * 2;
$fillcaplength = min(7, $filllength / 2);
imagecopy($bar, $lfill, 0, 0, 0, 0, $fillcaplength, 14);
imagecopy($bar, $rfill, $filllength - $fillcaplength, 0, 7 - $fillcaplength, 0, $fillcaplength, 14);
if($filllength > 14)
{
imagecopyresized($bar, $fill, 7, 0, 0, 0, $filllength - 14, 14, 1, 14);
}
return $bar;
}
else
{
return false;
}
}
try using imagecreatetruecolor() to create your image.
http://www.php.net/manual/en/function.imagecreatetruecolor.php
I think you need to set the Alpha blend of the image...
imagealphablending($cropimg, false);
imagesavealpha($cropimg, true);
I've also found that it helps to set the Color Allocation.
imageColorAllocate ($cropimg, 0, 0, 0);
I think you will need to call those three functions on all your filled images. Sorry for the incomplete answer, I'm in a rush but thought I'd throw you a bone.

Categories