Gorilla3D Primative Teachings

Fact #3:
Search
Subscribe to Feed:

Code for Scaling Watermarks for Images in PHP with GD


Tuesday, October 28, 2008

Had to do watermarking which, by itself is relatively easy. But then there was an issue with the ratio of the watermark and image size. So below is how to watermark with an image thats way too big for a small watermark.

  1.  
  2. <?php
  3. //------------------------------------------------------------------------------
  4. //-- Image
  5. //------------------------------------------------------------------------------
  6. $filename = 'images/beagle01-lg.jpg';
  7. $image = imagecreatefromjpeg($filename);
  8.  
  9. //------------------------------------------------------------------------------
  10. //-- Watermark
  11. //------------------------------------------------------------------------------
  12. $wfilename = 'images/watermark.png';
  13. $watermark = imagecreatefrompng($wfilename);
  14.  
  15. //------------------------------------------------------------------------------
  16. //-- Marked Image
  17. //------------------------------------------------------------------------------
  18. // Grab the extension
  19. $pathinfo = pathinfo($filename);
  20. $extension = $pathinfo['extension'];
  21. // Give this file a random name
  22. $markedname = uniqid() . '.' . $extension;
  23.  
  24. //------------------------------------------------------------------------------
  25. //-- Resample Watermark
  26. //-- Scale the water mark to a ratio of $ratio of the orginal image
  27. //-- TODO: Downward scaling for watermarks that are too large for smaller images
  28. //------------------------------------------------------------------------------
  29. $ratio_limit = 3; // Ratio 1:3
  30. list($watermark_width, $watermark_height, $type, $attr) = getimagesize($wfilename);
  31. list($image_width, $image_height, $type, $attr) = getimagesize($filename);
  32.  
  33. $width = $watermark_width;
  34. $height = $watermark_height;
  35. $ratio = 1.0;
  36.  
  37. while(1) {
  38. //-- TODO: Im sure there is a formula for this that doesn't need a loop
  39. //-- The image to watermater ratio is too small.
  40. if((intval(($image_width * $image_height) / ($width * $height)) <= 3) or
  41. ($width * $ratio >= $image_width or $height * $ratio >= $image_height)) {
  42. break;
  43. } else {
  44. $width = $width * $ratio;
  45. $height = $height * $ratio;
  46. $ratio += 0.1;
  47. }
  48. }
  49.  
  50. $newwidth = intval($width);
  51. $newheight = intval($height);
  52.  
  53. $resampled = imagecreatetruecolor($newwidth, $newheight);
  54. imagealphablending($resampled, false);
  55. imagesavealpha($resampled, true);
  56. imagefilledrectangle($resampled, 0, 0, $newwidth, $newheight,
  57. imagecolorallocatealpha($resampled, 0, 0, 0, 127));
  58. imagecopyresampled($resampled, $watermark, 0, 0, 0, 0, $newwidth, $newheight,
  59. $watermark_width, $watermark_height);
  60. $watermark = $resampled;
  61. unset($resampled);
  62.  
  63. //------------------------------------------------------------------------------
  64. //-- Apply Watermark to bottom right of image
  65. //------------------------------------------------------------------------------
  66. imagealphablending($image,true);
  67. $dst_w = imagesx($image);
  68. $dst_h = imagesy($image);
  69. imagealphablending($watermark,true);
  70. $src_w = imagesx($watermark);
  71. $src_h = imagesy($watermark);
  72. imagecopy($image, $watermark, ($dst_w-$src_w), ($dst_h-$src_h), 0, 0, $src_w, $src_h);
  73. imagejpeg($markedname, $filename, 85);
  74. ?>
  75.  


0 comments

PHP & Firefox 3 AJAX Image Upload


Friday, August 15, 2008

PHP + Firefox3 AJAX Image Upload

