I'm currently building an ecommerce site (with Drupal Commerce). We sell sports clothing that is made to order. The customer is able to pick a style, two colours and a size. For each style there are over three hundred combinations of colours that could be chosen.
I am creating artwork for the products in Illustrator. They are fairly simple vectors that use only two flat colours with a black outline on top.
I'm trying to find a way to generate all of the colour combinations for each style, preferably dynamically. I've looked at GD but I'm not sure that will work here. I wondered if there was a way of either using SVG (as I already have vectors) or stacking 3 transparent PNGs that could have a colour overlay applied and preserve their transparency? Done.
To create the images dynamically I have created one GIF that contains the white background and a pure red and pure blue region to define the primary and secondary areas. This is run through GD which changes the red and blue to the user selected colours. Then a transparent PNG is merged on top which contains the black outline and the company logo.
On index.php I have a form that allows users to choose a style and two colours:
<form method="post" action="index.php">
<label for="style">Style:</label>
<select id="style" name="style" required>
<option value="0001">Vertical Stripe</option>
<option value="0002">V Neck</option>
<option value="0003">Contrast Side</option>
...
</select>
<br><br>
<label for="color1">Color 1:</label>
<select id="color1" name="color1" required>
<option></option>
<option value="134,84,66">Retro Brown</option>
<option value="115,51,68">Claret</option>
<option value="167,57,52">Deep Red</option>
<option value="213,69,54">Bright Red</option>
...
</select>
...
</form>
After the form has been submitted there's some PHP to create a URL that passes the options over to product-image.php:
<?php
$url = "product-image.php";
if (isset($_POST["style"])) {
$url = $url . "?style=" . $_POST["style"];
}
if (isset($_POST["color1"])) {
$url = $url . "&color1=" . $_POST["color1"];
}
if (isset($_POST["color2"])) {
$url = $url . "&color2=" . $_POST["color2"];
}
?>
<img class="product" src="<?php echo $url; ?>">
Then the bulk of the work is done by product-image.php:
// Set some dummy values to avoid errors
$style = "0001";
$color1 = array(255,255,0);
$color2 = array(0,0,200);
if (isset($_GET["style"])) {
$style = $_GET["style"];
}
$colorFile = $style . "colors.gif";
$outlineFile = $style . "outline.png";
// Load image with coloured sections
$image_1 = imagecreatefromgif($colorFile);
// Load image with outlines
$image_2 = imagecreatefrompng($outlineFile);
imagealphablending($image_1, true);
imagesavealpha($image_1, true);
imagetruecolortopalette($image_1, false, 255);
// Import $color1 values to create an RGB array
if (isset($_GET["color1"])) {
$color1 = explode(',', $_GET["color1"]);
}
// Import $color2 values to create an RGB array
if (isset($_GET["color2"])) {
$color2 = explode(',', $_GET["color2"]);
}
// Define Primary (red) region
$region1 = imagecolorclosest ( $image_1, 255,0,0);
// Set new colour for $region1 using the values passed into $color1
imagecolorset($image_1, $region1, $color1[0], $color1[1], $color1[2]);
// Get Secondary (blue) region
$region2 = imagecolorclosest ( $image_1, 0,0,255);
// Set new colour for $region2 using the values passed into $color2
imagecolorset($image_1, $region2, $color2[0], $color2[1], $color2[2]);
// Create a true color canvas, this seems to retain transparency when merging PNG & GIF
$merged_image = imagecreatetruecolor(339, 390);
// Merge the newly coloured sections
imagecopy($merged_image, $image_1, 0, 0, 0, 0, 339, 390);
// Merge the outlines on top
imagecopy($merged_image, $image_2, 0, 0, 0, 0, 339, 390);
// Tell browser to expect PNG
header("Content-type: image/png");
// Output new PNG
imagepng($merged_image);
// Tidy up
imagedestroy($image_1);
imagedestroy($image_2);
imagedestroy($merged_image);
I am pretty chuffed with the results as I am still learning PHP and had never looked into GD before. I have posted a rough demo here (there is also a link to download all the files used on that page).
Any suggestions for improvements? Ultimately I want the user to select two colours in the drop downs and then a script will look to see if an image with those options exists and if not it dynamically creates it by setting the colour of the two regions and then stores the newly created image for future users.
How can I make it auto update without the need for a submit button?
All of the above works and now I've got it to store the images it creates and added a check to see if the image is there before it tries to create it too. The linked example has been updated with all the code but here's the new product-image.php file for anyone that's interested.
$style = "0001"; // Dummy values to avoid errors
$color1 = array(247,228,064);
$color2 = array(031,076,146);
$templatePath = "../templates/"; // Relative path from this file to your templates
if (isset($_GET["style"])) {
$style = $_GET["style"]; // Replace $style with real value if recieved
}
if (isset($_GET["color1"])) {
$color1 = explode(',', $_GET["color1"]); // Replace $color1 with real RGB array if recieved
}
if (isset($_GET["color2"])) {
$color2 = explode(',', $_GET["color2"]); // Replace $color2 with real RGB array if recieved
}
// Create unique output file name by concatenating all numerical values eg:0001247228522562146.png
$outputFileName = $style . implode("", $color1) . implode("", $color2) . ".png";
// Check if the image we want already exists
if (file_exists($outputFileName)) {
// If it does then open the file in a binary mode
$fp = fopen($outputFileName, 'rb');
// send the right headers
header("Content-Type: image/png");
header("Content-Length: " . filesize($outputFileName));
// dump the picture and stop the script
fpassthru($fp);
exit;
} else { // If it doesn't already exist then lets create the image...
$colorFile = $templatePath . $style . "colors.gif";
$outlineFile = $templatePath . $style . "outline.png";
$image_1 = imagecreatefromgif($colorFile); // Load image with coloured sections
$image_2 = imagecreatefrompng($outlineFile); // Load image with outlines
imagealphablending($image_1, true);
imagesavealpha($image_1, true);
imagetruecolortopalette($image_1, false, 255);
$region1 = imagecolorclosest ( $image_1, 255,0,0); // Get Primary (red) region
imagecolorset($image_1, $region1, $color1[0], $color1[1], $color1[2]); // Set new colour for $region1
$region2 = imagecolorclosest ( $image_1, 0,0,255); // Get Secondary (blue) region
imagecolorset($image_1, $region2, $color2[0], $color2[1], $color2[2]); // Set new colour for $region2
$merged_image = imagecreatetruecolor(339, 390); // Create a true color canvas
imagecopy($merged_image, $image_1, 0, 0, 0, 0, 339, 390); // Merge the newly coloured sections
imagecopy($merged_image, $image_2, 0, 0, 0, 0, 339, 390); // Merge the outlines on top
header("Content-type: image/png"); // Tell browser to expect PNG
imagepng($merged_image, $outputFileName); // Save new PNG to server
imagedestroy($image_1); // Tidy up
imagedestroy($image_2);
imagedestroy($merged_image);
// open the image we just created in a binary mode
$fp = fopen($outputFileName, 'rb');
// send the right headers
header("Content-Type: image/png");
header("Content-Length: " . filesize($outputFileName));
// dump the picture and stop the script
fpassthru($fp);
exit;
}
Using the code above and adding a few lines of jQuery I have finally achieved my original goal.
The jQuery:
$('select').click(function() {
var style = $("select#style").val();
var color1 = $("select#color1").val();
var color2 = $("select#color2").val();
var productImgURL = 'product-image.php?style='+ style + '&color1=' + color1 + '&color2=' + color2;
$('.product').attr('src',productImgURL);
});
As soon as the select box is modified the jQuery requests a different image from product-image.php by appending the values. The interaction is smooth and works exactly how I wanted.
Now I just have to figure out how to store the generated images and add a check to see if they have already been generated. Then I have to make all of this play nice with Drupal Commerce.
I have updated my example page and the all of the code is available for download there.
Although this question received no responses I wouldn't have figured this out without trawling through many other questions on this site so thanks to everyone who posts here!
Related
I'm trying to use Imagick::steganoImage with an example image from wikimedia commons.
If I try to show the decoded image of the watermark, I always obtain the 1 pixel image you can see below, whatever image I choose as source.
Anyone may help me to understand why and how I can sort this out?
<?
header("Content-Type: image/png");
// Create a new imagick object
$image = new Imagick('https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/Frostedbubble2.jpg/640px-Frostedbubble2.jpg');
$watermark = new Imagick('LABEL:Hello World!');
// The decoding process must "know" about the watermarks size, and starting
// pixel offset.
define('STEGANO_OFFSET', 64); // Secret offset
define('STEGANO_WIDTH', $watermark->getImageWidth());
define('STEGANO_HEIGHT', $watermark->getImageHeight());
$stegano = $image->steganoImage($watermark, STEGANO_OFFSET);
$stegano->writeImage('output.png');
$decoded = new Imagick();
$decoded->setSizeOffset(STEGANO_WIDTH, STEGANO_HEIGHT, STEGANO_OFFSET);
$decoded->readImage('STEGANO:output.png');
$decoded->writeImage('decoded.png');
// Show the output
$decoded->setImageFormat('png');
echo $decoded->getImageBlob();
?>
I tried also the code at this page https://www.geeksforgeeks.org/php-imagick-steganoimage-function/ and the geeksforgeeks image is shown correctly but the stegano image appear as totally black.
<?php
// Create a new imagick object
$imagick = new Imagick(
'https://media.geeksforgeeks.org/wp-content/uploads/geeksforgeeks-13.png');
// Create another Imagick object containing watermark
$watermark = new Imagick('label:This is my secret.');
// Hide $watermark inside $imagick
$imagick = $imagick->steganoImage($watermark, 64);
// Write image to the local folder
$imagick->writeImage('output.png');
// Set the offset
$imagick->setSizeOffset($watermark->getImageWidth(),
$watermark->getImageHeight(), 64);
// Read the encoded image and extract secret
$imagick->readImage('STEGANO:output.png');
// Show the output
$imagick->setImageFormat('png');
header("Content-Type: image/png");
echo $imagick->getImageBlob();
?>
Looks like new Imagick('LABEL:Hello World!'); is no longer enough for a simple label. You'll need to set the size of the canvas, and the point size BEFORE reading the label.
define('STEGANO_OFFSET', 64); // Secret offset
define('STEGANO_WIDTH', 88);
define('STEGANO_HEIGHT', 14);
$watermark = new Imagick();
$watermark->setSize(STEGANO_WIDTH, STEGANO_HEIGHT);
$watermark->setPointSize(16);
$watermark->readImage('LABEL:Hello World!');
$stegano = $image->steganoImage($watermark, STEGANO_OFFSET);
I can't speak when/why this changed, but if you run the following...
convert 'label:Hello World!' decoded.png
... you would have the same image previously extracted from STEGANO:
Need some help with images.
As the topic says, I want to create an image with live updating text on it.
This is mainly used by game servers and players to show off their stats and info. Server-wise, to show if the server is online and how many players are online and such.
I haven no idea how to do it and figured this would be the best place to find out. Since I don't have any idea what this is even called, i did not know what to search for.
Thanx in advance.
This is an html+css+ajax solution. Make the image an html element's background image. Let's use a div. Then position the text in the div. Use ajax to update the text. The image will remain the same while the text can be updated.
Was possible with the use of API. Created an API of the database I want to use, connected to the database and everything worked!
After using $API_GET to get the data, I set it into an array-format.
Used PHP for everything.
From there on I used imagecreatefrompng, obviously to select an image.
Set a few colors using imagecolorallocate and from there on it was purely adding the text on the image as to where I want them using imagettftext.
Creating an image, with live updating stats on it.
But we still have to tell the browser to load it as an image and not a page with an image on it, so therefor...
header( "Content-type: image/png" );
And imagesetthickness to 5, followed by imagepng and imagedestroy.
Code Extracts:
$API_GET = file_get_contents("API URL");
$API_GET = json_decode($API_GET);
$API = array();
foreach ($API_GET as $key => $value) {
$API[$key] = $value;
}
if (file_exists($imagefile)) {
$bg_img = imagecreatefrompng ( "IMAGE URL");
$color_red = imagecolorallocate( $bg_img, 250, 0, 0 );
imagettftext($bg_img, 20, 0, 19, 36, $color_red, 'FONT URL.tff',"Text On Image");
imagesetthickness ( $my_img, 5 );
header( "Content-type: image/png" );
imagepng( $my_img );
imagedestroy( $my_img );
} else {
echo 'Image does not exist.';
}
That is the basic structure of the code.
Thank You for your reply to the question.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am using owl carousel and it works perfectly except it does not support circular/infinite scrolling. I did search for ideas on google and stackoverflow with no luck. Has anyone implemented circular/infinite scrolling in owl carousel?
Owl Carousel does have the loop: true configuration setting. But, there's a few problems I don't like:
Owl doesn't goto the first slide when at the end, when dragging (instead of clicking on navigation buttons)
Owl rewinds to the first slide, it doesn't wrap around infinitely. This is a big difference, and not nearly as pleasing as a properly circular / infinitely scrolling carousel.
To that end I've found and recommend using the Slick Carousel instead. Slick has a "Center Mode" which had exactly the functionality I was looking for:
http://kenwheeler.github.io/slick/
No.They said that carousel doesn't support circular slides.
Possibly this may help:
rewindNav: true
But this works only with navigation arrows, not with responsive slides =(
Or you may huck it somehow)
I was able to accomplish it using jquery/php/ajax. Here is how I did it:
1) First you need to initially place the first x amount of images on the page which will technically be the first page and then afterwards you'll load via ajax each time you reach the end of the carousel. In the example script I supplied I am getting a list of images from a fictional database table called "images". In my php script, for this particular example, it will return 24 owl-item divs with content. For this example I will loading 24 images at a time on the first page initially and then ajax will attempt to return 24 more each time.
HTML (You will need to add the first items into the carousel div and these items will technically be the first page of items. You could use php to populate the divs/image source for the initial first page. Just use regular divs like I did below because the carousel will add the owl-item class to them once it initializes).
<div class="circle-slider">
<div>
<img src="/path/to/image/1" />
</div>
<div>
<img src="/path/to/image/2" />
</div>
.... the rest of the images go here, each in their own div ....
.... for this example I'd load 24 images total ...
</div>
Javascript (This javascript goes on the same page as the HTML above.)
<script type="text/javascript">
$(document).ready(function() {
var itemsPerPage = 0; // The number of items per page.
var page = 2; // Start on page 2 since we initially created page 1 in HTML
var working = false; //Boolean to keep the trigger from firing while we work
var lastvalue = 0; //last value of the owl objects item position array
var carouselDiv = '.circle-slider'; // the div that you will be placing the owl carousel on. See HTML above. MUST BE IN jQuery Notation.
//Normal Owl Carousel Setup. See their site for more options. My example works with these options. No guarantee if you change them to something else that it will work.
$(carouselDiv).owlCarousel({
items : 1,
itemsDesktop : [1920,2],
itemsDesktopSmall : [980,2],
itemsTablet: [768,2],
itemsTabletSmall: [480,1],
itemsMobile : [370,1],
singleItem : false,
itemsScaleUp : false,
slideSpeed : 800,
paginationSpeed : 300,
rewindSpeed : 250,
pagination:false,
autoPlay : false,
afterMove : function() {
// This is where all the magic happens. Once you slide the items around and let go this afterMove callback fires.
var owl = $(carouselDiv).data('owlCarousel'); //get the current owl carousel object
lastvalue = owl.positionsInArray[owl.positionsInArray.length-1]; //Get the last item position value in the position array
if((owl.currentItem == owl.maximumItem) && !working){
working = true; //Set working to true so we dont fire more events and load more items until this request is finished working
$.ajax({
method: "GET",
url: "/path/to/php/script/see/script/below",
async: false,
dataType: "script",
data: { page: page, itemWidth: owl.itemWidth }
}).done(function( data ) {
itemsPerPage = parseInt(cresults.numberOfItems, 10);
if( itemsPerPage ){
$('.owl-wrapper').width($('.owl-wrapper').width() + (itemsPerPage * owl.itemWidth)); //modify the width of the wrapper div to handle the new items
$('.owl-wrapper').append(cresults.html); //append the markup
owl.maximumItem = parseInt(owl.maximumItem, 10) + parseInt(itemsPerPage, 10); //modify the max items in the owl object
for (var i = 0; i < itemsPerPage; i++) { // add new indexes in the position array for the owl object.
lastvalue = lastvalue-owl.itemWidth
owl.positionsInArray.push(lastvalue);
}
owl.maximumPixels = owl.maximumPixels - (owl.itemWidth * itemsPerPage); //modify the owl maximum pixels to accomodate new items
owl.$owlItems = $(carouselDiv).find(".owl-item");
page = page + 1;
}
working = false;
});
}
}
});
});
</script>
PHP SCRIPT (Create a php file and this should be the page that is used in the ajax url in the JavaScript i.e. $.ajax({method: "GET",url: "/path/to/php/script"..... )
<?php
$page = isset($_GET['page']) ? $_GET['page'] : 2;
$itemWidth = isset($_GET['itemWidth']) ? $_GET['itemWidth'] : 0;
//Get 24 images from my database
$link = mysqli_connect("myhost","myuser","mypassw","mybd") or die("Error " . mysqli_error($link));
$query = 'SELECT * FROM images LIMIT 24 OFFSET ' . (($page - 1) * 24);
$result = $link->query($query);
$return = null;
while($image = mysqli_fetch_object($result)) {
$return .= '<div style="width: ' . $itemWidth . 'px;" class="owl-item"><div><img src="' . $image->path . '" alt="img" /></div></div>';
}
mysqli_close($link);
// Replace some characters in the return string to they wont mess up javascript
$return = preg_replace('/\n/s', "", $return);
$return = preg_replace('/\s\s+/', ' ', $return);
$return = preg_replace('/\'/', '’', $return);
echo 'cresults = { "html" : \'' . $return . '\', numberOfItems: \'' . $result->num_rows . '\'};'; //echoing the return value will fulfill the Ajax call to this method
That's pretty much it. Easy as pie. Works pretty well too. If the browser resizes and causes the owl items to resize as well, it does reset the carousel back to the first item but I figured out how to add the items to the object so it doesnt mess things up and that is already included in the JavaScript. Let me know if you have any issues and I might be able to help fix them. Been working on this several days and just got this working so I haven't had time to extensively test it but I know it works on mobile phones, both iPhone and Android and works on iPads as well as on desktop browsers. Have fun!
The order and invoice numbers are hard to read on my printed mangento invoices. I want to change the header from the white on dark grey default to plain old black on white. Can anyone point me to the right place to update this?
I was looking in the invoice.php file in Mage\Sales\Model\Order\Pdf but while there appear to be some items from this printed report in there... I cannot see anything having to do with the header.
Thanks
The file you are looking for is app/code/core/Mage/Sales/Model/Order/Pdf/Abstract.php. I have marked the two lines you'll need to change with // <--. The documentation for Zend_Pdf_Color_GrayScale will tell you that 0.0 is black, 1.0 is white.
protected function insertOrder(&$page, $obj, $putOrderId = true)
{
if ($obj instanceof Mage_Sales_Model_Order) {
$shipment = null;
$order = $obj;
} elseif ($obj instanceof Mage_Sales_Model_Order_Shipment) {
$shipment = $obj;
$order = $shipment->getOrder();
}
/* #var $order Mage_Sales_Model_Order */
$page->setFillColor(new Zend_Pdf_Color_GrayScale(1)); // <-- White header
$page->drawRectangle(25, 790, 570, 755);
$page->setFillColor(new Zend_Pdf_Color_GrayScale(0)); // <-- Black text
$this->_setFontRegular($page);
if ($putOrderId) {
$page->drawText(Mage::helper('sales')->__('Order # ').$order->getRealOrderId(), 35, 770, 'UTF-8');
}
$page->drawText(Mage::helper('sales')->__('Order Date: ') . Mage::helper('core')->formatDate($order->getCreatedAtStoreDate(), 'medium', false), 35, 760, 'UTF-8');
Additional information (discovered when making this change):
Be aware that the Creditmemo, Invoice, and shipment all share the same basic header from the Abstract file. So when you change the background color of the abstract file there is a line containing the Shipment #, Invoice # or Credit Memo # that is printed in each of the following files that you will also need to address.
The default font color is white and so changing the abstrat background header to white creates a white on white (hence invisible) result.
In the Creditmemo.php, Invoice.php, and Shipment.php files in that same directory find the following line (almost identical across the 3 files) and update it as well.
public function getPdf($shipments = array())
{
// .... a few lines of code ..... //
/* Add head */
$this->insertOrder($page, $shipment, Mage::getStoreConfigFlag(self::XML_PATH_SALES_PDF_SHIPMENT_PUT_ORDER_ID, $order->getStoreId()));
// 0 to print black, 1 to print white
$page->setFillColor(new Zend_Pdf_Color_GrayScale(1));
$this->_setFontRegular($page);
Just a heads up to anyone looking for this answer but not able to find the code to change in Invoice.php, Shipping.php etc.
Im my Magento Version 1.7.0.2 to change the top title invoice number I also made this change in the Abstract.php file around line 512.
` public function insertDocumentNumber(Zend_Pdf_Page $page, $text)
{
$page->setFillColor(new Zend_Pdf_Color_GrayScale(0));`
Just wanted to share as I personally wasted too much time on this and hope to save the next person some.
I found this: http://docs.magentocommerce.com/Varien/Varien_Image/Varien_Image.html#crop
But I'm not sure if this is deprecated or something because when I tried this:
echo rawurlencode($this->helper('catalog/image')->init($_product, 'image')->constrainOnly(TRUE)->keepAspectRatio(TRUE)->keepFrame(FALSE)->setWatermarkImageOpacity(0)->crop(10, 20, 30, 40)->resize(300, null))
It doesn't work and gives me this error:
Fatal error: Call to undefined method Mage_Catalog_Helper_Image::crop() in /home/xxxxx/public_html/app/design/frontend/default/xxxxx/template/catalog/product/view.phtml
So is the crop() method actually usable at all? If it is, how can I use it to crop (not to be confused with resize) the product images of Magento? Thanks!
Your mistake is assuming that $this->helper('catalog/image')->init($_product, 'image') returns a Varien_Image instance, when in fact there are two intermediate classes involved:
Mage_Catalog_Helper_Image and Mage_Catalog_Model_Product_Image.
The catalog/image helper is a mess, even though it has been cleaned up a bit in recent versions (e.g. no more private methods). Still, some getters still are protected without there being a real need for it.
Here is my workaround:
/* #var $imageHelper Mage_Catalog_Helper_Image */
// Initialize the image helper
$imageHelper = Mage::helper('catalog/image')->init($_product, 'image')
->constrainOnly(true)
->keepAspectRatio(true)
->keepFrame(false)
->setWatermarkImageOpacity(0);
// Get the catalog/product_image instance
/* #var $imageModel Mage_Catalog_Model_Product_Image */
$reflection = new ReflectionClass($imageHelper);
$property = $reflection->getProperty('_model');
$property->setAccessible(true);
$imageModel = $property->getValue($imageHelper);
// Initialize the missing values on the image model
// Usually done in Mage_Catalog_Helper_Image::__toString()
if (! $imageModel->isCached())
{
$getWatermarkMethod = $reflection->getMethod('getWatermark');
$getWatermarkMethod->setAccessible(true);
$imageModel->setBaseFile($_product->getImage())
->resize()
->setWatermark($getWatermarkMethod->invoke($imageHelper));
// Crop the image using the image processor
// $imageModel->getImageProcessor() returns a Varien_Image instance
$imageModel->getImageProcessor()->crop(10, 20, 30, 40);
// Generate the image according to the set parameters and
// get the URL while bypassing the helper to avoid reinitialization
$url = $imageModel->saveFile()->getUrl();
}
echo $url . "\n";
It would be easier to use the catalog/product_image model or Varien_Image directly, but this way all the Magento watermark settings still are applied.
Either way isn't clean.
I hope the getters on the helper are made public in future releases.
Here is the alternative method ( credits from Onlinebizsoft.com )
The following code first looking the image that available in the /resize directory, if it's not there, doing rest of things.
// actual path of image
$_imageUrl = Mage::getBaseDir('media').DS."myimage".DS.$post->getThumbnail();
// path of the resized image to be saved
// here, the resized image is saved in media/resized folder
$imageResized = Mage::getBaseDir('media').DS."myimage".DS."resized".DS.$post->getThumbnail();
// resize image only if the image file exists and the resized image file doesn't exist
// the image is resized proportionally with the width/height 135px
if (!file_exists($imageResized)&&file_exists($_imageUrl)) :
$imageObj = new Varien_Image($_imageUrl);
$imageObj->constrainOnly(TRUE);
$imageObj->keepAspectRatio(TRUE);
$imageObj->keepFrame(FALSE);
$imageObj->resize(135, 135);
$imageObj->save($imageResized);
endif;
Check the website Resize - Scale Crop images
Did you tried Varien_Image class ?
$image = new Varien_Image($img);
$cropped = $image->crop();