simplesoftwareio/simple-qrcode Image manipulation - php

I would like to know how to change image position using canvas in php
I'm trying to display the content inside the picture to bottom right
for($i=0;$i<$request->tables_count;$i++)
{
$milliseconds = round(microtime(true) * 1000);
$qrCodeName = 'storage/uploads/restaurants/' . $milliseconds . "-" . Carbon::now()->toDateString() . '.png';
$newTable=Table::create([
'qr_code' => $qrCodeName,
'num_table' => $i+1,
'status' => 1,
'restaurant_id' =>$restaurant->id,
]);
$numTableImage = Image::canvas(100, 350)->fill('rgba(0, 0, 0, 0.5)');
$numTableImage->text($newTable->num_table, 100, 200, function($font) {
$font->file(public_path('templates/backOffice/restaurant/fonts/OpenSans-Bold.ttf'));
$font->size(100);
$font->color('#fdf6e3');
$font->align('center');
});
$numTableImage->save('storage/uploads/restaurants/table'.$newTable->num_table.'.png');
$qrCode = str_random(10) . "-" . $newTable->id;
$data = $numTableImage->encode();
QrCode::format('png')->mergeString($data)->size(450)->generate($qrCode, $qrCodeName);
}

If I'm understanding what you are doing correctly... why not add the canvas element, inside a div, and then add a span after the canvas?
<style>
div {
position:relative;
}
span {
position: absolute;
bottom:0;
right:0;
}
</style>
<div>
<canvas></canvas>
<span>1</span>
</div>
This way, you can easily position the number image / whatever it is in the bottom right using CSS positioning.
The answer here: Position Relative vs Absolute? is useful for understanding CSS positioning.
Would this solution work for you? Or do you have constraints that mean it won't?
Or if they are separate elements created in the canvas, do the same, but set the element in the canvas as per the span.

Related

Laminas Barcode not rendering correctly

I'm attempting to render barcodes for a MVC application in laminas.
I can build the barcode object, and the renderer, but when I render it it blacks out the whole screen with a single white square in the middle.
I tried replacing my code with the following from PHP Snippets, and I got the same issue. Am I missing a php extension or a composer package or something?
<?php use Common\Util;
use Laminas\Barcode\Object\Code128;
use Laminas\Barcode\Renderer\Image;
$barcode = new Code128([
'text' => 'PHP Snippets',
'barHeight' => 60,
'factor' => 2,
]);
$renderer = new Image([
'resource' => imagecreate($barcode->getWidth(), $barcode->getHeight()),
'barcode' => $barcode,
]);
ob_start();
$renderer->render();
$image = base64_encode(ob_get_contents());
ob_end_clean();
echo '<img src="data:image/png;base64,' . $image . '">';
?>
Here is the html that renders. For some reason it renders the whole <body> as a single image, from the bar code.
<body style="margin: 0px; background: #0e0e0e; height: 100%"><img style="-webkit-user-select: none;margin: auto;background-color: hsl(0, 0%, 90%);transition: background-color 300ms;" src="http://mymvcapp.com/orders"></body>
And here is what displays over the whole browser tab.

How do you make custom images editable when writing a post?

I've altered the default code that is generated when you upload an image through the posting page with the "add media" button in the post content.
This is the code I am using:
add_filter('image_send_to_editor', 'img_wrapper', 20, 8);
function img_wrapper($html, $id, $caption, $title, $align, $url, $size, $alt){
$class = "IA_image";
$editor_size = 300;
$img_meta = wp_get_attachment_metadata($id);
$width = $img_meta['width'];
$height = $img_meta['height'];
$url = wp_get_original_image_url($id);
$style = "width: {$editor_size}px; height: {$editor_size}px; background-image: url({$url}); background-position: center; background-size: cover;";
$html = "<div class=\"{$class}\" data-width=\"{$width}\" data-height=\"{$height}\" style=\"{$style}\"></div>";
// Add caption
if($caption){
$style = "font-style: italic;";
$html .= "<p class=\"caption\" style=\"{$style}\">{$caption}</p>";
}
$html = "<div class=\"{$class}-outer\">{$html}</div>";
return $html;
}
Instead of inserting an img tag I'm now using divs and setting the background image on them accordingly. I'm displaying these images on the wordpress single page.
However, by doing this, the image can not be edited like the usual images (an edit button appears when you click on it). This is the edit button I'm referring to:
Is there any way I can add this "edit" button to my altered images?

php Preventing dynamically added vertical images from being displayed horizontal

I have this problem with a simple cms I'm working on:
I have a simple php function getting image elements from a specified directory, and printing them to the html
<?php if($row["imgs"] == TRUE){ ?>
<div class="imrow">
<?php
$dir = $row["folder"];
$img = glob($dir."*.{jpg,jpeg,png}", GLOB_BRACE);
$tabing = 3;
$scale = sizeof($img);
for ($i = 0; $i < $tabing; $i++) {
echo '<img src="'.$img[$i].'" alt="image" />';
}
?>
</div><?php }//closing the first if of images ?>
(...)
<?php if($row["imgs"] == TRUE) { ?>
<div class="imrow">
<?php
for ($i = $tabing; $i < $scale; $i++) {
if(!($i % $tabing) && ($i!=0)){echo '</div><div class="imrow">';}
echo '<img src="'.$img[$i].'" alt="image" />';
}
?>
</div>
<?php }//second if closing ?>
The style for images and rows:
.imrow {
display: block;
}
.imrow img {
z-index: 10;
float: left;
height: 100%;
cursor: pointer;
transition: transform .5s ease;
box-shadow: 1px 1px 12px rgb(200, 200, 200);
}
And are laid out using a simple jQuery function
$(".imrow").each(function () { // for every row
var row = $(this); //it gives it a name
var rowW = row.width(); //it seals it's width
var imgW = 0; //it sets a image width variable
var fixH = 600; //and get a fixed amount
row.children().each(function () {
$(this).css("height", fixH); //apply fixed height to element in order to get ratio
imgW += $(this).width(); //get the width of this and
$(this).css("height", "100%");
arr.push($(this).attr("src")); // restore
});
row.css("height", rowW / (imgW / fixH) - 2);
});
The problem here is the fact that some of the added Vertical images, turn out horizontal
Here's how it looks in a folder
And how it turns out in the website:
EDIT: This is a php only issue from what I see, because when I analyze the elements in chrome, the images are flipped by default inside, as you all can see here:
So my first bet goes on glob doing something wrong.
Has anyone experienced it, or knows a way to make glob get everything properly?
Bare in mind that this issue only happens to some of the images, and is not depended on the format of the displayed image.
Any help would be extremely useful
It appears the problem was metadata stored in the images that describe the correct orientation.
There is a image-orientation css property that is supposed to be used to display the image in the correct orientation, but it doesn't seem to be supported in all browsers.
The only other solution at the moment is to edit the image's metadata with a metadata editor or, as you have, to open the images in photoshop and save them.

how to change img style width to attribute width in php

How can I go from this
<img style="width:200px; height:300px; ...
to this
<img width="200" height="300" ...
with PHP?
An easy way can be not to touch to the html...
Find a way to target those images in your css and just adapt the display
div.myimages img {
max-with:320px;
height: auto!important;
}
It's gonna use some RegEx:
//use SimpleXMLElement to parse the attributes
$img = new SimpleXMLElement($imgStr);
$pattern = '~([a-z-]+)\s*:\s*([^;$]+)~si';
//convert the value of the style attribute into an associative array
if (preg_match_all($pattern, $img['style'], $match)) {
$style[] = array_combine(
array_map('strtolower', $match[1]),
array_map(function($val) { return trim($val, '"\' '); }, $match[2])
);
}
// add the width and height attributes and get the new html
$img->addAttribute('width', $style[0]['width']);
$img->addAttribute('height', $style[0]['height']);
$newImgStr = $img->asXML();
// remove the width and height rules from the style attribute
$newImgStr = preg_replace('/width:([^;$]+);/', '', $newImgStr);
$newImgStr = preg_replace('/height:([^;$]+);/', '', $newImgStr);
If the style is already loaded with the img then the solutiona can be made with JQUERY :
$(function () {
width=$(this).css("width");
height=$(this).css("height");
$(this).attr("width",width);
$(this).attr("height",height);
});
Hope it will serve your purposes.

Cut strings short PHP

