How can I use IMagick to resize text based on character count and image size - draw

I'm currently trying to create a meme website site, a problem I'm having is I can't get the code to work which should shrink the text when there's a large amount of characters.
Can anyone point me in the direction or does anyone know why my text is not getting smaller when then wordcount increase.
As always thankyou for your help- much appreciated.
<?php
$color = new ImagickPixel('#ffffff');
$strokeSize = "2 : 2";
$text = "This is a load of text that should change in size when long.";
$fontsize ="55";
$draw = new ImagickDraw();
$outputImage = new Imagick('_img/user_memes/large/user_1/chicken.jpg');
// Get the width and height of the image
$imgSize = $outputImage ->getImageGeometry();
$imgWidth = $imgSize['width'];
$imgHeight = $imgSize['height'];
$draw->setFillColor('#fff');
$draw->setFont( "fonts/impact.ttf" );
$draw->setGravity(Imagick::GRAVITY_SOUTH);
$draw->setStrokeColor('#000');
$draw->setStrokeWidth(1);
$draw->setStrokeAntialias(true);
$draw->setTextAntialias(true);
// Set the desired width of the text to 90% of the image width
$textDesiredWidth = intval( $imgWidth * 0.9 );
$textDesiredHeight = intval( $imgHeight * 0.9 );
var_dump($outputImage->queryFontMetrics($draw, ''.$text.''));
// Create an array for the textwidth and textheight
$textProperties = array( 'textWidth' => 1 );
// Increase the fontsize until we have reached our desired width
while ( $textProperties['textWidth'] <= $textDesiredWidth ) {
$draw->setFontSize( $fontsize );
$textProperties = $outputImage->queryFontMetrics( $draw, $text );
$fontSize++;
}
echo "---" . $textProperties['textWidth'];
$outputImage->annotateImage($draw, 0, 5, 0, ''.$text.'');
$outputImage->setFormat('png');
$outputImage->writeimage('_img/user_memes/large/user_1/spork_thumbnail.png');
?>
<br><br>
<img src="_img/user_memes/large/user_1/spork_thumbnail.png" alt="some_text">

Related

mPDF image to cover page with crop and no distortion

I've tried every conceivable combination of getting something that seems so simple to work.
I need to place an image on a page, A4 (210mm (h) X 297mm (w)) and have that image 100% height, i.e. 297mm, then stretch the width proportionally to that and just crop the overflow (i.e. hidden in css overflow). I've tried every combination I can think of with $mpdf->Image(), or like I've done everywhere else in the PDF file, use pure HTML and CSS. E.g.
<img src="path(to/file.jpg" />
or
<div style="background: url("path(to/file.jpg") center center no-repeat;"></div>
again, with all possible CSS configurations I can think of.
Is it not possible to stretch and image to fit the entire pages height while maintaining the aspect ratio and crop the image on the sides?
I've seen background-image-resize on MPDF full page background, but again, nothing.
How can I get an image to be 100% of the page's height (I don't care if I have to define the height (i.e. 297mm) or if it's a percentage) have the image scale proportionally to that and crop any excess of the image on the sides.
I'm sure I've just missed something obvious here. I can't see what I'm doing wrong (I think I'm stuck in a loop in my head now).
An example of what shows up fine (as expected) if I do an echo and view in the browser
$html = '<div style="
background: url('.$imageSource.') center center no-repeat;
position: absolute;
overflow: hidden;
height: 297mm;
width: 100%;
background-size: cover;
top: 0;
left: 0;
"></div>';
However, doing the same with $pdf->WriteHTML( $html, 2 ) and then $pdf->Output() the image is 297mm in height, but the width is distorted (i.e. it doesn't stretch proportionally to the height).
Here is the resulting PDF (with a placeholder image)
This is what I'm trying to achieve
So the resulting PDF gets "squeezed". Instead of extending the width proportionally to the height (297mm).
PS. Sorry for the lack of actual tested code. But there are just so many different combinations I've tried that I can't reproduce all of them.
PPS. Using latest version of mPDF. Grabbed from GitHub three days ago.
Since I had a lot of problems getting the logic, CSS and math right I thought I'd share my final working solution here with anyone else struggling with this.
Start with the function
function image( $containerWidth, $containerHeight, $imageSource, $top, $left, $border ){
// Get image width
$imageWidth = getimagesize( $imageSource )[0];
// Get image height
$imageHeight = getimagesize( $imageSource )[1];
// Get image aspect ratio
$imageRatio = $imageWidth / $imageHeight;
// Get container aspect ratio
$containerRatio = $containerWidth / $containerHeight;
// Decide if image should increase in height or width
if( $imageRatio > $containerRatio ){
$width = ( ( $imageRatio / $containerRatio ) * 100 );
}else{
$width = ( ( $containerRatio / $imageRatio ) * 100 );
}
if( $border ){
// $border array: 0 = thicknes in points, 1 = type (solid, dotted etc), 2 = color
$border = 'border: '.$border[0].'pt '.$border[1].' '.$border[2].';';
}
return '<div style="position: absolute; top: '.$top.'mm; left: '.$left.'mm; width: '.$containerWidth.'mm; height: '.$containerHeight.'mm; overflow:hidden; margin:0;'.$border.'"><img src="'.$imageSource.'" style="width: '.$width.'%; margin: 0 -'.( ( $width - 100 ) / 2 ).'%;" /></div>';
}
Then for a centered full page image
$image1 = image( 210, 297, $imageSource[0], 0, 0, null );
Or two images on top of each other, one with a white border
$image2 = image( 105, 148, $imageSource[1], 15, 15, null );
$image3 = image( 105, 148, $imageSource[2], 133, 90, [ 10, 'solid', 'white' ] );
Output
// mPDF options array
$pdfOptions = array(
'mode' => 'utf-8',
'format' => 'A4',
'img_dpi' => 300,
'dpi' => 300,
);
// Declare $pdf and set options
$pdf = new \Mpdf\Mpdf( $pdfOptions );
// Stylesheets
$style = file_get_contents( __DIR__ . '/path/to/stylesheet.css');
$pdf->WriteHTML( $style, 1 );
$pdf->WriteHTML( $image1, 2 );
$pdf->AddPage();
$pdf->WriteHTML( $image2, 2 );
$pdf->WriteHTML( $image3, 2 );
$pdf->Output();

vlc pays video created with libavcodec at wrong frame rate

As a test i'd like to create a video that has a framerate of 1 fps. When I create it like this vlc still plays it at 25 fps. does anybody have an idea?
AVFormatContext* formatContext;
avformat_alloc_output_context2(&formatContext, NULL, NULL, "test.h264");
AVOutputFormat* outputFormat = formatContext->oformat;
AVStream* videoStream = av_new_stream(formatContext, 0);
AVCodecContext* ctx = videoStream->codec;
ctx->codec_type = AVMEDIA_TYPE_VIDEO;
ctx->codec_id = CODEC_ID_H264;
ctx->bit_rate = 500*1000;
ctx->bit_rate_tolerance = 0;
ctx->width = w;
ctx->height = h;
ctx->pix_fmt = AV_PIX_FMT_YUV420P;
ctx->time_base.den = 1;//25;
ctx->time_base.num = 1;
this is an old question but I hope it help others with the same problem
AVStream has an explicit time_base which is set by muxer according to container.
as stated in AVStream.time_base comment :
The muxer MAY use the user-provided value of
AVCodecContext.time_base as a hint.
you need to use av_rescale_q() to set your RAW FRAME pts to a correct value :
/* AVFrame* */ raw_frame->pts = av_rescale_q(my_pts, ctx->time_base, videoStream->time_base);
.
.
.
/* AVPacket pkt; */
avcodec_encode_video2(ctx, pkt, &got_packet);
.
.
.
av_write_frame(formatContext, &pkt);

How do I create an inner drop shadow in text with php Imagick please?

I'm at the beginning of the learning curve with ImageMagick.
I have successfully created some text on a patterned background with outer light drop shadow to give the nice appearance of cut-out text.
To finish off the effect I need to give the text and inner dark drop shadow.
Are there any ImageMagick experts out there who can help with the php please?
This is my code so far which I'm happy with.
<?php
header('Content-type: image/jpeg');
$background_layer = new Imagick('test_background.jpg'); # background image
$d = $background_layer->getImageGeometry();
$w = $d['width'];
$h = $d['height'];
$text_layer = new Imagick();
$text_layer->newImage($w, $h, new ImagickPixel('none'));
$text_layer->setImageFormat('png');
$ImagickDraw = new ImagickDraw();
$ImagickDraw->setFillColor('#484848');
$ImagickDraw->setFont('Helvetica-Bold');
$ImagickDraw->setFontSize( 40 );
$ImagickDraw->setTextAlignment(2); // centre
$text_layer->annotateImage( $ImagickDraw, $w / 2, 50, 0, "Stuart's\niPhone" );
// create white drop shadow on it's own layer
$shadow_layer_white = $text_layer->clone();
$shadow_layer_white->setImageBackgroundColor( new ImagickPixel( 'white' ) );
$shadow_layer_white->shadowImage( 70, .3, 1, 1 );
// composite original text_layer onto shadow_layer
$shadow_layer_white->compositeImage( $text_layer, Imagick::COMPOSITE_OVER, 0, 0 );
// composite shadow_layer (which now has text AND the shadow) onto image_layer
$background_layer->compositeImage( $shadow_layer_white, Imagick::COMPOSITE_OVER, 0, 0 );
echo($background_layer);
?>
I'm too new to post images so you can see what I have so far at
http://www.avforums.com/images/temptest.php
Any help you can give to add an internal dark drop shadow in the text would be appreciated.
Thanks
You are using Imagick not Imagemagick directly and may want to add that tag as well.
I do not use Imagick but shadeimage should do what you want in one go?

How can I display images similar to Tumblr's photosets?

I'm converting my wife's blog over to Wordpress and I want to display image galleries similar to how they're displayed on Tumblr. Here's an example of the layout:
http://bobbyandmaura.com/post/8195960363/photoset_iframe/bobbyandmaura/tumblr_lp2nebJFEW1qhd8ae/500
I can handle the markup and CSS for displaying the images. What I need help with is understanding how I can create this dynamically. Tumblr is smart enough to dynamically display different quantities of images while still always filling all of the space. Here's another example with fewer image:
http://bobbyandmaura.com/post/6700400507/photoset_iframe/bobbyandmaura/tumblr_ln23gi8EqU1qhd8ae/500
Hopefully I can use math to create a dynamic solution so I don't have to manually create a bunch of different possibilities.
OK. Solved. I got a hack to show WP gallery as Tumblr photoset. It is not as customizable as Tumblr, this will only show the first image as the cover image(larger) and rest images in small grid like set.
You need to edit wp-includes/media.php file. If your theme as any other gallery file, you have to edit that. Edit at your own risk as this is core file of WP. If you update your WP in future, you have to do this again. Sorry, I have no time to write a plugin.
Search for "foreach ( $attachments as $id => $attachment )" in wp-includes/media.php and change the following (replace the foreach loop)
$ccg = 1;
foreach ( $attachments as $id => $attachment ) {
if($ccg == 1)
{
$link = isset($attr['link']) && 'file' == $attr['link'] ? wp_get_attachment_link($id, large, false, false) : wp_get_attachment_link($id, $size, true, false);
}
else
{
$link = isset($attr['link']) && 'file' == $attr['link'] ? wp_get_attachment_link($id, $size, false, false) : wp_get_attachment_link($id, $size, true, false);
}
$output .= "<{$itemtag} class='gallery-item'>";
$output .= "
<{$icontag} class='gallery-icon'>
$link
</{$icontag}>";
if ( $captiontag && trim($attachment->post_excerpt) ) {
$output .= "
<{$captiontag} class='wp-caption-text gallery-caption'>
" . wptexturize($attachment->post_excerpt) . "
</{$captiontag}>";
}
$output .= "</{$itemtag}>";
if ( ( $columns > 1 && ++$i % $columns == 1) || $ccg == 1 )
$output .= '<br style="clear: both" />';
$ccg++;
}
Demo gallery can be found at http://ontrip.in/the-ca-cur-badi-forest-resort-gorumara/
You may need to modify your Gallery columns number. You may select the cover image by alternating the image order in Gallery insert box.
My friend Victor Gonzáles developed Aurum to manage proportions and have that nice effect. You can get it here: https://github.com/aficiomaquinas/Aurum-CSS
You then additionally group the images by similar proportions(w/h) with a tolerance of 0.2. So that <0.2 is one group < 0.4 another, < 0.6, etc.
Then have a random chance of spawning them in 1,2,3 columns / row.

New Background Image on each page reload

How can I display a new background image on each page refresh on a website (using Wordpress if this helps anything)? I would also like to take into account different screen resolutions, and proper handling for this. Any help would be greatly appreciated.
Have you seen this page in the wordpress codex?
It explains how to rotate the header image. It shouldn't be too hard adapt it for your needs.
Just have your own script that randomly returns pictures each time it is accessed. I have one that I wrote in C at the URL below that returns a different pic each time.
http://www.scale18.com/cgi-bin/gpic
You can generate it in realtime with GD library
To detect screen resolution, you can use client-side javascript
screen.height
screen.width
To display a different image, you could probably use a script to generate a random number and display the image that ties to it...?
You could store the "current" imaage in the session and just check each time you generate a new random number, that it's not going to display the last....
This is what I use with Wordpress to randomly rotate the header images on my site.
Someone else wrote the code and I can't remember who. Put the php code below into a file named rotate.php, and then put rotate.php into the directory of images that are to be rotated (i.e. "headerimages"), and rotate.php will draw from them. Call rotate.php from your CSS style sheet in whatever DIV is used for your headerimage.
I don't understand what you mean by being able to handle different screen resolutions. End user screen resolutions?
<?php
/*
Call this way: <img src="http://example.com/rotate.php">
Set $folder to the full path to the location of your images.
For example: $folder = '/user/me/example.com/images/';
If the rotate.php file will be in the same folder as your
images then you should leave it set to $folder = '.';
*/
$folder = '.';
$extList = array();
$extList['gif'] = 'image/gif';
$extList['jpg'] = 'image/jpeg';
$extList['jpeg'] = 'image/jpeg';
$extList['png'] = 'image/png';
$img = null;
if (substr($folder,-1) != '/') {
$folder = $folder.'/';
}
if (isset($_GET['img'])) {
$imageInfo = pathinfo($_GET['img']);
if (
isset( $extList[ strtolower( $imageInfo['extension'] ) ] ) &&
file_exists( $folder.$imageInfo['basename'] )
) {
$img = $folder.$imageInfo['basename'];
}
} else {
$fileList = array();
$handle = opendir($folder);
while ( false !== ( $file = readdir($handle) ) ) {
$file_info = pathinfo($file);
if (
isset( $extList[ strtolower( $file_info['extension'] ) ] )
) {
$fileList[] = $file;
}
}
closedir($handle);
if (count($fileList) > 0) {
$imageNumber = time() % count($fileList);
$img = $folder.$fileList[$imageNumber];
}
}
if ($img!=null) {
$imageInfo = pathinfo($img);
$contentType = 'Content-type: '.$extList[ $imageInfo['extension'] ];
header ($contentType);
readfile($img);
} else {
if ( function_exists('imagecreate') ) {
header ("Content-type: image/png");
$im = #imagecreate (100, 100)
or die ("Cannot initialize new GD image stream");
$background_color = imagecolorallocate ($im, 255, 255, 255);
$text_color = imagecolorallocate ($im, 0,0,0);
imagestring ($im, 2, 5, 5, "IMAGE ERROR", $text_color);
imagepng ($im);
imagedestroy($im);
}
}
?>
JavaScript is probably your best bet for this one.