Here is a sample dump of using firefox3's getAsDataURL to push to php and using GD to process it into an image and then save to file.

  1.  
  2. /* Ajax Functions */
  3. function Ajax(url, options) {
  4. if (typeof XMLHttpRequest!='undefined') {var page = new XMLHttpRequest();}
  5. else if (window.createRequest) { var page = window.createRequest();}
  6. else if (window.ActiveXObject) { var page = new ActiveXObject('MSXML2.XMLHTTP.3.0');}
  7. else { alert('Ooops, we failed to process your request. Tell us your browser please!'); }
  8. if (page) {
  9. if (options.method == 'post') {
  10. page.open('POST', url, true);
  11. page.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded") }
  12. else {
  13. page.open('GET', url, true);
  14. }
  15. page.onreadystatechange = function() {
  16. if (page.readyState == 4 && page.status == 200) {
  17. if ('function' == typeof options.onComplete) options.onComplete(page.responseText);
  18. }
  19. }
  20. if (options.method == 'post') {
  21. page.send(options.data);
  22. } else {
  23. page.send(null);
  24. }
  25. } else {
  26. alert('There has been a problem processing your request');
  27. }
  28. }
  29. function writeImage() {
  30. var imgdata = $('imagefile').files.item(0).getAsDataURL();
  31. var imgsize = $('imagefile').files.item(0).fileSize;
  32. var imgname = $('imagefile').files.item(0).fileName;
  33. Ajax("post.image.php", {"method":"post", "data": {"data":imgdata, "size":imgsize, "name":imgname}, "onComplete": function(image) { alert('uploaded'); }});
  34. }
  35.  


  1.  
  2. <input type="file" id="imagefile" name="imagefile" onchange="writeImage()"/>
  3.  


  1.  
  2. <?php
  3. $uploadfile = 'temp.jpg';
  4. //-- Parse the data
  5. $img_str = $_POST['data'];
  6. $img_str = explode('base64,', $img_str);
  7. $img_str = $img_str[1];
  8. $img_str = base64_decode($img_str);
  9. //-- Create image from string
  10. $image = imagecreatefromstring($img_str);
  11. //-- Save to file
  12. imagejpeg($image, $uploadfile, 85);
  13. ?>
  14.  


0 comments

Modular C++ Web Server / Framework


Sunday, August 10, 2008

I am working on a modular cpp web server to allow compile c++ shared / dynamic libraries. This way if anyone is ever wanting to challenge themselves, they can do so by writing a module for the deamon using the framework.

Bare-Bone sample library
  1.  
  2. #include <stdio.h>
  3. #include "HttpModule.h"
  4.  
  5. class hello : public HttpModule {
  6. public:
  7. static char *get() {
  8. char *temp = "Hello World from a c++ sample";
  9. return temp;
  10. }
  11. };
  12.  
  13. // the class factories
  14. extern "C" HttpModule* create() {
  15. return new hello;
  16. }
  17.  
  18. extern "C" void destroy(HttpModule* p) {
  19. delete p;
  20. }
  21.  

Compile the dynamic lib
  1.  
  2. # compile into a shared library
  3. g++ -fPIC -c hello.cpp
  4. g++ -shared -o libhello.so hello.o
  5. # Using g++ on intel mac
  6. # g++ -dynamiclib -o libhello.so hello.o
  7.  


How does one then use this library on the server, well... I'll eventually make a configuration file, but for now you ave to directly edit the webserver.
  1.  
  2. module_map http_modules [] = {
  3. {"/helloworld", "./libhello.so"}
  4. };
  5.  


That correlates to http://localhost/helloworld and outputs "Hello World from a c++ sample"

1 comments

Gorilla Db - (Improved) MySQLi Wrapper


Sunday, August 3, 2008

I've updated my mysqli wrapper to handle binds better and easier to new people trying to use prepared statements. I've also added Non-Filtered binds, because I'll also be release my Table class to help with simple queries you always end up running.

Db is a connection manager, it will use the connection you first create throughout your application. You can continue to call Db:init() and as long as a connection has already been made, you can run queries. Best of all It has prepared statements thanks to Wrapping MySQLi. For documentation and download please visit Gorilla Labs

  1.  
  2. //-- Prepared Statements
  3. // Execute a query
  4. $db->prepare('SELECT * FROM blog_entries WHERE id=?')->bind(23)->query();
  5. // or
  6. $db->prepare(SELECT * FROM blog_entries WHERE id=?);
  7. $db->bind(23);
  8. $db->query();
  9. // you can also stack binds
  10. $db->prepare('SELECT * FROM blog_entries WHERE id=? and title=?')
  11. ->bind(23)->bind('Hello World')->query();
  12. $db->prepare('SELECT * FROM blog_entries WHERE id=? and title=?')
  13. ->bind(array(23,'Hello World'))->query();
  14. $entry = $db->fetchOne();
  15.  
  16. // you can do can use them all in the same parameter
  17. $db->prepare('SELECT * FROM events WHERE name LIKE ? OR name LIKE ? and location LIKE ?')
  18. ->bind('%My%', '%Event%', '%San%')
  19. ->query();
  20.  
  21. // you can do can use an array and if they have keys you can assign you ?'s to them
  22. $db->prepare('SELECT * FROM events WHERE name LIKE ?arg1 OR name LIKE ?arg2 and location LIKE ?')
  23. ->bind(array('arg2'=>'%Event%'), '%San%', array('arg1'=>'%My%'))
  24. ->query();
  25.  
  26. // a cleaner example notice they can be in any order but you probably shouldn't
  27. $db->prepare('SELECT * FROM events WHERE name LIKE ?arg1 OR name LIKE ?arg2 and location LIKE ?')
  28. ->bind(array('arg2'=>'%Event%', '%San%', 'arg1'=>'%My%'))
  29. ->query();
  30.  
  31. // and yes keys can be used multiple times
  32. $db->prepare('SELECT * FROM events WHERE name LIKE ?arg1 OR name LIKE ?arg1 and location LIKE ?')
  33. ->bind(array('%San%', 'arg1'=>'%My%'))
  34. ->query();
  35.  


1 comments

Wordpress Plugin Development: Not so bad?


Saturday, August 2, 2008

When I had tried Drupal for size the admin area was so complex I'd never recommend it to a sane person. Wordpress has a much more simple admin area, but whats impressed me is how simple their API is. I wish it was more documented, but its given me a good run.

Wordpress's Front-end (What everyone else see) is crap. But its Back-end is not half bad. I get access to their editor, users and so on.

So later this week I'll post a really clean plugin so you can all agree with me :)

0 comments