Image block with ability to crop

Permalink 2 users found helpful
I made a block that can size/crop an image to fit your desired maximum dimensions, with the ability to change the location of the crop.

For example, if you have a 200 x 100 box you want to fill with an image, you can use this block to upload an image of pretty much any larger dimensions and it will be sized down and positioned so all 20,000 pixels are occupied.

It's a stand-alone extension (fork?) of the Image block, and should be able to replace it ... but I make no claims to solid code or best practices.

I'd like to continue to improve this, so please let me know if you run into any issues.

kirkroberts
 
kirkroberts replied on at Permalink Reply
kirkroberts
Here's the block.
deanhawthornthwaite replied on at Permalink Reply
deanhawthornthwaite
is this block still available please?
cant see a link.
Thanks, Dean.
kirkroberts replied on at Permalink Reply
kirkroberts
Hi Dean... I believe the standard Image block in Concrete5 now gives you this functionality (this thread is 4+ years old). When editing an Image block you can choose "Scale Image" => "Force Exact Image Match" which will crop the image to the dimensions you specify (assuming the original image is larger than the new dimensions and can be cropped).
JohntheFish replied on at Permalink Reply
JohntheFish
Crop to exact fit is now in the core image block - see the 'Scale Image' select at the bottom of the edit dialog.

(EDIT - referring to 5.6 and 5.6.3.2 in particular)
kirkroberts replied on at Permalink Reply
kirkroberts
It looks like in 5.6.3.1 the "force match" just distorts the image. Not sure about 5.7, which is probably what John is referring to.
deanhawthornthwaite replied on at Permalink Reply
deanhawthornthwaite
thanks guys will have a play.
Dean.
deanhawthornthwaite replied on at Permalink Reply
deanhawthornthwaite
just tried it and you can control the image size with either option auto or fixed, but it doesn't seem to crop?
kirkroberts replied on at Permalink Reply 1 Attachment
kirkroberts
Yep, looking in the Image block controller it appears that no option actually crops the image. I was shocked. Not what I expected at all. Lunacy! (on my part or theirs, not sure...)

I made a controller addition. Add the attached file (after unzipping) to /blocks/image/ (you'll probably need to create the "image" folder in /blocks) so the file path will be /blocks/image/controller.php

This adds cropping if "force match" is selected. Note that if you leave either width or height blank the original image's dimension will be used.

Hope that helps.
deanhawthornthwaite replied on at Permalink Reply
deanhawthornthwaite
Thanks kirkroberts, I didn't expect someone to write code just for me!

Sorry though as it does not seem to work. I wrote over the existing
controller.php file in the image folder but nothing changes when I test
it on an image block?

just to make sure the folder route was ...
concrete/blocks/image/controller.php


On 31/10/2014 14:32, concrete5 Community wrote:
JohntheFish replied on at Permalink Reply
JohntheFish
Without looking, my guess is that its supposed to be an override placed in the root level /blocks

See:
http://www.concrete5.org/documentation/how-tos/developers/change-th...
kirkroberts replied on at Permalink Reply
kirkroberts
Yep, John is right on, as usual.

Follow my instructions and it should work (assuming you restore the images controller you erroneously overwrote).

You'll likely have a folder at /blocks/images that contains ONLY the file I attached to my previous message.
deanhawthornthwaite replied on at Permalink Reply
deanhawthornthwaite
Sorry guys but I'm getting confused.
Please can you explain exactly what files/folders I need and where they
should be placed.
I'm only a lowly designer not a coder I'm afraid :-)



On 31/10/2014 17:42, concrete5 Community wrote:
JohntheFish replied on at Permalink Reply
JohntheFish
Block overrides are all explained in the howto I linked.
kirkroberts replied on at Permalink Reply
kirkroberts
#1 these are instructions for Concrete5 version 5.6.x NOT 5.7.x

On the root level of your site there are folders for blocks, concrete, config, controllers, etc.
In the blocks folder ON THE ROOT LEVEL (not in the concrete folder) make a folder called "image". Put the controller.php file (after unzipping it) in the "images" folder you just made. If it already exists there that's fine, just use it.

This extends the Image block controller that resides in the /concrete folder. It's considered a best practice to NEVER directly modify any files in the concrete folder. Don't touch those files for any reason.