How would you go about Cutting strings short so it doesnt go to the next line in a div tag For example my message string contained the following:
We prefer questions that can be answered, not just discussed. Provide details. Write clearly and simply. If your question is about this website, ask it on meta instead.
And i want to preferably display it as
We prefer questions that can be answered, not just discussed. Provide ... Read More
Im thinking cutting the string short using PHP but then you have the following problem
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ... Read More
You can see that the above string can still be expanded a bit more. Any way to do this or Not, Thanks in Advance
How you can shorten a string is already answered, but your main question:
How would you go about Cutting strings short so it doesnt go to the next line in a div tag
this will not work in most cases.
for example:
iiiiiiiiii
wwwwwwwwww
You see the problem ?
this only works if your chars have the same width like:
iiiiiiiiii
wwwwwwwwww
Using PHP, you can use the wordwrap function to perform truncation:
function truncate_to_length($text, $length, $text_if_longer = "...")
{
if (strlen($text) > $length)
{
$text = wordwrap($text, $length);
$text = substr($text, 0, strpos($text, "\n"));
return $text . $text_if_longer;
}
return $text;
}
The following mostly works; the main issue is that the "...Read more" notice can cover up part of a letter. It also uses a bunch of presentational elements and requires JS. It makes me feel unclean.
The outermost element (of class .string) is used to set the overall size. .text holds the text to display. Between .string and .text in the descendent hierarchy is an element with a large width. This puts all the text in .text on one line. JS is used to show or hide the "...Read more" notice.
<style type="text/css">
.string {
height: 1em;
width: 25%;
position: relative; /* create containing block for children */
border: 1px solid black;
overflow: hidden;
background: white; /* or whatever, as long as it's not "transparent". */
}
.string .line {
width: 5000px; /* long enough for you? */
}
.string .notice {
position: absolute;
top: 0;
right: 0;
z-index: 1;
display: none;
background: inherit; /* so that the notice will completely cover up whatever's beneath */
}
</style>
<div class="string">
<div class="line"><span class="text">We prefer questions that can be answered,
not just discussed. Provide details. Write clearly and simply. If your
question is about this website, ask it on meta instead.</span></div>
</div>
<hr />
<div class="string">
<div class="line"><span class="text">Lorem ipsum dolor sit amet.</span></div>
</div>
<script>
function isOverflowed(elt) {
return elt.offsetWidth > elt.parentNode.parentNode.clientWidth;
}
function getNotice(textElt) {
try {
return (textElt.parentNode.parentNode.getElementsByClassName('notice'))[0];
} catch (e) {
return {style: {}};
}
}
function show(elt) {
elt.style.display = 'block';
}
function hide(elt) {
elt.style.display = 'none';
}
function showReadMoreNotices() {
var text=document.getElementsByClassName('text');
for (var i=0; i<text.length; ++i) {
if (isOverflowed(text[i])) {
show(getNotice(text[i]));
} else {
hide(getNotice(text[i]));
}
}
}
var strings = document.getElementsByClassName('string');
var notice = document.createElement('div');
notice.appendChild(document.createTextNode('\u2026Read more'));
notice.className = 'notice';
for (var i=0; i<strings.length; ++i) {
strings[i].appendChild(notice.cloneNode(true));
}
showReadMoreNotices();
/* use your favorite event registration method here. Not that the traditional
* model is my favorite, it's just simple.
*/
window.onresize = showReadMoreNotices;
</script>
Check the size, if the size is greater than your maximum, take the leftmost characters.
Leftmost # = Total size - size("... read more").
Then append the read more to the left most characters.
Jacob
Here is an example taken from http://snippetdb.com/php/truncate-string:
function Truncate ($str, $length=10, $trailing='...')
{
// take off chars for the trailing
$length-=strlen($trailing);
if (strlen($str) > $length)
{
// string exceeded length, truncate and add trailing dots
return substr($str,0,$length).$trailing;
}
else
{
// string was already short enough, return the string
$res = $str;
}
return $res;
}
Oooo i came up with something that works but not works completely... Id like to share
div.string{
height:15px;
overflow:hidden;
}
It solves the problem that it will hide the whole word that wont fit in to the end of line.., because of the overflow and the height is set to one line only. However the above still dosent do the Problem shown by Rufinus:
iiiiiiiiiiiiii
wwwwwwwwwwwwww
This is a function picked from smarty templates that shortens strings without cutting them.
function str_short($string, $length = 80, $etc = '...', $break_words = false, $middle = false) {
if ($length == 0)
return '';
if (strlen($string) > $length) {
$length -= min($length, strlen($etc));
if (!$break_words && !$middle) {
$string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1));
}
if(!$middle) {
return substr($string, 0, $length) . $etc;
} else {
return substr($string, 0, $length/2) . $etc . substr($string, -$length/2);
}
} else {
return $string;
}
}
It all depends on the font. Of course, you can use a monospace font, but that isn't a solution. Anyway, why would you like to do this? Even if you manage to make it work on a certain font, it might be that an user doesn't have it. Then a different font will be used, and everything may break...
It would be basically impossible to do this in PHP with a non monospace font (even with a monospace font, it is difficult to tell exactly how long a string in going to be in a certain browser. The only way I can think of doing this in a browser is to put it in a and set the width of a the span to be a certain width then use overflow: hidden.
Depending on what browser you're using, this one line of CSS could do the trick:
div.string {
word-wrap: break-word;
}
If you know what true-type font the browser is using, you can use the imagettfbbox() in the GD library to calculate the width of your text. Then iterate and drop characters off of the end of the text until it fits into your div.
This may not be very efficient, I know that, but it does the job. You could fine-tune and optimize for your specific solution.
<?
$width = 280; // max. width in pixels that the text should have
$font = 'C:\Windows\Fonts\verdana.TTF';
$text = 'The quick brown fox jumps over the lazy dog';
function getWidth($text) {
list($x1, , $x2) = imagettfbbox(12, 0, $font, $text);
return $x2-$x1;
}
while (getWidth($text.'...') > $width) $text = substr($text, 0, -1);
?>
<style type='text/css'>
#my_div {
font-family: Verdana;
font-size: 12pt;
border: 1px solid black;
width: 280px;
padding: 0
}
</style>
<div id='my_div'>
<?=$text?>...
</div>

Categories