Welcome Guest, Not a member yet? Register   Sign In
Best Practice for Images : Generating Thumbs or Resizing on the Fly
#1

[eluser]Steve_K[/eluser]
Hi all,

I know there's been a good deal written on thumbnail generation and the like, but I wanted to explain what I've made and see what kind of best-practice advice I could find. Here's my story...

Currently, I have a site which allows users to upload collections of photos to projects they've created after first creating an account. Upon account creation, the site generates folders for the users in the following fashion for each of five pre-defined projects:

/students/username/project_num/images/thumbs/

(This is to say that within a pre-created students folder, the username, project_num, images and thumbs folders are created recursively five times.)

When a user uploads images to a project, I have a gallery controller which uploads the full images into the images folder for the project_num, and then creates a smaller thumbnail which maintains its ratio. So far so good.

On the index page of the site, where these thumbnails and full images are displayed, I had a bit of a brain lapse, thinking I could simply output the full image while resizing it via css for a 'medium-size' image which would lead to the full-size image when clicked.

(To be clear, the path is: Click on thumbnail --> Load scaled full-size (medium-size) image via ajax into a display area above thumbs --> Click on medium-sized image --> Load full size image via lightbox, or something of that nature.)

I have everything working to this point, except, as one might imagine, resizing the full-sized images with css doesn't maintain aspect ratio for the thumbs, which means I need to find the best way to resize these.

In thinking about it, I figured I had two options:
1. I could resize the image on the fly when the user clicks a thumbnail to load the medium-sized image via ajax. (I have a method 'get_image($url)' in my gallery controller which simply loads a view with an image tag and the image source passed to it, etc.) I thought perhaps I could send it first to my gallery model, resize it there on the fly, and send it on to the view.

The problem I'm having is that resizing it on the fly and echoing it out gives me the raw image data (I apologize, I don't know that's the right term). I've tried using data_uris to format the raw data into something echoable, but with no success. Is this method possible?

2. The second option I considered was to generate a second medium-sized thumbnail when the user uploads the image with maintain_ratio set to true. This method is slightly less ideal, given that when providing a way for the user to delete their projects, I'll need to scan for an additional set of images to delete. Not a huge deal, definitely, but something I figured could be avoided by generating the medium-sized image on the fly.

I hope I've been clear in my explanations, if long-winded! I'm very curious to see what suggestions folks have about the best way to handle this.

Much thanks for reading, and any suggestions are much-appreciated!

Steve K.
#2

[eluser]Jondolar[/eluser]
You need to change the html header if you want to output the image (after resizing, etc.) and make sure you only output the image data with no other data. You'll need to search for proper headers to use when outputting an image.

Also, regenerating/resizing an image on every page load is pretty intensive. You might want to cache the image. There are two basic ways to cache the image. 1. Standard cache where you generate the image on the fly only if a cached version doesn't already exist. 2. Create the medium sized image when the image is uploaded.

I recommend you create the medium and thumb images when the image is uploaded. Disk space is cheap, usually. Plus, if you look at the size of your medium and thumb (possibly created with a lower quality level), you might see that they only take up 10% to 20% more disk space than the original.

Good luck with your project.
#3

[eluser]shoelessone[/eluser]
So I'm going to ask a question, but just so I understand the problem and learn something.

Why can't just show the thumbnail, and then if/when somebody clicks for the medium size image, you use JS to somehow display the medium image, and use the thumbnails name to come up with the medium image, and use CSS to scale the medium image?

I mean, you wouldn't even need ajax? right? I'm assuming you've got some naming convention (image_name_thumb.jpg and image_name_full.jpg or something) so you could just set the src of the medium image?

And you said CSS distorts the dimensions of the photo, but only if you specify a width AND height.. Could you get away with just containing the width (or height)? I mean, for a fixed width layout that might work, right?

So onclick of thumbnail, add whatever markup you need with JS, and set the source to the resized version of the full size jpg (whose name you get from the thumbnail image name, or by pre-populating it somehwhere on page load), then onclick again displays the image full size (it would have been cached at that point)?
#4

[eluser]Steve_K[/eluser]
@ Jondolar : Thanks for the suggestions, they're very helpful.

@ shoelessone :

Thanks for your reply. I should clarify that, when I say 'AJAX', what I'm really doing is exactly what you're saying. I have a thumb which links to a view which has an image tag whose source gets dynamically re-generated and displayed on-click. Then I have CSS which resizes the fullsize image down to a medium size. I didn't know about the fact that CSS would scale proportionally if I didn't give it a height, so thanks very much for that, as it, in effect, at least partially does what I want. The problem now is that because the displayed image's height isn't fixed, it pushes the thumbnails beneath it down, or raises them up, depending on its variable height. The only way I see to have a fixed width / height is to create other thumbs with maintain_ratio set to true and then wrap the thumbs in a containing div with padding and a fixed width height which are equal to the parameters I pass to resize.

Anyhow, all that to say THANKS for this - it was really insightful, and I appreciate it. (And if you feel I've got my facts or logic wrong here, let me know!)
#5

[eluser]shoelessone[/eluser]
In that case (and again, maybe I'm misunderstanding something), could you use something like this http://staff.osuosl.org/~rob/jquery.scale/index.htm ? It's basically a jQuery plugin that will automatically resize an image to fit inside of it's container.

Or possibly even easier/cleaner, write a bit of JS that does something like
if thumb.height>thumb.width
then set the medium.height=whatever you specify
else set medium.width = whatever you specify

(in other words, if it's a landscape image then constrain the width, if it's portrait constrain the height). I'm guessing there might be a better way to do this (I'm guessing the suedo code won't work Wink)

EDIT: for the record, I think that making a medium thumbnail is very likely the best solution though, because obviously if somebody doesn't have JS enabled then your page won't degrade very well if JS is required to resize the image. I'm sure you could make it degrade fairly well (or do what I do and just hope everybody has JS Wink), but if you can spare the cpu cycles and space, the medium thumbnail might be the safest/easiest way to do this.
#6

[eluser]Steve_K[/eluser]
I like the JS fit-in-container option, yeah. I'd thought about that, too, but was giving it a go with CSS for a bit before I moved to JS. I reckon the plugin would work best, given that it looks for the dimensions of a container? As I understand it, if the JS just changed the width and height to whatever I specified, it's essentially acting like fixed CSS. Also, I've noticed that setting the display of the image to a percentage width via CSS has some decent results, as well.

I'll give the jQuery plug a try, thanks!

EDIT: Yeah, such was my thought, too. Honestly, the variable height doesn't look bad, though.
#7

[eluser]CroNiX[/eluser]
Personally, I'd have it create a thumbnail using an image library (true thumbnail, not a large image displayed at a different size with css/image attributes) and store both the large image and the thumbnail. Use the thumbnail to click to get to the larger image. If you are just resizing large images via css you are wasting bandwidth and the time it will take to display that larger image. Not to mention an extra load on your server. Not a big deal unless you have a popular site with lots of visitors, which I presume is the end goal.
#8

[eluser]Steve_K[/eluser]
Thanks for the reply, Cronix, I appreciate the advice.

Currently, I've got the code for uploading the original image, and making three different sizes: thumb, med, display.

It works great, but only for smaller images, or so it seems. Any time I try to upload a larger image, the smallest resize call (thumbs) works, but the other two fail. Is there any way to find out why the CI resize() function fails more specifically than just returning false? My assumption is that, for some reason, since I have maintain_ratio set to true, it can't find an exact scale for the images and fails. Any suggestions on how I can further troubleshoot this?

Thanks!

EDIT: Also, if any mods think this should be a new topic, I'll be happy to move it to one.
#9

[eluser]danmontgomery[/eluser]
How big are these files? You might be hitting PHP's memory_limit or max_execution_time (both are php.ini settings)
#10

[eluser]CroNiX[/eluser]
You might try looking at your php error log to see whats going on. Noctrum's theory is also a good one to check into. If you have a good debugger, try stepping through the code to see where it blows up if adjusting the php ini settings doesn't help.




Theme © iAndrew 2016 - Forum software by © MyBB