Showing posts with label photos. Show all posts
Showing posts with label photos. Show all posts

Resize image on the fly with ASP.NET MVC

I built a piece of code sometime ago and today I decided to optimize it.

My use case is this: a user can upload some photos of his house for example. Image dimensions (height x width) are not restricted. The user can upload any photo as long as its size is less than or equal to 750 KB.

Then, I have a listing page (Index.cshtml) that has a WebGrid. The grid shows realties available for sell, rent, etc. In this grid I want to display just a thumbnail of a given photo (the first one I grab as per code bellow) for each realty. I placed a constraint such that the thumbnail dimensions must be 100x100 pixels. Of course one shouldn’t load the full size version of a photo just to show it on the grid. The grid has 10 rows per page and if the images are on the range of 500 KB, the load put on the user connection to transmit all those photos from the server to the client would be high: 10 x 500 KB ≃ 5 MB. This would be an unresponsive page! No doubt…

Googling a little bit I stumbled upon something I didn’t know yet. It’s called WebImage and comes in System.Web.Helpers just as the WebGrid I discussed earlier. With this little kid on the block, one can have a controller “action” that does something like this:

public void GetPhotoThumbnail(int realtyId)
{
// Loading photos’ info from database for specific Realty...
var photos = DocumentSession.Query<File>().Where(f => f.RealtyId == realtyId); if (photos.Any()) { var photo = photos.First(); new WebImage(photo.Path) .Resize(101, 101, false, true) // Resizing the image to 100x100 px on the fly... .Crop(1, 1) // Cropping it to remove 1px border at top and left sides (bug in WebImage) .Write(); } // Loading a default photo for realties that don't have a Photo new WebImage(HostingEnvironment.MapPath(@"~/Content/images/no-photo100x100.png")).Write(); }
Calling the .Write() method does the magic. As you can see, I’m not saving the thumbnail in the disk, that is, a new image is generated on the fly/dynamically and sent to the user’s browser. Amazing…
In a view using the Razor syntax one would have something like this to display the photo:
<img src="@Url.Action("GetPhotoThumbnail", new { realtyId = item.Id })" width="100" height="100"/>
Another useful variation/overload of the above action method is this one (even more dynamic):
public void GetPhotoThumbnail(int realtyId, int width, int height)
{
    // Loading photos’ info from database for specific Realty...
    var photos = DocumentSession.Query<File>().Where(f => f.RealtyId == realtyId);

    if (photos.Any())
    {
        var photo = photos.First();

        new WebImage(photo.Path)
            .Resize(width, height, false, true) // Resizing the image to 100x100 px on the fly...
            .Crop(1, 1) // Cropping it to remove 1px border at top and left sides (bug in WebImage)
            .Write();
    }

    // Loading a default photo for realties that don't have a Photo
        new WebImage(HostingEnvironment.MapPath(@"~/Content/images/no-photo100x100.png")).Write();
}
Then, in the view one would call the action passing the width and height variables as per requirement:
<img src="@Url.Action("GetPhotoThumbnail", new { realtyId = item.Id, width = 100, height = 100 })" />
There are a handful of available functions in a WebImage. You should really check them out.

You can find more insightful info about the WebImage class reading this post by Gunnar Peipman: ASP.NET MVC 3 Beta: Simple image manipulations using WebImage helper

Note: there really are better ways of handling this kind of situation (adding image caching, etc – see ImageResizer) but for the site I’m working on, the solution I show in this post is sufficient and pretty responsive right now.

Hope it helps.

Extract GPS coord from Google Maps to geotag photos

This is a quick tip related to something that I just tried today and that worked.

My camera SONY DSC-HX100V has GPS capability built-in but it won't work everywhere and it needs some time to acquire the satellite signal. This way if you just want to take a quick snap you may end with photos that don’t have GPS location in their Exif metadata. GPS is a recent capability when we talk about cameras.

SONY DSC-HX100V camera with built-in GPSFigure 1 - SONY DSC-HX100V camera with built-in GPS

Taking that into consideration, let’s say you have some photos in iPhoto (Mac OS) or whatever program you use to manage your photos. I mention iPhoto here since it’s the app I use. Those photos don't have a location set due to no GPS signal available where the photos were taken. So how can one add that missing GPS location info/data on those photos? By the way, this process is called geotagging.

This is what I’ve tried and what worked perfectly in my case:

1 - Open Google Maps and find the place/point where you’ve taken the photos.

2 - Right click that place/point you want in the map and select Center Map here.

3 - Click the Link button. Black mouse pointer is over it in the screenshot bellow.

Google Maps link popup box with URL that contains GPS coordinatesFigure 2 - Google Maps link popup box with URL that contains GPS coordinates

A popup box will open. Copy the text/URL and paste it in your preferred text editor app. The link will look something like this:

http://maps.google.com/maps/ms?msid=201266260819946046546.0004a0e1b939dec67f18e&msa=0&ll=-22.428568,-44.619633&spn=0.001983,0.004128

Pay attention to the highlighted part that correspond to the longitude and latitude data.

4 - Select the photos you want in iPhoto to apply Location information and press command+I to access the Assign a Place box. Copy the highlighted text above and paste it in the box. Press the enter key to finish the task.

Adding GPS coordinates to iPhoto Assign a Place boxFigure 3 - Adding GPS coordinates to iPhoto Assign a Place box

This procedure works great when you just want to add GPS coordinates in your photos no matter if your camera has a built-in GPS or not since any photo can be geotagged nowadays.

Hope it helps!

You can check my photos in this slideshow: