Loading images from database and displaying miniatures

Hi. I stuck with with one problem. Starting from beginning:

  • I’ve image file stored in DB;

  • I’m able to display it in grid column in original size;

And my solution look following (basing on some post from this forum);




//columns configuration from grid

        	array(

            	'name'=>'data',

            	'type'=>'raw',

            	'value'=>'CHtml::image(Yii::app()->urlManager->createUrl(\'/image/previewImage\',array(\'id\'=>$data->id)))'

        	),

//action in controller to get image on the fly

	public function actionPreviewImage($id)

	{

    	$model=DbImage::model()->findByPk($id);

    	header("Content-type: ".$model->type);

    	echo $model->data;

	}



It work perfectly until images are small. What I would like to do, is to resize images on the fly, let say to 200x100. I tried to use for that purpose image helper without success. Any idea how to modify my coding to get thumbs?

All available tools for image manipulation are usually file based. So you’d have to save the image back to the disk before you can resize it.

Maybe it was not that a good idea to save images to DB in the first place. I know, it’s tempting and about a decade ago i was convinced, too, that it would be way cool. But now you see, what price you have to pay (and there are even more drawbacks). If by any means you can move back to file based image store i’d recommend to do that. Take the right tools for the right job: DB for data, filesystem for binary stuff. Both are perfect at that. If you don’t, anything you want to do becomes more complicated than before.

Hope that doesn’t sound to “smart-assy” (if one can say that). :)

Frocco to the rescue:

Upload and rezise using PhpThumb ;)

<edit>

Agree: no reason to store the image itself in the database.

See the link ^

</edit>

Is not a good idea to resize image on the fly, better to resize when you save them and store the thumb too in the database.

I am one of the last knigths on the side of blob-image-storer in the never-ending war of religion about images in database/filesystem, and I resize them at the moment of upload (using the temp file) and I save both as blob.

There is a library that allows you to work with images on the fly, not on file, but, as Mike has noticed, is really more difficoult.

If you will join the dark side of blob-image-storer, be prepared to be alone against many, to use more difficoult libraries and to accused to slow down the database, but you will get the prize of integrity constrain!

Here a sample of code for resize image on the fly (but is better to do at upload):




		// maximum dimension

		$w=640;

		$h=640;

		$im = imagecreatefromstring($this->preview_data);

		

		$size[0] = imagesx($im);

		$size[1] = imagesy($im);

		$newwidth = $size[0];

		$newheight = $size[1];

		//calculate the new dimensions respecting the original sizes

		if( $newwidth > $w ){

			$newheight = ($w / $newwidth) * $newheight;

			$newwidth = $w;

		}

		if( $newheight > $h ){

			$newwidth = ($h / $newheight) * $newwidth;

			$newheight = $h;

		}

		// create the new image

		$new = imagecreatetruecolor($newwidth, $newheight);

		// copy the image with new sizes

		imagecopyresampled($new, $im, 0, 0, 0, 0, $newwidth, $newheight, $size[0], $size[1]);

		ob_start();

		ob_implicit_flush(false);

		

		if( $this->preview_mime == 'image/jpeg' ) imagejpeg($new, '', 100);

		elseif ( $this->preview_mime == 'image/gif' ) imagegif($new);

		elseif (  $this->preview_mime == 'image/png' ) imagepng($new);

		$this->preview_data=ob_get_clean();



Join the dark side! We have got cookies!!

Don’t start a war here please :)

I was just jocking.

I just said that is possible to do with a blob, and add a suggestion about how to do it.

As Mike has been so direct against blob, I just replicated in a jockling way, that’s all.

I hope you found my post or funny or useful, or both of them, I really didn’t want to be rude or arressive.

Why not keep images in db and then temporarily save the original image + resized version(s) (to a public path)? htaccess should come in handy there.

DbImage::getImageUrl($id, $width = null, $height = null);

This also has the benefit that you can simply flush the temp folder and the images will regenerate (eg on server crash, moving to another server, resize method changed…). So no need to move the files or manually regenerate the images all the time.

@zaccaria:

Hehe, don’t worry, i’m not a fanatic and always open to rational arguments.

In this case i just see no good reason to use a DB. If it’s about consistency: That’s where our fine before/afterSave and afterDelete events come into play. A perfect place to save/delete uploaded images for a record. You could even start a transaction beforeSave then try to save the image with id as filename afterSave and rollback if your save fails. One minor drawback is, you have to be carefull with deleteAll(…), as this will not call afterDelete. But any serious Yii developer will know that. ;)

I found that funny! Your humour wasn’t lost on me.:lol:

I am just wondering: Are there any benefits of storing images in a database?

If you store the name, path, size, attributes in the database and the images themselves in the file system, don’t we have a win-win here?

But it’s good to know that you can do this if you want. ;)

I save images in the database because I am lazy.

Saving images in database gives you lof of freedom about deletion, in fact free you from write:

  • an afterDelete in a model

  • an afterDelete in related model (like Office->manyPhotos, you have to write an afterDelete here)

  • an afterDelete in related model of related model(like User->manyOffices->manyPhotos, you have to write an afterDelete here)

And let you freely use deleteAll or any other delete method (for example by sql).

Also gives you advantages in backup: if you want to backup the site, you have to do the backup of database + backup of image folder, that means write 2 cronTask (if you want to avoid backup, there is ingoreTable option in mysqlDump).

If you are lazy enough I think that blob will suite you. Take the suggiestion of Y!! (very wisdom: images in database and thumb on fs, great!).

save binary data in database make the database too large and slow to load the data.

But I agree that saving binary data in database is more useful that when you save cache for example.