5

I'm working on the rails backend of a native app.

In a native app, retina (high resolution) images are automatically loaded using the @2x naming convention.

For example, you can have two images called image.png and image@2x.png (the higher resolution version of the same image). If the app is running on an iPhone 3gs, image.png is automatically loaded. If the app is used on an iPhone 4, image@2x.png will be loaded automatically.

This @2x convention doesn't work for non-native web apps according to what I've read and seen in action.

It seems that Apple's @2x convention doesn't work for images supplied by a Rails backend. I know that media queries can help with this, but I'm wondering if there is some sort of work around for having an iPhone 4 automatically load @2x images from a web app instead of the non-highres counterpart.

Emil
  • 7,220
  • 17
  • 76
  • 135
user1212187
  • 51
  • 1
  • 1
  • 3
  • 3
    You're going to need to explain this so much better if you want anyone to answer it. Especially what you mean by the @2x convention – Ryan Bigg Feb 15 '12 at 19:21
  • 3
    @RyanBigg The '@2x' naming convention will be instantly familiar to any iOS developer. It's simply a way of naming an alternate, high-resolution version of an image so that it will be recognized and used by high-resolution devices. – Caleb Feb 15 '12 at 21:02

6 Answers6

4

I suggest the following:

In your rails app, create different versions of the images when uploaded.

Then in the iOS app, you could have a look at the scale property of UIScreen and determine which image to load:

if ([[UIScreen mainScreen] scale] == 2.0f){
  //load retina image
} else {
  //load non-retina image
}
Jakob W
  • 3,347
  • 19
  • 27
  • I've seen your answer a lot, but I'm trying to do something slightly different. Let's say in a Rails view I display <%= image_tag "image.png" %>. Even if image@2x.png exists in the same directory as image.png, the iPhone4 running the Rails app loads image.png. I know that I can determine the device pixel ratio (to determine if it's a retina device) using Javascript and store it using a cookie and then conditionally serve images based on the cookie value, but I was wondering if there's another work around that's more automatic on the client side and doesn't require the backend to use a cookie. – user1212187 Feb 15 '12 at 22:51
  • You say in your question that this is a native app, but yet in your comment you mention using views. Well which is it? Jakob's solution is predicated on using a native app, contacting the Rails server via an API. This will obviously not work if your iPhone app is merely opening a UIWebView and loading a view from Rails, and a server-side session var may be your only bet in that case. – poetmountain Aug 07 '12 at 05:08
2

The HiSRC gem works nicely: https://github.com/haihappen/hisrc-rails

It uses the same naming convention as Apple (@2x for retina images) and automatically serves the correct one.

I used this in conjunction with CarrierWave, creating two thumbnail versions upon upload:

version :retina_thumb do
  process :resize_to_fill => [200, 200]
  def full_filename (for_file = model.photo.file)
    "thumb@2x.jpg"
  end
end

version :thumb, :from_version => :retina_thumb do
  process :resize_to_fill => [100, 100]
  def full_filename (for_file = model.photo.file)
    "thumb.jpg"
  end
end

And in your view:

<%= responsive_image_tag user.photo_url(:thumb).to_s %>

Another gem I tried was Clear Eyes, but I couldn't get it to work...

Brian
  • 1,028
  • 12
  • 20
1

Is this not the simplest solution - or do I miss something?

<%= image_tag("image.png", srcset: { "image@2x.png" => "2x"}) %>
0

I've written a rails gem this should solve the problem

The iOSDev
  • 5,237
  • 7
  • 41
  • 78
0

I've packaged a solutions as a gem https://github.com/jhnvz/retina_rails

Al you have to do is:

  1. Add gem 'retina_rails' to your Gemfile.
  2. Run bundle install.
  3. Add //= require retina to your Javascript manifest file (usually found at app/assets/javascripts/application.js).

Carrierwave

  1. Add include RetinaRails::CarrierWave to the bottom of your uploader

    class ExampleUploader < CarrierWave::Uploader::Base
    
      version :small do
        process :resize_to_fill => [30, 30]
      end
    
      include RetinaRails::CarrierWave
    
    end
    

Paperclip

  1. Add include RetinaRails::Paperclip to the bottom of your uploader

    class ExampleUploader < ActiveRecord::Base
    
      has_attached_file :image,
        :styles => {
           :original => ["800x800", :jpg],
           :big => ["125x125#", :jpg]
         }
    
      include RetinaRails::Paperclip
    
    end
    

The gem automatically generates retina versions (appends @2x to filename) based on your defined versions in an uploader. The js checks if the users got a retina display and if so appends @2x to the image file name.

Also posted this answer in: How do you generate retina (iPad) friendly (progressive or interlaced) jpeg images with CarrierWave?

Community
  • 1
  • 1
0

What do you think about this approach:

Uploading a raw file with high resolution and then just generate the 3 different sizes. Here for an Icon model I want to implement:

  has_attached_file :attachment,
  storage: :s3,
  s3_credentials: Rails.configuration.aws,
  s3_protocol: :https,
  s3_host_name: 's3.amazonaws.com',
  url: ':s3_domain_url',
  path: ':class/:attachment/:id_partition/:style_:basename.:extension',
  styles: {
    '@3x_thumb': '192x192>',
    '@2x_thumb': '128x128>',
    'thumb': '64x64>'
  },
  convert_options: { 
    all: '-strip', 
    '@3x_thumb': '-quality 100 -interlace Plane', 
    '@2x_thumb': '-quality 100 -interlace Plane', 
    'thumb': '-quality 100 -interlace Plane'
    },
  :s3_headers => { 'Cache-Control' => 'max-age=3600' }

I am not sure what convert option are correct but the naming and sizing problem is solved.

Simon Franzen
  • 2,628
  • 25
  • 34