I had the honor of designing the new United Pixelworkers shirt for Seattle. Pick one up if you like it.
I see lots of blurry images out there on websites (and application webviews) designed for retina iPhone/iPad and more recently the new MacBook Pro. These images are not taking full advantage of the retina display’s pixel density.
Remember these things…
- Retina displays render HTML at the same “pixel” size as standard displays. This means your old width:1024px website is rendered the same size on retina. No need to go back and update old size definitions because retina displays basically understand one pixel as four tiny pixels.
- Retina HTML use four times the number of pixels to render those same elements (2X wide and 2X tall). System Fonts and CSS rendered graphics will convert to the new pixel density for free.
- Since both retina and standard displays render elements the same size, images on retina displays need the need the extra pixel data to fill in the 4X pixels.
It’s real easy to take advantage of the retina display pixel density. Just double the size of your images. If the design calls for a 100×50 pixel image you need to serve up a 200×100 pixel image. Use CSS to define the image back down to 100×50. This condenses the pixel density of the image to match the retina display density.
IMG elements can be resized with the usual CSS. When resizing background images, the new CSS3 background-size property is your best buddy.
background-size: 100px 50px;
/*First number is width. Second number is height.*/
You can combine the background-size and background-repeat properties for tiled images.
Be smart about performance. Whenever possible, use HTML/CSS properties instead of images. Also, you can use a combination of CSS media queries and server side techniques to avoid serving large retina-size images to non-retina displays. I’ll explain that in more detail with a later post.
Dropbox is great for testing retina iPhone mockups. Your design files are twice the size of the final product and it’s important to view them within the context of the device.
Create an alias/shortcut to your Dropbox testing folder on your desktop. Grab a screenshot the 960 x 640 design and throw it in the Dropbox alias/shortcut folder. Open it it up through Dropbox on your iPhone and view in @2x retina glory.
I find the workflow between screenshots and the alias/shortcut folder quick enough to allow rapid iteration.
Recently I’ve been working on a project to move our photo experience to store images on Amazon’s S3 service instead of the local server, in hopes to gain performance and move away from handling the maintenance static files tend to have.
There are many examples online of saving directly to Amazon and not using Django’s Storage Backend, however these examples tend to not give the best overall experience, specially when the site is for a customer. Why keep files on Amazon after a customer has deleted the relationship on your site? Paying for the extra space is something I’m not looking to do.
Luckily during this search I learned about Django’s Storage API and loved the concept and found a great package called django-storage that already has implemented S3 support. The documentation could use a bit of work, but isn’t too hard to get a handle of.
Now that I had the capability to save images to S3 I also wanted the possibility to resize said image and create a thumbnail.
The issue with this is that all examples I could find where in regards to either files saved on disk or stored in memory, neither of which was my case.
Below is example code that allows you to resize images using Django’s models.ImageField and PIL library. Hopefully this saves someone some time as it took me a few hours to come up with a solution.
import urllib2 as urllib
from PIL import Image
from cStringIO import StringIO
from django.core.files.uploadedfile import SimpleUploadedFile
'''Open original photo which we want to resize using PIL's Image object'''
img_file = urllib.urlopen(self.image.url)
im = StringIO(img_file.read())
resized_image = Image.open(im)
'''Convert to RGB if necessary'''
if resized_image.mode not in ('L', 'RGB'):
resized_image = resized_image.convert('RGB')
'''We use our PIL Image object to create the resized image, which already
has a thumbnail() convenicne method that constrains proportions.
Additionally, we use Image.ANTIALIAS to make the image look better.
Without antialiasing the image pattern artificats may reulst.'''
'''Save the resized image'''
temp_handle = StringIO()
''' Save to the image field'''
suf = SimpleUploadedFile(os.path.split(self.image.name)[-1].split('.'),
self.image.save('%s.jpg' % suf.name, suf, save=True)
Had some troubles finding what seemed to be such an easy Google search. Needed the capability to load an image based on a url. Here is my solution:
import urllib2 as urllib from PIL import Image from cStringIO import StringIO img_file = urllib.urlopen(self.image.url) im = StringIO(img_file.read()) resized_image = Image.open(im)
Recently I started looking into Amazon’s S3 service to (hopefully) offer better performance on serving up static content for our customers. Its a great service and ridiculously cheap. The first client I am applying the S3 storage to is for Dylan Priest Photography, its critical that the images load as fast as possible as that is the main content of his site. As our web-server is currently a bit overworked off loading the static content to S3 should help with overall performance.
Here at Hardly Code, we are mostly a Django shop. I found a great plugin called django-storages that has multiple different type of storages. The documentation is a little bit on the lite side and took a few hours to get the feel for it. (It was my first time not using the default storage.)
I was applying this to our Album app but when trying to edit an album I kept getting (Creating a new album worked fine):
NotImplementedError: This backend doesn't support absolute paths.
The conflict was in the s3boto storage class the path method was not implemented. As per the Django documentation, for non local storage you should not implement this method. The only way I found to solve this solution was to go ahead and implement this method in the django-storage code and modify storages.backends.s3boto and add the path method.
def url(self, name):
def path(self, name):
A fairly easy fix and as far as I can tell it hasn’t created any issues with the modification. Not sure if this a bug with django, django-storage, or my implementation, but it took me long enough to figure out that I thought I would document it and hopefully save someone else some time.
Awesome. I guess. Although Ask.com had this same feature in May of 2006. Ask.com even had a commercial about this
game-changer yet “Binoculars” didn’t really do much for the service.
I never found Binoculars useful. You could click an icon to see what a site looked like or you could click a link and be transported to the site. Continue reading