So, you'll also probably need to download a fresh version of Concrete5 5.6.3.2 (or whatever version you have) and transfer over to your site the /concrete/blocks/image/controller.php file that you previously overwrote. This should restore it to factory settings. If you're unsure, you could overwrite the entire /concrete folder just to make sure you're getting the right file.

That's the best I can explain it.
deanhawthornthwaite replied on at Permalink Reply
deanhawthornthwaite
I really appreciate all your help, and have just gone through the
process you very clearly described but nothing has changed.
I read some of the documentation about overrides but it started to lose
me, but I basically get the idea.

I must be thick as Sh*** or missing something, I even looked at the
environment info below and I cant see it there?

# concrete5 Overrides
blocks/image, languages/nb_NO, languages/zh_TW, languages/ro_RO,
languages/sk_SK, languages/fa_IR, languages/el_GR, languages/es_MX,
languages/nl_NL, languages/fi_FI, languages/es_AR, languages/cs_CZ,
languages/fr_FR, languages/es_ES, languages/it_IT, languages/vi_VN,
languages/de_DE, languages/ja_JP, languages/sl_SI, languages/tr_TR,
languages/pt_PT, languages/da_DK, languages/ru_RU, languages/ar,
languages/sv_SE, languages/es_PE

Please dont spend any more time on this, i will just crop the image in
PS as I'm losing the will to live!



On 31/10/2014 18:05, concrete5 Community wrote:
kirkroberts replied on at Permalink Reply
kirkroberts
Sorry it isn't working for you.

You never did tell us what version of Concrete5 you're running (and shame on me for not making sure of that in the first place). Which version is it?
deanhawthornthwaite replied on at Permalink Reply
deanhawthornthwaite
it's 5.6.3.2

On 31/10/2014 18:40, concrete5 Community wrote:
kirkroberts replied on at Permalink Reply
kirkroberts
Shoot, I was almost hoping it was 5.7. It should work on 5.6.3.2.
In your previous message blocks/image is the very first override, so you have it in the right place.
I'd guess either the original Image controller wasn't restored properly (probably nothing would work then)
or
you haven't actually used the block settings correctly
or
caching is in play and you're seeing old versions (try turning off ALL caching and clear the cache)
kirkroberts replied on at Permalink Reply 1 Attachment
kirkroberts
Fixed a bug where you couldn't select to crop, save, then edit later to deselect cropping.
olacom replied on at Permalink Reply
olacom
Nice one! :)
melat0nin replied on at Permalink Reply
melat0nin
Would it be possible to integrate this logic into the page_list block to enable automatic thumbnailing?

I'm achieving something similar at the moment using Remo's thumbnail template, then a masking DIV and negative margins to show the thumbnail, but I'm wary that occassionally the wrong part of the image will be cropped that way and it will look stupid :(
kirkroberts replied on at Permalink Reply
kirkroberts
I've used the same logic for other blocks I've made to allow cropping/positioning of a thumbnail.

Unfortunately the positioning relies on a human making a judgment call about which part of the image to show. It can't happen automatically, unless I'm missing the meaning of your question.

Otherwise, just dive into the code and see how it works. The code you want to swipe is in the controller, in the getContentAndGenerate method.
$p = max(0, min($this->cropAlignNum, 100)) * .01;
$margin = $goWide ? "margin-left:" . (($w - $nw) * $p) : "margin-top:" . (($h - $nh) * $p);
$margin .= "px;";

Of course you'll need to modify to integrate it into your own code, but that should get you started.

Good luck!
zoinks replied on at Permalink Reply
Thank you for this!

Does it reduce the file size, too? Like if someone uploads a 500k file but crops it way down, does it reduce the file size, too? Or does it just sort of hide the excess image but keep the file size the same?

Also, can this work inside the WYSIWYG editor (ie. can people add images and crop them while they are adding content through the WYSIWYG editor?)
kirkroberts replied on at Permalink Reply
kirkroberts
The block is just the image block with the ability to crop tacked on, so yes it downsizes and optimizes the image. The cropping is in the CSS, so you will probably have a little extra image you can't see, but that shouldn't affect the filesize *too* much.

Try it out and right-click the image to open in a new window and you'll see what I mean.
NUL76 replied on at Permalink Reply 1 Attachment
NUL76
I use a PHP script to make a thumbnail of images I've included by using custom attributes. See attachment.

Extract the ZIP file. Upload the file thumbnail.php and folder cache to (let's say) the folder libraries (in your root). Make sure you give them both 755 rights.

To use this php:
<?  if ($cobj->getAttribute('photo_attribute_name')) {
    $imgHelper = Loader::helper('image');
    $image = $imgHelper->getThumbnail($cobj->getAttribute('photo_attribute_name'), 200, 200)->src;
    $photo = '/libraries/thumbnail.php?src='.$image.'&h=100&w=100&zc=1'; }  ?>


Why making a thumbnail of 200 by 200 first? Well C5 doesn't crop this. It gives the image a max width and height of 200 pixels. So the file could be 200px width, but 120px height.
After that I crop the image and give it the final thumbnail size.
kirkroberts replied on at Permalink Reply
kirkroberts
Thanks for posting this.

Unless I'm missing something there is margin for error here. In your example 200 x 200 guarantees one side of the image will be 200px, but doesn't guarantee the other side will be at least 100px. What happens then?
NUL76 replied on at Permalink Reply
NUL76
Yeah... You have to keep that in mind when you're resizing to a smaller size. You can also just change 200x200 to e.g. 500x500 or 1000x1000.

So it's good to think about this what the most suitable size is for the website.
MrNiceGaius replied on at Permalink Reply
MrNiceGaius
Thanks for sharing, this technique will be really useful for using other thumbnail processing scripts as well like phpThumb for example (make sure to get the patched version!) ... anyways I'm sure your script will work just fine I just thought I should thank you for giving me some new ideas

Cheers,

and thanks Kirkroberts for this handy addon, I like the idea of using the original c5 image block and the default image.php helper so this is perfect and I think the css cropping is probably fine.

*I highly recommend the custom image.php helper class that jorden and kirk posted here, it's what I've been using for all of my hard-coded cropped thumbnails within templates.

Seriously though who in the world wants to have image thumbnails that don't automatically "zoom-crop"??? I really do hope the cropping functionality that jorden and kirk added makes it's way into the core.

Anyhow,
- if you just need a quick and dirty block for your client to add cropped thumbnails then Kirks CSS cropper is sweet,
- if you need to output thumbnails in a page_list template for example then the image.php helper class is the way to go...
- and if you want really fancy thumbnail generating options in addition to cropping then NUL76's solution would work and you could use any php thumbnail generating script you want.
carl101lee replied on at Permalink Reply
carl101lee
Hi There

I am trying to use your thumbnail script - to resize any image with the customer attribute photo_attribute_name.

OK I have uploaed your thumnail.php and the cashe folder to root/libraries/ folder

Then I went about rcreateding a custom attribute with the name photo_attribute_name by creating a root/models/attribute/type/photo_attribute_name/controller.php (which from what I understand is wher i need to put the code to do what ever i want the attribute to do. The contoller.php is set-out in a way I dont unsderstand and I just want it to do your php command above i guess!

CAn you give me an example of what to put in controller.php or am i doing this conpletely wrong.

What I need to do is you see I haev an image block which uses file sets but it does not scale the images, and the end user wishes to upload direct from his camra? (which means the file size and res is huge, So I would liek to be able to set a resize attribute whcih res-resizes the image when uploaded and selected. Or even have it that this is auto done when added to file set -Into-Banner?

Is this possible?
Many Thanks For any help
Carl Lee
kirkroberts replied on at Permalink Reply
kirkroberts
You can now resize and crop using c5's built-in image helper (assuming you're using 5.4.2 or higher ... I think that was when they implemented this in the core).

$ih = Loader::helper('image');
$f = $c->getAttribute('YOUR_ATTRIBUTE_HANDLE');
$width = 200;
$height = 100;
$crop = true;
$img = $ih->getThumbnail($f, $width, $height, $crop);
echo '<img src="' . $img->src . '" width="' . $width . '" height="' . $img->height . '" alt="' . $f->getTitle() . '" />';


Hope that helps!
(code just typed in, not tested)
braincramp replied on at Permalink Reply
braincramp
I can't seem to get this installed on 5.4.1. It keeps telling me it can't create some croppable_image class or something when I put this in the blocks folder. Am I missing something? Any help would be great.
kirkroberts replied on at Permalink Reply
kirkroberts
Thanks for letting me know.
I haven't tried using the block on a 5.4.1 site yet.
I'm pretty busy right now but I'll try to take a look and get back with you.
kirkroberts replied on at Permalink Reply
kirkroberts
Just tried installing the block on a 5.4.1 upgrade and it worked.

Sounds like maybe you're getting the error when you go to Add Functionality in the dashboard. If that's the case, then there is probably another instance of a block trying to use the same class name. This might happen if you've duplicated the folder, but renamed one of them (that just happened to me :-).

Good luck!
braincramp replied on at Permalink Reply
braincramp
Thanks I will check the duplicate problem.
braincramp replied on at Permalink Reply
braincramp
Yes, the duplicate was the issue. Thanks
jordanlev replied on at Permalink Reply
jordanlev
I just uploaded an image helper class that includes cropping, so if you don't mind getting your hands dirty just a little bit this might be helpful to you:
http://www.concrete5.org/index.php?cID=70847#89293...
braincramp replied on at Permalink Reply
braincramp
I will give this a shot, but I can tell you this will be very useful for some other hacks I have in place. Btw your Deluxe Gallery looks awesome, I will definitely be replacing some other galleries with it.
kirkroberts replied on at Permalink Reply
kirkroberts
Jordan, this is going to obviate the need for a cropping image block (at least 99% of the time). Really, I don't usually want the editor to have that much control anyway :-) Thanks!
jordanlev replied on at Permalink Reply
jordanlev
You're welcome -- thank you for your original inspiration in that other thread where you posted your CSS cropping code!
braincramp replied on at Permalink Reply
braincramp
Perhaps I just don't understand completely, but how do I get this functionality for blocks like image blocks and such? I can understand for custom templates that I can call helpers and specify sizes but let's say it is something like this croppable image block, how would I do that?
kirkroberts replied on at Permalink Reply
kirkroberts
Jordan may answer more eloquently, but basically the helper enables you to size and crop on the code level.

So, in a block template view.php file (or maybe in a page type) you would use the code
$ih = Loader::helper('image');
$thumb = $ih->getThumbnail($fileObj, 100, 100, true);

(assuming you've put the new helper in your /helpers directory)

This takes the $fileObj and resizes it to as small as it can be and still fill up the 100 x 100 pixel space. The "true" argument is what forces the crop. If that were left off or set to "false" the image would be as big as it can be while still fitting in the 100 x 100 pixel space.

Still haven't tested the new helper class, but that's the theory.

Hope that helps!

EDIT: to be clear, you would probably use this in a custom block you create, or in a custom view template for something like a Page List block. It lets you control cropping on the code side. The Croppable Image Block might still be useful if you want to put the control in the hands of an editor.
jordanlev replied on at Permalink Reply
jordanlev
kirk is correct -- you use this in your own code. But you could also modify the built-in image block very easily to support this. Just copy concrete/blocks/image/controller.php to blocks/image/controller.php, then edit the new file like so:
find this line...
$thumb = $ih->getThumbnail($f, $mw, $mh);

(should be around line 65)
and change it to this:
$thumb = $ih->getThumbnail($f, $mw, $mh, true);
freestylemovement replied on at Permalink Reply
freestylemovement
This is a really interesting thread. i've been wanting to create a page list block that utilizes an auto crop from actual page content. has anyone worked with this sort of idea before?

the idea would be that in a media blog, you'll usually include an image or video at the top. it would be amazing if there was a way to pull the first image in 'main' to resize/crop..
enlil replied on at Permalink Reply
enlil
jordanlev replied on at Permalink Reply
jordanlev
You can customize the Page List template to pull the first image block and display it like so (put this inside the "foreach ($pages as $page)" loop):
$blocks = $page->getBlocks('Main');
foreach ($blocks as $block) {
   if ($block->btHandle == 'image') {
      $block->display();
      break; //stop looping through the blocks now that we've found the first image
   }
}


If, however, you don't have an actual 'image' block there, but rather a 'content' block with an image embedded in it... that is more difficult because you need to parse the content block's html to pull out an image tag. It can be done, but is very error-prone and you're probably better off telling users to use an image block. Or you could make a new area on the page (in your page type template) for a 'Teaser' or something and just display every block in that area. Finally, another option is the free "Page List Teasers" addon in the marketplace -- this will not be specific to images, but will show excerpts of actual page content from the pages it lists.

Good luck!

-Jordan