I am using this Kohana Captcha module in an application. The image renders correctly on my local environment but on our dev environment it returns the following:
�PNG
IHDR 2 1îµM JIDATxÕ|il¤ÉyÞSUßÙýõÅr8$ç¾8«Ñ=¼YÁ¶àݵ9 È°£ÀH #üÌß $#¤ÀFäì$¬X²VÒÚÒjiµëÕÜË!Co²}~gùÑMvl»I$¿`_W}u
¤YZúHPÝ©²Vq×ÝG4øÅ5tªëÕÏN%*v6óB^ï¢kT×A (Å]ïç²m¶Þ^HåsáEÜã\Hµïq5 ni©#)Bé£ûÄ»¥àåsýí5
ª±êgáùØelCóBQý,#¡¤b¦ #QãÚN¶¦o¾pµâEBÚºfk©1ÒlFIÜ qCÀ¥ô¢ªM4µÍFLO¤#Éæo:&ïv¤T~Áoo´C"jè±êÌMánoÌj(*.¥ôqS¿SàB*ð0¥1[×l]3Xsö`:u])¢¥¸heÜFÜHö' !g¹¼Vvs} ÒE§ÛQ~ñ"Ñѵê4M¢ßDxî¤F!?[c¨î^(ä6ÁèEÂ0BlÙºfiLk&í`2f2¤R^ÄC!wZS
¦c¤ Ù<d>xÅ#$ûÍúD¯#¥
J{0Áa3êBñ½:Ô©]ÕYÖÀ»
C®T)à¥Ð)Ý6cbi¥iËJùp£Èço=RÐL]mj¥ËåF é|$z£ìK¤
Êa»kÞ1ÓT ÀýÀ0Xë};a#BBüH§t0tcJHÌÐb Ò¸ s© )ÒjÄ2¶Rª¸TòÛ¹Ê]÷èq½$ûùbXyì(FÁhuwdÈlÇ!#DßRð¢ö$µ©±sSª© ¥ ÓH¨*N*¾KËe(^´Tts!ÄéjrX!éäú\!r[RKû&ªëªZÑn&è®ôØ Ô(áBVuµmRÚ¶snE?,xaUÒÚFs£¶ª8뼸\~ôHå5Ä;cM¾#$}$µþ0ym(§ö ¤vÒ! PñDÌjIº~KÖÝþÈçrv½¢SjÕ.¦ÆvBè˺â4µuÍÖ©±mpjmWZ© w4ALÏ"ÿ± Hj$e}ZAñ±â·I¡¡·«Ý¸lÇ SÂÈvòÆó`jÌÖYÌÐÆiB ÅåâÜù¡4=ÊÍxpø(Ò¯KÉ-'ýÑ(¶a÷Çá56R¼ê, ðê¡?Ú5\£6\R[×Ú#a±;míüPJåfó<h>
g(Çz-3m0*©¢¯,ûù»%wEÔ!TÛm'âv+^kÓ `I#
CxÑM²§qòÖ-cXö&ÖlZ¡Pø~ _(ÀN6A2Jeg
"Ü{û´K9éÌñDj4ÎÌÝiUο·:ÿjpa7©ìnG±Eü¨¡S]#¤v,¥`LµÙûåLJ±Åß6s51G[tKª¤í;N/B±ó+¦±ÎátöA^DMtÝm¦;ô Ç°7CêJªÊ²_YôÜ%_D2ë53'FB`wÇ_x®ëö{P©4ve»*ÚciUɹ3¦ÏLóÃ:ýÝ?|/ôµw{fïv¯Í§mgIoi[Æ6,;ô}!UÀUë¸ì«{XÌ%¢H5Úq4½ö /y}[©N^ø·ãVf{ûo¬\Ëçï¢J³ßóÌñ/I¦ ĺËtrâOg¾5¿'ÁLÆ"/hÍvCÁA}¤DÆMwW ô.ÿ{^E_îê_î
}o:5·²¥±3ç.d^!Ðm5F¬áµ¢|±
Ù[ÂáhÕç÷¿»¸|u]Í'^Yô¾µbuZÉá8 BIçTá~Ù]nQÎÿý+g_¦ëìÓß¡Fä"äJ*îJaKÉÅ]ÉããóGO.LwÌLô±ÈIÂðéùsO:0ºd9~L&¢`2â/x¡ÏÛ°lÙé³W®í8P (£¦cºù`óX-¾üÅrfRï8]ÚùhõzáQc(ä&\ÍféQ !¤{àÌkOÿôkYZ*h¶Ùy¼ô¥óO:Ý)Ý6Eñ×#"Bet øÙWÜß<y>c:'='íö]ö/8©
eÒ¯^)°V ÚJHnRv¦pü³]BQÇj&ëåÚ¦äî6ÛdN8{NC
y÷[óÉxfÔ Çõ_¼ñ¦[¤ÓÜÀËÃrPÏÎrÉý Þ|î_¼:ðÄ(Ð
ë¹láájq!§cr¿v
ÓÄÀhNIÌ~Ú]]]a-~cmdòÆyÊÄÀÈòÈèúÈ°``ty`t
ë+ÎÂl"®-¤ÚèÔr!ÓpåÌç^tFⶣ¯,ÛäÓ¨7ܼßSPäc¿Õ_McIÝþNÔÃcËd÷b JcÅiwð.B#CöâٰتïNÊHd§$Kr(X©øÑgOpsåüûïDAëJôÿü¥®GôêÄ|Û; Hvº#çkñ?i|¦Å\¢²8¸4ytéAW¶(Uf,%ÂÎÅÓW>=ûôL¦·TÌÆÜòÞe ìôÁ ì4¾øÞ¡QiÄ ¢XRKsM¬ ¦S#¦»ëuKFjàN3© ø·¤RT×ÂOÅ{j/ñµÅ§ê¯WrSKÃ×NSßÅáîSG ¬|2·xí»R(>¾¯ÚÑLõá*Æ÷F&¯÷K¾]ÅDAQ_Ú¡D¾<k>¼]¨KÁõ·VB¯jPª>©r #¦wK5¾u°ÍÓª%pAvíN
%¹R
³o¯Õú(ÒÿdmýK멾l}z¥:R\2CÏÏ®}¿?ôõ¦Ï5J¹ø߯øf,¸òÚíu Ró HAÞý3óS±O]ØÓoüÆ;W£ÿùõñ§ºA¬.³¡aÉîÕ·§¤®3:F'óÕ'Áx%Yð¤Õ(~NJrA©ý¤Ä¡Ým'ìâìþ«x2ÃÝÕ¹«Õà~¤k¤vÜS Ô0øaÇklU×ØÕ_|òó÷LP,Q^YÿÁ7ìjñUmCH(ýµÔùËοúÄ#IB(¡|ìTÙBÇpmEB´ÅNv¬N΢î'¬Z. pQu]'kØJdN§3ûÐÎÄT#ä¥Å|} /b¶1ÿÑTq!¯oÏQk,AaäÜòÅÏÍZ{»Ð¼µÄ_þËÈÏMÒ2B ÈÑR6]}ú¾ÜËFÿãk+¿ä$S©ù§·]¥Ðp ¬
ZÑ¿Ý{³F÷±9¯Eë¯s-£ 1ª
Ñl=oÜd×D$γ^
B 1䵯Àtf¤&EsÓ+Ã)B Z ¥!j·è/Ý>½Úøpr"ùÆæQ¥ØäÂ{ HðÌK©'I¼õÝÜĹaYÚSÏg¥#W¢æHæÜø#,¦×GM1RB¬¤¡+A8hOÖüÉ`Ò[×+Õ?bÂý0«4_?VZgUöÛ)E«+¥zm[RÜ
3þÒ':z´
·?ÅÎý¿ÓY.ÿþ*e ض><fw> ¢HÞørçF^)Dàå¨RÒÃNL7^}#ÑŤß'L>âÉZØ1Ô^:ø±>Ó|¾
"^¶®IA5tÑ~§ê\¨Ç¬ÍJ0pyØån½Gó_úʽQF¡öî?½×+Õä>^¸-ÌÝ$´zúbìåW3ï|?ëj?¥$Ó Á¥gjáënÒ¨åÀ¢HDaÕ
'"TÙJjØIÚö&B#©iTËæ²^Êz)moY6ëÊ©DÀe·-¹3tÉ¥Ú½R¯ÉÊM=Ñ ¹XÍVf±f¡8ÜrásO?|ùwnÚA/6dsq=ñ£7*P0BÁ*m1gJ~=ýp:ª9æÛÖ¤;µá1RêÁ-©¤T¾·=Kù2?Sé>éÐôzMÛE\
¢!¡Ë¢)u3ÒAeV~" züôn(ʨÎpA¾6"³î+Å̱îj¢0¿^ͨhA7²wRHîfA¡òÅ/Þyâ(PQsØ>è{ï¯.G Jµ¯:9Ú¤À7þxùòç¿û}ïWRZ_U Â¥§jleþ~TZa¸É|Ûô"÷ö3KFmk¤P³®;ôд
Ø °t*Z{·®!v[O¼ÏP#~Ƶ"ÙfTÙµ2uÖavjE)hA6}%TT9L/¯}õêàñ *,(àÆG'¯}p¶ÚKTK÷aõ¿,iRAüøü{U2þê?è øàÍR ¬ÀR#TÅ/qÔ`F¨É(¦ ¥û0´t ÄFúBlõ:»1bf,FT PtåF©Á!ZÌj;F6 ^Õba5ý'¹äîaâ×}¤ðÛðQ²£¦G(·yDßûáåÉ#m*T
I5½sf
õ²¢GPªÛûÞX;mæ9çó¯g4 Xfîr÷-ÛÜß°$³º![rîÞ|Ä$ÏXdëIÜy*©F®t D¬Ü)¹Ùâf"d d»ªë.,A7ðÄáÊÏÓ~ý]×úùv×2ïû|!GWV
TBî?´îÚ&cUÀä7õ©÷ÿ²_ס J¥(æraoEQ*#q ~hÜù
P.ì>Ãt4¯!r½szÃ/wU#« n}sFDj[#A0Ë ~¸;¦;¡)B*Ùrà ßøö¨_xêó÷ÍNtßùöa a±Búkm½é}».MPLÀh¨uÅÊ祹ðõX|Ào¾ï¯Î7Y`øfCVÓÏGV®ó¨SÐÜ
²ÜìÒ À'c?.V׳dä·MÏé7/ýþPõóä÷VVoh¶Awd+)£4n)¡dÄ¥JV}!B¨ÆzNTSëÖ ¹ä^pµÂ¦½úÕGÎn 0}ôëo\èOiOâj#È?ëÒZOиÃV" yÎ ¥üwKï¿Uzçç_ê¼ô¼õæUv÷7P\Í=ËC :&6Göæ£#æ½êz,ï1ÿW'tX¾^¼ú'3ÕRiÞ¤jî׺"ÌFnxÌtö¾ôÏ>ÊôÔó-ö§ôÞb½Ún´7M£©þ_ÎÖÅÃû~w¯!Cqõý²RBõ£7×zSMïÍ b¦g«åB1 ~)5*#ºsaz¼Vj
©±¸ûó¶³R:¥Þû7SÞ¡34fj»ÝE ÙáN Pjéæ\+vÓñ¥ßúýkUgqÝúÖ\^I°¶s¿Ë;u)ùà?ÿ»¥gíÏ^qRêÚßw^Ê£ÈL(,\jAøÅUàR«OÓlr5SíM>:ó¥¾®Ó %Õíÿ½xãÍÓ°#Û°TRMþøÓc]#Ïg:%J)©2Ǻx$ÜlsùÑ.]yõîç¾p4pýÜTæÏÿø²[2èt{å¶T¨
£^þ½G·p£±,HJ¤:ñìËÉá1óç?+ðv©Rª[½é(RØ_ ÝK÷Å ¤y'wóOsC % µ¥ªµ$ÈutuwïîëÎÏåßýú[-¾¶)é&í«×N^Zn|xíÝ¡ïó¼µuebzoj{ÞäÌÚ~¸¼øk¿÷¯)%£7>q]ιʰg^J8gÿǽØxê(>¿* #çè¶N¿ÞÛq|K0TÙ{¹÷ó3ïäJ«ÈZ3µ^"øô³cg²
NÞü_ç~þöpcÁÛÙQë¼V×Jrcö(ÖuÖØ#Å7ªTëòß*¼ùÿ
JmyÃr¾ Ìö;3«c|»ïDÊNÔðÖ¼¿p3?óaÎ_ßÜÜÃW6%*
¨¦×ØàØzàê÷owûnn6f°£T DÆ'ª¾löÔ[Üpßß.µwgfº¶Ç^éR
ÑtÊRX^Ü¥0ðdà
/÷Øn»")ò¾öÓÄðéìñ+cçW:zÝÏÎ_xv^IÌO§§nöÌÝ9B|gÛ®H©Ü# ¿2ûÂk÷ÞÿþèþïÙvßBJë*h(Ú%µ:üÊ÷¯Ï¬Ü.ñK]u¥« #Æ4E¿«e'±©=S7{ dz*Ç/¬¿¸Ëk¿±Â×»¦3ó÷ÓÒQÀº!3v~ÀOºænJªáQ°átvüÓò]§%7=PSRÖÎåèa·~Ùt1½Qè¬~Î-Ç?\ùð¯G&Fή¿¸rñI%ùè¹ÕÑs«JµEgþ~úÆMSe-Û åyD§?é|¼r¾ëýÕsµßSªýy
ÀDÓQ 무Ä3¦n1 bã¡n5¹øó+Hã©,.&³×7P¬Ø½ë½S7z§ûd78?2ï,v)u)ùÍùRfãâÁÎvK.ªÔ²iãs
¿6Të 8EÈD+Ù;M£U_òºUC?µT£¿ú§²Ü" Ûd 9ûNξóQ¿¦É¾áÂÀh.}n9Ýí9é À½=û[é1R%6ïO©]ÜM¿ÚN" `[µixHr_0R²
ÍúË¢ëùÎñtvóóαeyDç&3·o$þkoWùÄøòñ{×zö·Ò=¸sÅ6¢²¹IçhÛ (3Oò(qÊ a2ÉÆËçáøW®w§³Mñ3¤cË>W
«ÎêóÓïí{è= #ilz£Íjýѽâ®
x #Ó¨®oR#5¤½bô·B ×Ö;)irM_gÄÐèÎE¼Ã9{#(¸Õ ¥DðöÆd"P¤ÉÒ*~ËÚ:ªÓh#o ¸ríÿ¾Ì/ú2VÂb#TQöyõG+l£EryS#íæ"i¡³0ØîÞäê fëlQuN5ä}
˾ÚÏ_ÅFq,ͱ´Þ åBgMtÍa± ZÐó8c¥ PJijó7Ô¾ fn
BP-clìËtë47^©Üû·E04¢mMDè¤l
hb0ÁÔHÿUtéLU IEND®B`
This is the render() method:
public function render($html = TRUE)
{
// Creates $this->image
$this->image_create(Captcha::$config['background']);
// Add a random gradient
if (empty(Captcha::$config['background']))
{
$color1 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255));
$color2 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255));
$this->image_gradient($color1, $color2);
}
// Add a few random lines
for ($i = 0, $count = mt_rand(5, Captcha::$config['complexity'] * 4); $i < $count; $i++)
{
$color = imagecolorallocatealpha($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(100, 255), mt_rand(50, 120));
imageline($this->image, mt_rand(0, Captcha::$config['width']), 0, mt_rand(0, Captcha::$config['width']), Captcha::$config['height'], $color);
}
// Calculate character font-size and spacing
$default_size = min(Captcha::$config['width'], Captcha::$config['height'] * 2) / (utf8::strlen($this->response) + 1);
$spacing = (int) (Captcha::$config['width'] * 0.9 / utf8::strlen($this->response));
// Draw each Captcha character with varying attributes
for ($i = 0, $strlen = utf8::strlen($this->response); $i < $strlen; $i++)
{
// Use different fonts if available
$font = Captcha::$config['fontpath'].Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
// Allocate random color, size and rotation attributes to text
$color = imagecolorallocate($this->image, mt_rand(0, 150), mt_rand(0, 150), mt_rand(0, 150));
$angle = mt_rand(-40, 20);
// Scale the character size on image height
$size = $default_size / 10 * mt_rand(8, 12);
$box = imageftbbox($size, $angle, $font, utf8::substr($this->response, $i, 1));
// Calculate character starting coordinates
$x = $spacing / 4 + $i * $spacing;
$y = Captcha::$config['height'] / 2 + ($box[2] - $box[5]) / 4;
// Write text character to image
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, utf8::substr($this->response, $i, 1));
}
// Output
return $this->image_render($html);
}
and the image_render()
/**
* Returns the img html element or outputs the image to the browser.
*
* #param boolean $html Output as HTML
* #return mixed HTML, string or void
*/
public function image_render($html)
{
// Output html element
if ($html === TRUE)
return '<img src="'.url::site('captcha/'.Captcha::$config['group']).'" width="'.Captcha::$config['width'].'" height="'.Captcha::$config['height'].'" alt="Captcha" class="captcha" />';
// Send the correct HTTP header
Request::current()->headers('Content-Type', 'image/'.$this->image_type)
->headers('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0')
->headers('Pragma', 'no-cache')
->headers('Connection', 'close');
// Pick the correct output function
$function = 'image'.$this->image_type;
$function($this->image);
// Free up resources
imagedestroy($this->image);
}
GD library is enabled on the dev environment. Both environments use apache 2.2, php 5.4. Is there another server setting I need to enable?
This type of bugs sometimes bugs me, try to add:
die();
after the last line:
return $this->image_render($html);
Sometimes it works for me.
The text looks like a PNG datastream, only rendered by a text editor instead of an image viewer.
Related
Hi I keep getting this error:
Runtime Deprecated code usage - Imagick::clone method is deprecated and it's use should be avoided
It is always around this function:
protected function ImagePngAlpha($file, $x, $y, $wpx, $hpx, $w, $h, $type, $link, $align, $resize, $dpi, $palign, $filehash='') {
if (empty($filehash)) {
$filehash = md5($file);
}
// create temp image file (without alpha channel)
$tempfile_plain = K_PATH_CACHE.'mskp_'.$filehash;
// create temp alpha file
$tempfile_alpha = K_PATH_CACHE.'mska_'.$filehash;
if (extension_loaded('imagick')) { // ImageMagick
// ImageMagick library
$img = new Imagick();
$img->readImage($file);
// clone image object
$imga = $img->clone();
// extract alpha channel
$img->separateImageChannel(8); // 8 = (imagick::CHANNEL_ALPHA | imagick::CHANNEL_OPACITY | imagick::CHANNEL_MATTE);
$img->negateImage(true);
$img->setImageFormat('png');
$img->writeImage($tempfile_alpha);
// remove alpha channel
$imga->separateImageChannel(39); // 39 = (imagick::CHANNEL_ALL & ~(imagick::CHANNEL_ALPHA | imagick::CHANNEL_OPACITY | imagick::CHANNEL_MATTE));
$imga->setImageFormat('png');
$imga->writeImage($tempfile_plain);
} else { // GD library
// generate images
$img = imagecreatefrompng($file);
$imgalpha = imagecreate($wpx, $hpx);
// generate gray scale palette (0 -> 255)
for ($c = 0; $c < 256; ++$c) {
ImageColorAllocate($imgalpha, $c, $c, $c);
}
// extract alpha channel
for ($xpx = 0; $xpx < $wpx; ++$xpx) {
for ($ypx = 0; $ypx < $hpx; ++$ypx) {
$color = imagecolorat($img, $xpx, $ypx);
$alpha = ($color >> 24); // shifts off the first 24 bits (where 8x3 are used for each color), and returns the remaining 7 allocated bits (commonly used for alpha)
$alpha = (((127 - $alpha) / 127) * 255); // GD alpha is only 7 bit (0 -> 127)
$alpha = $this->getGDgamma($alpha); // correct gamma
imagesetpixel($imgalpha, $xpx, $ypx, $alpha);
}
}
imagepng($imgalpha, $tempfile_alpha);
imagedestroy($imgalpha);
// extract image without alpha channel
$imgplain = imagecreatetruecolor($wpx, $hpx);
imagecopy($imgplain, $img, 0, 0, 0, 0, $wpx, $hpx);
imagepng($imgplain, $tempfile_plain);
imagedestroy($imgplain);
}
// embed mask image
$imgmask = $this->Image($tempfile_alpha, $x, $y, $w, $h, 'PNG', '', '', $resize, $dpi, '', true, false);
// embed image, masked with previously embedded mask
$this->Image($tempfile_plain, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi, $palign, false, $imgmask);
// remove temp files
unlink($tempfile_alpha);
unlink($tempfile_plain);
}
All I was trying to do is change the image inside the PDF, but for some reason it won't allow me. I tried looking online but I could not find the same issue. Can anyone help please?
As explained in the Imagick::clone documentation, this method is indeed deprecated, and to be replace by an object cloning.
Replace the line $imga = $img->clone(); by $imga = clone $img;
I have the following code to print text on an image. I am also adding a debug box around the text. However, I noticed the text on the left lies outside of the box that PHP gives me with imagettfbbox.
This looks like an issue with the font swash. Is there anyway to account for this? Can I figure out the distance between the start of the swash and the actual position imagettfbbox gives to me?
I don't think this is an issue with the font, as I tried it with a few script style fonts and the results were similar.
<?php
$font = 'scriptin.ttf';
$text = 'Ipsum';
$size = 30;
$image = imagecreatetruecolor(200, 200);
$fontColour = imagecolorallocate($image, hexdec('11'), hexdec('11'), hexdec('11'));
$bgColour = imagecolorallocate($image, hexdec('CC'), hexdec('CC'), hexdec('CC'));
imagefilledrectangle($image, 0, 0, 200, 200, $bgColour);
$dimensions = imagettfbbox($size, 0, $font, $text);
imagefilledrectangle(
$image,
$dimensions[0] + 40,
$dimensions[7] + 50,
$dimensions[2] + 40,
$dimensions[3] + 50,
imagecolorallocate($image, mt_rand(1, 180), mt_rand(1, 180), mt_rand(1, 180))
);
imagettftext(
$image,
$size,
0,
40,
50,
$fontColour,
$font,
$text
);
header('Content-Type: image/png');
imagepng($image);
The code and font is available here: https://github.com/AydinHassan/image-swash-example
If you point a VHOST at the repository, you can just hit swash.php
Edit: This appears to be fixed in PHP 7.0.12 (bug #53504) so the code below shouldn't be required.
Based on a comment in the PHP manual I've written the following function to calculate and return the difference between where GD thinks the left side of the bounding box is and where the leftmost pixel is found:
function xadjust($size, $angle, $fontfile, $text)
{
$bbox = imagettfbbox($size, $angle, $fontfile, $text);
$width = $bbox[4] - $bbox[6]; // upper right x - upper left x;
$height = $bbox[1] - $bbox[7]; // lower left y - upper left y;
// create an image with height and width doubled to fit any 'swash'.
$im = imagecreatetruecolor($width * 2, $height * 2);
// set background color to opaque black.
imagefill($im, 0, 0, 0x00000000);
// draw the text in opaque white.
imagettftext(
$im,
$size,
0,
$width / 2,
$height,
0x00ffffff,
$fontfile,
$text
);
// set the min-width to its possible maximum.
$min_x = $width * 2;
for ($x = 0; $x < $width * 2; $x++) {
// each x-pixel (horizontal)
for ($y = 0; $y < $height * 2; $y++) {
// each y-pixel (vertical)
if (imagecolorat($im, $x, $y) > 0) {
// non-black pixel found!
$min_x = min($x, $min_x);
}
}
}
imagedestroy($im);
// return the difference between where GD thinks the bounding box is and
// where we found the leftmost non-black pixel.
return (($width / 2) - $min_x) - abs($bbox[0]);
}
This can be integrated to your script fairly easily:
$font = 'scriptin.ttf';
$text = 'Ipsum';
$size = 30;
$image = imagecreatetruecolor(200, 200);
$fontColour = imagecolorallocate($image, hexdec('11'), hexdec('11'), hexdec('11'));
$bgColour = imagecolorallocate($image, hexdec('CC'), hexdec('CC'), hexdec('CC'));
imagefilledrectangle($image, 0, 0, 200, 200, $bgColour);
$xadjust = xadjust($size, 0, $font, $text); // 1. get the adjust value.
$dimensions = imagettfbbox($size, 0, $font, $text);
imagefilledrectangle(
$image,
$dimensions[0] + 40 - $xadjust, // 2. move the left-side of the box to the left.
$dimensions[7] + 50,
$dimensions[2] + 40 - $xadjust, // 3. move the right-side of the box to the left.
$dimensions[3] + 50,
imagecolorallocate($image, mt_rand(1, 180), mt_rand(1, 180), mt_rand(1, 180))
);
imagettftext(
$image,
$size,
0,
40,
50,
$fontColour,
$font,
$text
);
header('Content-Type: image/png');
imagepng($image);
This gives me the following output:
I've run it with a few other fonts and sizes and it seems to be accurate to within 1 pixel.
captcha works good in my localhost usbwebserwer. In web serwer captcha image not showing. when open image in firefox see code:
ÿØÿàJFIFÿþ>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality ÿÛC $.' ",#(7),01444'9=82<.342ÿÛC 2!!22222222222222222222222222222222222222222222222222ÿÀ(x"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚâãäåæçèéêòóôõö÷øùúÿÚ?õ{¥Ãgieg§ìmNÞ8a¶É,aË’\)ùNðK|Äv‘Y“X˪¨ÚÜÛB-£•bx¥hB³ 1æo¼r褟˜°©5Ý&ÊËJ¶Õ, Ħ‚â#åZ G1rýÅR9þš²'K›h,®ôíÿe„ùÊЋ€Ê#Ü#VÄ[É*ÊÌJ3}ìŽè$õ‹þ¿«·Ü»iâ´i¦öm>í§G–cöh2°“ºÊã+Ø6rß=mÙjÚÌsMoyáÃ[2q9$ÈÇ;T« ¤6îBõÀ–íõ ¤–Ár]ÝÅŵ¯rñ’ª r2#áñÔ»tÒEoy¨Ío-¾£Ôb`æI¼éV6¨œ,ƒ¹¹#¤ï;Y‰Ev³ûÄ™·M¨¾¡x.nÙ‘ÙÑ>Ð]b(~##•q’¤3§Êq¸Ö$šd–1ßé–÷×+o:ÚÞ¢LŒxm¹Sµ6»+1'0, Œ·x}üS«Ú]\Zx²k1l‹Iµ ‘¤Y‚ \ð0#ÎXõé“ÇumðÒyn¼Eo¨kš\Žã‰s2±.̸+´àrªày§k…îo¾±¨é–ñÞI»)+^.õŒ‡ÚƒpÃm?6NßšµÛ¤‚IþÉ"”DIH…Ö±„aÃdnbNÔ<¥¸ç~\6¡áë«ínöîP—rEï{(³*9¾X±Ë$ãïgåÜ›M¹²»Õ--îÚÈFmä†ÞRüË‘4{¨ ÇÏÆìàäÏ,Sqc»µËúŽ¥¡CmG%º`É°¬Ä«$jåU3*î<© #ÒŠhçŒÇeªÃ1Œ$ûñîL[s¿ ˜yJŒ3ç ÀSæ6¾#·ŸÇm*£œÊ%žûS±- +¿$«K7‚GžÍtó©ÜØËka¤ÄâÜËöu%Šg#Ê #‘Ž¹â‰ÓJÉ°R¹½}z|w–6ØGiÓÉå¶ÐÊÛ‰\î8òÉwࣜTEå•õ¹â–9áO–A0ŒÆIhKd¬„Œœ8,\Œ¡h:-Œ’_Ì€ÆU/†ô*w`˜Â»pf ±n 2ƒE†“syT;eÈ‘ŒäžTœ’<Ö‰/õtoÊXeÒî´É'b‡toóR1¸‰$ÈCŸâÚÙ´5KúìKÜóøNóÅþ ¼ zÑVqPÆ¥¤c´þôƒ¼¯ ýÆÀ'öZ„5mË£~÷ê#co=¡Rˆ¬¤*ùóù$ƒµ6’wgå5¾^\¯…,¡B^MBYSæزmXò¥„ŠxÎHÚã;N®³Tׯ/í5Ý;O™|¼D%V 䃂ü—8U_˜åˆSZÊsç²Ø„•Ó´¯XØj¶Öò^é±Z#×WVí#ÂdNÊÿÕÒé3Oâk½ìw×·©o4~h‘JÄK4ŒêGÝ#ävùMsÚÖ²ðëN&ôn n,UŽB…ÉrH+×vyÎk²ÑYð×ÂÝ_L¸Ògß-Ïï#ÚѸ*r¯=1‡çŽ7í¦ä#‘м=©êÞ Ôï-.ŒZ4"¥Ä걇pÎÁ€ªBž¤Ÿök¦ð=æ£ÿ«j—eo-l¦6–ñ^š.B’ 3†\ÚNÀg‚ ¹O…ZõìqÀЫÝFï4 ÁµÁØ œ,ƒ åˆQ€2iŸÙŸÃr[‰´˜Þ;.‰p±Œå72°”$ð &Û¸ÒØåãðdòxí|+öØcˆQ<Ѽk“ð6°3ÐqÉ"½{ı\^økQÔ$±»‹PŽÎxå“dO´K0 å3† oâód„Ïû¶iI“ }ðF~SÂóŒƒCÂöžx‚êKe–ݨup) ®ÓÀ'-× }w[¢„h×rMm,ÂIÌAи?îÊnÙ¸àž‚Ê¸ÏÍŠ¬ÄŠ^ñ—ö^™áû=×(‘ÝÌ—& É Tpç3IÏnri|&Žy!Öu'6Èxƒ]Ïr}òÇÏ"í9aƒ†Î?ÁÙè]éÚíÔbVM0)BFYñÎËò«ž>\u"½Ÿáfœ–¾³êV³^Mæ#yJgV22(ÌAÜ« oñ¸ çYÆ1vëÿTnÙ¿¦ÝÜéÚEí¸¶½ÙG,¶Í$&$eRÌ»þD?À¹’ÞiÏ}¥^·ŠÞÒú{[};θTŽ|Ef±ÄŠTª†`œyy`‹EróÅ6ÜoøY÷ lÓ5t·?<vÕ2óæ#ù.!‚u¶9?u…[¤Ó^ßLÔ’HaÓ¢2¥±ù4„ã˜ÊìháŽåEEmëù e SÃÜÛI$:|¨îež8¬žXbF}æÄjHf%šNêMk‰î´ø>Ñ¥Ù[K¦ÊBºvÖÛ"ªà«ó`Pü¤½¸tRŠNMÙ=F—bÝÕ¬ïxñ4ùµdKHªù€ºC™U¼Ì…\ó‚pYys.£=šÄÚDÊR1=Éš}¹MÅBòpÛ~bëÈV%h¢³RÕÆDž¿¶‘-…ýíéÄ“òª‚ëóo#_rÎñ’¬AWªó˦è÷sD4…þÓR‰¹›#LJB’;t W9e'6ÇiEoJn£´»$–ÆÌwu©Ã;¼6qÞFÉ-µÄLî¨H 9)ó#iÛ÷ܱ&´f[ä™ná2I+¥Ï”#qI‡FyóÕÁ!ˆ¢³Ý¤2–™!Ô,£xå[Avñ}¤ ˜MªûAåz¨íÚ~`]¨X]É«!¼¹Ó>Á4ÌP«¾Ì!mÇsI’Tê:QE&í+!¥tC§ÙZ궖ªÑ[#‹P¢Ý ŠUŽDØ’Ì|°0~æA*jº´1³Ùÿiëˆäâ,†)nr<àåßÆÒ¤ÿt•V%¢Õ²KE{a|ÓÃr×PÜÀ²3B²yyEùOšXº®ÒAÕ™2QEJŠ–ã»[ÿÙ
Chrome calling:
Resource interpreted as Image but transferred with MIME type text/html
Here is code in my captcha:
<?php
/**
* #version 1.6.0
* #package Joomla
* #subpackage OS Membership
* #author Tuan Pham Ngoc
* #copyright Copyright (C) 2012 - 2013 Ossolution Team
* #license GNU/GPL, see LICENSE.php
*/
// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die();
class CaptchaSecurityImages
{
function generateCode($characters)
{
/* list all possible characters, similar looking characters and vowels have been removed */
$possible = '23456789bcdfghjkmnpqrstvwxyz';
$code = '';
$i = 0;
while ($i < $characters)
{
$code .= substr($possible, mt_rand(0, strlen($possible) - 1), 1);
$i++;
}
return $code;
}
function CaptchaSecurityImages($width = '120', $height = '40', $characters = '6')
{
$session = JFactory::getSession();
$this->font = JPATH_COMPONENT . '/assets/font/monofont.ttf';
$code = $this->generateCode($characters);
/* font size will be 75% of the image height */
$font_size = $height * 0.75;
$image = imagecreate($width, $height) or die('Cannot initialize new GD image stream');
/* set the colours */
$background_color = imagecolorallocate($image, 255, 255, 255);
$text_color = imagecolorallocate($image, 20, 40, 100);
$noise_color = imagecolorallocate($image, 100, 120, 180);
/* generate random dots in background */
for ($i = 0; $i < ($width * $height) / 3; $i++)
{
imagefilledellipse($image, mt_rand(0, $width), mt_rand(0, $height), 1, 1, $noise_color);
}
/* generate random lines in background */
for ($i = 0; $i < ($width * $height) / 150; $i++)
{
imageline($image, mt_rand(0, $width), mt_rand(0, $height), mt_rand(0, $width), mt_rand(0, $height), $noise_color);
}
/* create textbox and add text */
$textbox = imagettfbbox($font_size, 0, $this->font, $code) or die('Error in imagettfbbox function');
$x = ($width - $textbox[4]) / 2;
$y = ($height - $textbox[5]) / 2;
imagettftext($image, $font_size, 0, $x, $y, $text_color, $this->font, $code) or die('Error in imagettftext function');
/* output captcha image to browser */
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
$session->set('osm_security_code', $code);
}
}
here HTML:
<div style="position:relative">
<input type="text" class="inputbox input-mini" value="" size="8" name="security_code">
<img src="/rejestracja-enterprise-kwartalnie?task=show_captcha_image" title="Please enter the code you see in the image into Security code textbox" align="middle" id="captcha_image">
<a class="osm_reload" href="javascript:reloadCaptcha();"></a>
</div>
That is the image. You're just not telling your browser that it is, your browser interprets the data as text. Set a header to tell your browser to interpret the data as image:
header('Content-Type: image/jpeg');
The image data will have to be the only thing output on the page, no other HTML or text before or after it.
Ref Link : php imagejpeg()
Try This
ob_start();
header( "Content-type: image/jpeg" );
imagejpeg( $image, NULL, 100 );
imagedestroy( $image );
$i = ob_get_clean();
echo "<img src='data:image/jpeg;base64," . base64_encode( $i )."'>"; //saviour line!
i have this function that transforms image to trapezoid using PHP GD:
function perspective($i,$gradient=0.9,$rightdown=true,$background=0xFFFFFF) {
$mult=3;
$w=imagesx($i);
$h=imagesy($i);
$image=imagecreatetruecolor($w*$mult,$h*$mult);
imagecopyresized($image,$i,0,0,0,0,$w*$mult,$h*$mult,$w,$h);
imagedestroy($i);
$w*=$mult;
$h*=$mult;
$im=imagecreatetruecolor($w,$h);
$background=imagecolorallocate($im,($background>>16)&0xFF,($background>>8)&0xFF,$background&0xFF);
imagefill($im,0,0,$background);
imageantialias($im,true);
$nh=$h-($h*$gradient);
for ($x=0; $x<$w; $x++) {
$ni=(($rightdown) ? $x : $w-$x);
$p=intval($h-(($ni/$w)*$nh));
if (($p%2)<>0)
$p-=1;
$nx=intval(($p-$h)/2);
imagecopyresampled($im,$image,$x,0,$x,$nx,1,$p,1,$h-1);
imageline($im,$x,$h-1,$x,$h+$nx,$background);
imageline($im,$x,0,$x,-$nx-1,$background);
}
imagedestroy($image);
imagefilter($im,IMG_FILTER_SMOOTH,10);
$i=imagecreatetruecolor($w/$mult,$h/$mult);
imageantialias($i,true);
imagecopyresampled($i,$im,0,0,0,0,$w,$h,$w*$mult,$h*$mult);
imagedestroy($im);
return $i;
}
But i cant modify it to produce isosceles trapezoid, i think there needs just one small modification, but i cant figure it outh (i tried lot of things).
Can someone help?
Right, basically that code should generate the right values, but due to a bug has a lot of cludges in place to get a trapezium shape. The bug is that the copy of each line has the destination-y and the source-y values transposed. The source-y should always be 0, the destination-y should change.
There were also a few other small numerical bugs and double rounding at unnecessary points throwing off the results.
Also, the variable naming was atrocious, so I have rewritten it so that the entire function is clear.
Try the following:
function makeTrapeziumImage($image, $gradient, $rightToLeft = false, $background = 0xFFFFFF, $supersampleScale = 3) {
$originalWidth = imagesx($image);
$originalHeight = imagesy($image);
$supersampledWidth = $originalWidth * $supersampleScale;
$supersampledHeight = $originalHeight * $supersampleScale;
$supersampledImage = imagecreatetruecolor($supersampledWidth, $supersampledHeight);
imagecopyresized($supersampledImage, $image,
0, 0, 0, 0,
$supersampledWidth, $supersampledHeight, $originalWidth, $originalHeight);
$workingImage = imagecreatetruecolor($supersampledWidth, $supersampledHeight);
$backgroundColour = imagecolorallocate($workingImage, ($background >> 16) & 0xFF, ($background >> 8) & 0xFF, $background & 0xFF);
imagefill($workingImage, 0, 0, $backgroundColour);
imageantialias($workingImage,true);
$endHeight = $supersampledHeight - ($supersampledHeight * $gradient);
for ($x = 0; $x < $supersampledWidth; $x++) {
$cX = ($rightToLeft ? $supersampledWidth - $x : $x);
$dstHeight = $supersampledHeight - ((($cX + 1) / $supersampledWidth) * $endHeight);
$dstY = intval(($supersampledHeight - $dstHeight) / 2) - 1; // -1 required as zero-indexed
$dstY = ($dstY < 0 ? 0 : $dstY); // Rounding can make $dstY = -1
$dstHeight = intval($dstHeight); // Round the height after calculating $dstY
imagecopyresampled($workingImage, $supersampledImage,
$cX, $dstY, $cX, 0,
1, $dstHeight, 1, $supersampledHeight);
}
imagedestroy($supersampledImage);
imagefilter($workingImage, IMG_FILTER_SMOOTH, 10);
$resizedImage = imagecreatetruecolor($originalWidth, $originalHeight);
imageantialias($resizedImage, true);
imagecopyresampled($resizedImage, $workingImage,
0, 0, 0, 0,
$originalWidth, $originalHeight, $supersampledWidth, $supersampledHeight);
imagedestroy($workingImage);
return $resizedImage;
}
The essential mechanism of the inner loop, as before, is to take each column of pixels, along the x-axis and resize them over a gradient. It naturally creates an isosceles trapezium. In order to create a non-isosceles trapezoid, another gradient would have to be specified. Alternatively, a set of start and end y-values could be specified and the gradients calculated from them.
Whilst this example works along the x-axis, in either direction as before, it could just as easily work along the y-axis (or the image could be rotated 90 degrees, processed, then rotated back).
I need to make this effect with php. I know that there is IMG_FILTER_PIXELATE in PHP image filter. But I need it to be smoother and embossed? like in this image:
This effect will make any image uploaded by user become pixelated and the edge of the picture become red (I know IMG_FILTER_EDGEDETECT but I don't know how to use it to change edge color).
I have no idea how to do this.
As the last answer was theoretical and seemed to be not enough, I've created a practical example:
Note: This is far from the "ideal" and perfect pixelate effect function, but it does it's job. Feel free to edit it according to your own needs.
<?php
/* Function to make pixelated images
* Supported input: .png .jpg .jpeg .gif
*
*
* Created on 24.01.2011 by Henrik Peinar
*/
/*
* image - the location of the image to pixelate
* pixelate_x - the size of "pixelate" effect on X axis (default 10)
* pixelate_y - the size of "pixelate" effect on Y axis (default 10)
* output - the name of the output file (extension will be added)
*/
function pixelate($image, $output, $pixelate_x = 20, $pixelate_y = 20)
{
// check if the input file exists
if(!file_exists($image))
echo 'File "'. $image .'" not found';
// get the input file extension and create a GD resource from it
$ext = pathinfo($image, PATHINFO_EXTENSION);
if($ext == "jpg" || $ext == "jpeg")
$img = imagecreatefromjpeg($image);
elseif($ext == "png")
$img = imagecreatefrompng($image);
elseif($ext == "gif")
$img = imagecreatefromgif($image);
else
echo 'Unsupported file extension';
// now we have the image loaded up and ready for the effect to be applied
// get the image size
$size = getimagesize($image);
$height = $size[1];
$width = $size[0];
// start from the top-left pixel and keep looping until we have the desired effect
for($y = 0;$y < $height;$y += $pixelate_y+1)
{
for($x = 0;$x < $width;$x += $pixelate_x+1)
{
// get the color for current pixel
$rgb = imagecolorsforindex($img, imagecolorat($img, $x, $y));
// get the closest color from palette
$color = imagecolorclosest($img, $rgb['red'], $rgb['green'], $rgb['blue']);
imagefilledrectangle($img, $x, $y, $x+$pixelate_x, $y+$pixelate_y, $color);
}
}
// save the image
$output_name = $output .'_'. time() .'.jpg';
imagejpeg($img, $output_name);
imagedestroy($img);
}
pixelate("test.jpg", "testing");
?>
This is the example function to create pixelated effect on images.
Here's an example results of using this function:
Original:
Pixelated 5px:
Pixelated 10px:
Pixelated 20px:
Thank you for your answer. I used your function and added another loop to change color of the outer pixel of the squares using a function called imagelinethick in http://www.php.net/manual/en/function.imageline.php. So it became:
<?php
$image = imagecreatefromjpeg('Penguins.jpg');
$imagex = imagesx($image);
$imagey = imagesy($image);
$pixelate_y=10;
$pixelate_x=10;
$height=$imagey;
$width=$imagex;
for($y = 0;$y < $height;$y += $pixelate_y+1)
{
for($x = 0;$x < $width;$x += $pixelate_x+1)
{
// get the color for current pixel
$rgb = imagecolorsforindex($image, imagecolorat($image, $x, $y));
// get the closest color from palette
$color = imagecolorclosest($image, $rgb['red'], $rgb['green'], $rgb['blue']);
imagefilledrectangle($image, $x, $y, $x+$pixelate_x, $y+$pixelate_y, $color);
}
}
for($y = 0;$y < $height;$y += $pixelate_y+1)
{
for($x = 0;$x < $width;$x += $pixelate_x+1)
{
//make a border line for each square
$rgb = imagecolorsforindex($image, imagecolorat($image, $x, $y));
$color = imagecolorclosest($image, 123, 123, 123);
imagelinethick($image, $x, $y, $x, $y+$pixelate_y, $color, 1);
imagelinethick($image, $x, $y, $x+$pixelate_x, $y, $color, 2);
}
}
function imagelinethick($image, $x1, $y1, $x2, $y2, $color, $thick = 1)
{
/* this way it works well only for orthogonal lines
imagesetthickness($image, $thick);
return imageline($image, $x1, $y1, $x2, $y2, $color);
*/
if ($thick == 1) {
return imageline($image, $x1, $y1, $x2, $y2, $color);
}
$t = $thick / 2 - 0.5;
if ($x1 == $x2 || $y1 == $y2) {
return imagefilledrectangle($image, round(min($x1, $x2) - $t), round(min($y1, $y2) - $t), round(max($x1, $x2) + $t), round(max($y1, $y2) + $t), $color);
}
$k = ($y2 - $y1) / ($x2 - $x1); //y = kx + q
$a = $t / sqrt(1 + pow($k, 2));
$points = array(
round($x1 - (1+$k)*$a), round($y1 + (1-$k)*$a),
round($x1 - (1-$k)*$a), round($y1 - (1+$k)*$a),
round($x2 + (1+$k)*$a), round($y2 - (1-$k)*$a),
round($x2 + (1-$k)*$a), round($y2 + (1+$k)*$a),
);
imagefilledpolygon($image, $points, 4, $color);
return imagepolygon($image, $points, 4, $color);
}
header("Content-Type: image/JPEG");
imageJPEG($image, "", 75);
?>
The result is like this: http://www.flickr.com/photos/52700219#N06/6759029339/
But I think this still need some improvement to make it smoother.
Here goes theoretically:
You have a image:
RGBRGBRGBRGB
GBRGBRGBRGBR
GBRGBRGBRRGB
BGRGBGRGGRBG
Take the color of the first pixel and set the same color for a square of next pixels (both down and right). Then take the color of a 5th pixel (as 4 ones in the start have already the same color). If you are done for the first row, go +3 rows down and start again.
So you get:
RRRRGGGBBBB
RRRRGGGBBBB
RRRRGGGBBBB
RRRRGGGBBBB
In PHP you can use the following functions to make this:
http://php.net/manual/en/function.imagecolorat.php to select the color of a pixel
http://php.net/manual/en/function.imagecolorset.php to set the color of a pixel
http://php.net/manual/en/function.imagesx.php get image width
http://php.net/manual/en/function.imagesy.php get image height
use for loops thru the pixels of a image
This is my attempt at the problem.
You can alter the pixelate block size and you can apply a blur which softens the effect on high contrast images. Can be a slow on large images with small pixelate block sizes though.
The scripts stores the colours of relevant pixels in an array. It then embosses the image, alters the contrast as required, pixelates the image using the imagefilter() function and then (if tile enhance is set) embosses it again (this increases the 3D effect on the final tiles). If blur is required the script the applies the Gaussian blur. The script then draws filled squares using the colour array to create the colourful pixelated effect within the embossed tile borders.
function pixelatemboss($image,$blockwidth=10,$blur=5,$tileenhance="true",$contrast=0,$negate="true")
{
if($blockwidth>1)
{
imagefilter($image,IMG_FILTER_CONTRAST,$contrast);
for($x=1;$x<imagesx($image);$x=$x+$blockwidth)
{
for($y=1;$y<imagesy($image);$y=$y+$blockwidth)
{
$color[$x][$y]=imagecolorat($image,$x,$y);
}
}
imagefilter($image,IMG_FILTER_EMBOSS);
imagefilter($image,IMG_FILTER_CONTRAST,$contrast);
imagefilter($image,IMG_FILTER_PIXELATE,$blockwidth,false);
if($tileenhance=="true")
{
imagefilter($image,IMG_FILTER_EMBOSS);
}
for($b=0;$b<$blur;$b++)
{
imagefilter($image,IMG_FILTER_GAUSSIAN_BLUR);
}
for($x=1;$x<imagesx($image);$x=$x+$blockwidth)
{
for($y=1;$y<imagesy($image);$y=$y+$blockwidth)
{
$rgb=$color[$x][$y];
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$col=imagecolorallocate($image,$r,$g,$b);
imagefilledrectangle($image,$x,$y,$x+($blockwidth-2),$y+($blockwidth-2),$col);
}
}
}
return $image;
}
Note for php 5.4 and up you need to use:
imageJPEG($image, NULL, 75);
You can no longer specify NULL by using a double quote (like this example):
imageJPEG($image, "", 75);