I want to add an image in header using TCPDF in my Magento store.
I am doing this:
$tcpdf = new TCPDF_TCPDF();
$img = file_get_contents(Mage::getBaseDir('media') . '/dhl/logo.jpg');
$PDF_HEADER_LOGO = $tcpdf->Image('#' . $img);//any image file. check correct path.
$PDF_HEADER_LOGO_WIDTH = "20";
$PDF_HEADER_TITLE = "This is my Title";
$PDF_HEADER_STRING = "This is Header Part";
$tcpdf->SetHeaderData($PDF_HEADER_LOGO, $PDF_HEADER_LOGO_WIDTH, $PDF_HEADER_TITLE, $PDF_HEADER_STRING);
$tcpdf->Output('report_per_route_'.time().'.pdf', 'I');
What steps I have to follow if I want to add my store name (left corner) and logo (right corner)?
If you are trying to generate the pdf using the WriteHTML() here is a little trick to add image without use of image() function.
Simply use the HTML <img> as below,
$image_path = 'path/to/image';
$print = '<p>some text here...</p>';
$print .= '<img src=" '. $image_path .' ">';
and you can use inline css to apply height, width etc.
TCPDF is tricky about inserting images as HTML. It implements few hacks to tell what is being loaded:
inserting image with src attribute as absolute path - must have star * prefix:
<img src="*/var/www/my-image.png">
inserting image with src attribute as relative path - both examples are treated as relative paths:
<img src="/var/www/my-image.png">
<img src="var/www/my-image.png">
Note, that relative paths are calculated differently on linux and windows - what works correctly on windows may not work well on linux. That is caused by checking first character in a path string as a forward slash /, which is considered a linux root and the path will be recalculated - relative path will append to a global variable DOCUMENT_ROOT.
Loading base-64 encoded string - must have # prefix in src attribute:
<img src="#iVBORw0KGgoAAggfd0000555....">
<img src="#'.base64_encode(file_get_contents($path)).'" width=50 height=35>
This is safe bet if you want to avoid issues with calculating correct path, but adds extra I/O overhead, because TCPDF will attempt to store supplied data as temporary image file in order to determine image width & height.
Ok. First of all $PDF_HEADER_LOGO is suppose to be an image file name, not image data - as in default implementation of Header() function. There is, however, one important thing to remember, exact location depends on K_PATH_IMAGES constant, which should contain path to images folder. If its defined before including TCPDF library its ok, if not TCPDF checks some default paths and first existing is used as images directory. Those directories are:
./examples/images/
./images/
/usr/share/doc/php-tcpdf/examples/images/
/usr/share/doc/tcpdf/examples/images/
/usr/share/doc/php/tcpdf/examples/images/
/var/www/tcpdf/images/
/var/www/html/tcpdf/images/
/usr/local/apache2/htdocs/tcpdf/images/
K_PATH_MAIN (which is root tcpdf folder)
So either define constant before, or put your file to one of above directories, and then pass only file name as first argument to SetHeaderData and it should work.
To have something similar for Footer you need to extend base TCPDF_TCPDF class and overwrite its Footer method.
Example:
class MYPDF extends TCPDF_TCPDF {
// Page footer
public function Footer() {
// Position at 15 mm from bottom
$this->SetY(-15);
// Set font
$this->SetFont('helvetica', 'I', 8);
// Page number
$this->Cell(0, 10, 'COMPANY NAME', 0, false, 'C', 0, '', 0, false, 'T', 'M');
$this->Image('/path/to/image.jpg', 500)
}
}
You'll probably need to work out exact coordinates. Especially in Image it depends on your dimensions, you can add another parameter to Image function being y coordinate, and two others - width and height of image.
And most importantly I recommend checking great examples section on TCPDF page:
http://www.tcpdf.org/examples.php
Related
I have a problem when trying to create my Telegram's Instant View template, with this error:
Resource fetch failed: https://gdude.de/blog/assets/images/Kaggle-Lyft/task.webp
Resource fetch failed: https://gdude.de/blog/assets/images/telegram.ico
The URLs are valid, I have checked.
These are the only two images that fail. Does IV support *.webp and *.ico images?
According to their manual, Instant View is only actually supporting gif, jpg and png.
with the attribute src and the optional attribute href to make the image clickable. Allowed formats: GIF, JPG, PNG (GIF would be converted into Video type by IV)
I had a similar problem and solved it in the following way.
Note: You need a hosting server to store a PHP script, a free one worked for me (000Webhost).
The diagram below represents the general idea
Instant View code
Note: I'm a beginner at Instant View and XPath, so for now I'm just writing code that works.
# Find unsupported images
$imgs: //img[ends-with(#src, ".webp")]
$imgs+: //img[ends-with(#src, ".ico")]
# Temporary element to create the URLs and make calls to the conversion service
#html_to_dom: "<a>"
$tmp_tag
# For each unsupported image
#map($imgs){
$img: $#
# Build de URL to request the image conversion service
#set_attr(href, "https://my-free-subdom.000webhostapp.com/imgconverter.php?url=", $img/#src): $tmp_tag/a
# Make the request
#load: $tmp_tag/a/#href
# Change the src of the unsupported image to that of the converted image created by the conversion service
#set_attr(src, $#//img/#src): $img
}
#remove: $tmp_tag
PHP script to convert the image
To handle the ICO files I used the IcoFileLoader library, I found it thanks to this question PHP GD .ico handling. I just took the PHP files from the src directory and put them directly on my hosting, so I had to use a simple Autoloader.
// The URL of the image to convert
// If the url of the image is relative, you have
// to build it here, example $url = 'https://gdude.de'.$_GET['url'];
$url = $_GET['url'];
// File name
$file_name = basename($url);
// Directory where the image will be saved
$dir = './';
// File location
$save_file_loc = $dir . $file_name;
// Open file
$fp = fopen($save_file_loc, 'wb');
// Download the image using CURL
$ch = curl_init($url);
// Set options for a cURL transfer
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
// Close file
fclose($fp);
// Load the image
// ICO images need special handling
if(str_ends_with($file_name, '.ico'))
{
require_once('Autoloader.php');
$loader = new IcoFileService;
// You must define the size, I did the tests with a 16X16 favicon.
$im = $loader->extractIcon($file_name, 16, 16);
}
else if(str_ends_with($file_name, '.webp'))
{
$im = imagecreatefromwebp($file_name);
}
// Check if the image was loaded
if(!isset($im))
{
die('Unable to load image!');
}
// Convert it to a png file
imagepng($im, $file_name.'.png');
imagedestroy($im);
// Delte the original image
unlink($file_name);
// "Return" the image in an HTML tag so that Instant View can handle it
echo '<img src="https://my-free-subdom.000webhostapp.com/' . $file_name . '.png">';
Feel free to improve the above code, perhaps add some security, delete old images, use other libraries or PHP functions, accept multiple images in the same request, etc.
I found imageoptim to be helpful for free conversion of (in my case) svg images. Just prepend this url to the svg url and they'll start to load. I chose a resolution of 2560 as it's the max resolution that IV 2.1 supports.
#set_attr(src, "https://img.gs/<your-username>/2560,fit,format=png,quality=high/", ./#src): $body//img[contains(#src, ".svg")]
#set_attr(srcset, "https://img.gs/<your-username>/2560,fit,format=png,quality=high/", ./#srcset): $body//img[contains(#srcset, ".svg")]
So this is really frustrating... on the mymaths website: https://www.mymaths.co.uk/, there's an image of a primary school child on a computer with this image address: https://www.mymaths.co.uk/assets/images/big/primary-school-photo-2.jpg.
I've tried so many things, but I can't seem to replace it.
Say I wanted to replace it with a picture of a hamburger, with this address: https://images.ctfassets.net/sd2voc54sjgs/5L6livQvCw28S04IUSAcm6/6482ea1819e86be1b4f7e85bfbbfe9a6/Blog_Header_Hamburger_History_Option.png?fm=jpg&q=80&fl=progressive&w=1100.
So far I've tried lots of threads, but this image seems to be different from images on other websites, which is why my code isn't working on it:
var images3 = document.getElementsByTagName ("img");
var i3=0;
while(i3<images3.length)
{
if(images[i3].src == "https://www.mymaths.co.uk/assets/images/big/primary-school-photo-2.jpg")
{
images[i3].src = "https://images.ctfassets.net/sd2voc54sjgs/5L6livQvCw28S04IUSAcm6/6482ea1819e86be1b4f7e85bfbbfe9a6/Blog_Header_Hamburger_History_Option.png?fm=jpg&q=80&fl=progressive&w=1100";
}
i3=i3+1;
}
Can somebody help me please? Thank you.
Well, this was new for me too. Apparently, the <picture> tag is not just a wrapper - it's a smarter version of <img>.
It allows to chose different URLs for the image tag depending on screen size and type. For example, try to do this in developper tools:
I replaced srcset for the <source> that has (max-width: 767px), which means it is active when browser window is smaller than 767px. Now if you resize browser window to make it smaller, at some point the original image will be raplaced with burger image.
So what you want to do is to replace all <source>'s srcset. This worked for me:
// Limit the list of omages on those that are under `<picture>` tag
const images = document.querySelectorAll("picture img, picture source");
// RegExp to check if we want to replace the URL
const replaceChecker = /primary-school-photo-2\.jpg$/i;
// The replacement URL
const replaceWith = "https://images.ctfassets.net/sd2voc54sjgs/5L6livQvCw28S04IUSAcm6/6482ea1819e86be1b4f7e85bfbbfe9a6/Blog_Header_Hamburger_History_Option.png?fm=jpg&q=80&fl=progressive&w=1100";
for(const image of images) {
// Pick the name of the attribute we want to change based on whether it's <img> or <source>
const srcAttributeName = image.tagName.toLowerCase() == "img" ? "src" : "srcset";
const oldURL = image[srcAttributeName] + "";
if(replaceChecker.test(oldURL)) {
image[srcAttributeName] = replaceWith;
}
}
You could improve that by checking the media attribute and if it says minimum screen width, use URL for smaller image of the hamburger. That is set by the w GET param in the hamburger image's URL.
I have this fiddle where i crop image and get values such as x,y,x1,y1,w,h:
http://jsfiddle.net/LvsYc/2511
Now what i want is to save that image with those values with Image Intervention but i dont know what function i need to use to pass those parameters. Any suggesion?
function updateCoords(c)
{
console.log(c);
$('#x').val(c.x);
$('#y').val(c.y);
$('#x2').val(c.x2);
$('#y2').val(c.y2);
$('#w').val(c.w);
$('#h').val(c.h);
};
I tried like this but is say that first arguement must be integer.
Image::make($image->getRealPath())->crop($w,$h,$w,$h)->save($path. '/' .$filename); but i get an error that crop first argument need to be integer.
Also what i try is this but it save full size image:
Image::make($image->getRealPath())
->rectangle($x1,$y1,$x2,$y2)->save($path. '/' .$filename);
I used rectangle because only that function recives 4 parameters
EDIT
http://image.intervention.io/api/crop
http://jsfiddle.net/LvsYc/10207/
I think this should do the trick.
$image = Image::make($request->file('image'));
$crop_box_start_x = intval($request->get('x'));
$crop_box_start_y = intval($request->get('y'));
$crop_box_width = intval($request->get('h'));
$crop_box_height = intval($request->get('w'));
$image = $image->crop($crop_box_width, $crop_box_height, $crop_box_start_x, $crop_box_start_y);
$image->save('path/to/save.png');
Tip: Just apply validation before cropping that the area you're cropping is inside the image.
String "unsafe" comes from contenteditable="true" div to where it was pasted as image from clipboard
// neeeds to be escaped. It is HTML5 valid
String unsafe = ""<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABaklEQVQokZWSXYuCQBSG+xdCa5nRRZgzUlmDNlmCxSCjZg4Y9OkwMxf9Sn/aXrRERrC779U5L+fhfHBa9T/Vek3m8/kztm3bcRzXdTebjed50+m0AWy3W4RQXdcAgCcAIcyyTEpZlqVlWQ1ASnm9XpMksW3bsiwAAISQECKEuN/vlNL1et0ALpeLUkoIked5EAS+7xNCqqpSSlFKwzB838FxnCiKzuezEOJ4PJZlebvdOOdxHGOMPyytaRqEEGPMGOOcSymVUoyx5+gfrjQYDB5zn04nznlVVYyxyWRimuYHoN/vD4fD5XKZpmlRFGma7na7w+GQ5zlCaDQavQOu64ZhmCRJlmUYYwDAeDwOw7Aoiv1+v1gsHMdpAIQQSiml1Pd9wzC63a5hGL1eDyEURVEQBJ1OpwFQSuM49jxP13Vd1x+maZpfL2oAq9VqNpu1221N097O8lpdv/3Sj9X6YDaA1p/V6PBr6UPfrxpWT8DSD68AAAAASUVORK5CYII=" alt="">
"
org.jsoup.safety.Whitelist whitelist = Whitelist.relaxed();
whitelist.addEnforcedAttribute("a", "rel", "nofollow");
String safe = Jsoup.clean(unsafe, whitelist);
//and safe becomes: "<img alt="">"
//entire src lost !?
Note: randome surrouning html has no effect. Src is lost in any case.
The basic problem here is that if one quick looks at relaxed here:
http://jsoup.org/apidocs/org/jsoup/safety/Whitelist.html#relaxed
assumes only tags are in, without attributes. Did not look into source, but here claims some attributes are also in: How to make a Jsoup whitelist to accept certain attribute content.
And image is also already in and src also.
the problem that causes my src to disapear is at
preserveRelativeLinks
Which is set to false,for relaxed, hidden somewhere in JSoup code
https://github.com/jhy/jsoup/issues/333
--> should be set to true:
System.out.println(Jsoup.clean("<img src='imgFile.png' />","http://www.somedomain.com", Whitelist.relaxed().preserveRelativeLinks(true)));
This is how to allow basic text with inline images like src="data:image/png;base64,...":
String safe = Jsoup.clean(unsafe, Whitelist.basic()
.addTags("img")
.addAttributes("img", "height", "src", "width")
.addProtocols("img", "src", "http", "https", "data"));
I am writing a script that generates Chinese character worksheets (so students can generate and practice writing)
The script is passed a 15 character string from a form in index.php.
The string is then exploded into an array of 15 elements (each a Chinese character).
The problem arises when I want to use the Write() function to populate the file with these characters, I've used the input to pick appropiate images without any problems but now it's the encoding of the fonts that gives me a hard time.
PS. I need to use a cursive/handwritten font as default 'print' fonts are not suitable for handwriting practice.
Ideally I would like to use HDZB_36.TTF or Sharp Regular Script Font
See the code below as well as images of errors I get with some different fonts.
<?php
header('Content-Type: text/html; charset=utf-8');
// linking TCPDF and FPDI libraries
require_once('tcpdf/tcpdf.php');
require_once('fpdi/fpdi.php');
// First retrieve a 15 chinese charcters long string from POST form in index.php
$hanzi = $_POST["hanzi"];
// Explode the hanzi into a 15 items array
function mb_str_split($hanzi){
return preg_split('/(?<!^)(?!$)/u', $hanzi);
}
$charlist = mb_str_split($hanzi);
// Define starting y positions of each line of the grid
$yPos1 = 10.71;
$yPos2 = 17.94;
// Creating new page with PDF as a background
$pdf = new FPDI();
$background = $pdf->setSourceFile('images/worksheet_template1.pdf');
$tplIdx = $pdf->importPage(1);
$pdf->AddPage();
$pdf->useTemplate($tplIdx, 0, 0, 210, 285, false);
/*
This is where the problem starts, I can manage to display latin characters using helvetica
but when I use any of the chinese fonts (usually encoded as GB2312 or BIG5) it fails.
With some larger (ex. stsong) fonts I get a browser error saying: No data received ERR_EMPTY_RESPONSE (Image 1)
With font 'htst3' the characters appeared upside down and were full of artifacts (Image 2).
With font HDZB_36 the characters were not rendered at all.
Other fonts will result in all of the chars displayed as '?' (Image 3)
*/
$fontname = TCPDF_FONTS::addTTFfont('ukai.ttf', 'TrueTypeUnicode', '', 64);
$pdf->SetFont('ukai','', 20);
for ($i = 0; $i <= 14; $i++){
// Generating path of the stroke order image (that works fine)
$sImgPath = "images/x-s.png";
$sImgPath = str_ireplace('x', $charlist[$i], $sImgPath);
// Stroke order image
$pdf->Image($sImgPath, '14', $yPos1, '','5');
// Here we will populate grid of the worksheet with chinese characters as TEXT
$pdf->SetXY(12.4,$yPos2);
$pdf->SetTextColor(0, 0, 0);
$pdf->Write(0, $charlist[$i], '', false);
$pdf->SetXY(24.2,$yPos2);
$pdf->SetTextColor(192,192,192);
$pdf->Write(0, $charlist[$i], '', false);
// Increase the y pos values so the next run of for() will draw in another line
$yPos1 = $yPos1+17.83;
$yPos2 = $yPos2+17.78;
}
ob_clean();
$pdf->Output('worksheet.pdf', 'I');
?>
Just a suggestion:
The file you generate worksheet.pdfshould perhaps have the same encoding as your letters.
The PDF should have the appropriate encoding, see: https://stackoverflow.com/a/10656899/1933185