Preview and Resize Pictures on the Fly

    I redid the site to the customer on Netcat and was surprised to find that someone else was using the loading of individual pictures for the originals and for the previews and, as a result, the individual columns in the database table. Where it was still not going to create thumbnails on the server side after loading the original.

    The idea is simple and not new. I first came across this approach in UMI-CMS, but used it in RubyOnRails. The point is that previews are created only when they are needed and of any size, and only the name of the original is stored in the database.

    If you need to display a preview of the image, you call a function like:
    1. @thumbs = Photo.view_thumbs('originals_name_file.jpg', '100', 'auto')
    where the second and third parameters are the desired size in pixels (auto means automatic fit to scale).

    The view_thumbs method checks in the folder (for example, "/ images / cache") the presence of the file originals_name_file_100xauto.jpg. If it finds it, it returns the string "originals_name_file_100xauto.jpg", if it does not find it, it creates a file of the right size on the fly and returns the same.

    The advantages of the approach are obvious:
    1. No garbage is created in the form of a large number of thumbnails on the disk. All previews are stored in one cache folder and can be deleted periodically to free up space.
    2. Unlimited thumbnails of various sizes. It is enough to set the necessary parameters in the method.
    For cakePHP there is an images.php helper that can be pulled out of Bakesale (there is no automatic fitting). The following is a RubyOnRails method that implements this approach.

    1. require 'RMagick'

    2. class Photo < ActiveRecord::Base
    3.  
    4.   def self.view_thumbs(image, width = 'auto', height = 'auto')
    5.         img_arr = image.split(".")
    6.     img, img_type = img_arr[0], img_arr[1]
    7.  
    8.     img_thumbs = "#{img}_#{width}x#{height}"
    9.     img_main_dir = "#{RAILS_ROOT}/public/images/"
    10.     img_thumbs_dir = "#{RAILS_ROOT}/public/images/cache/"

    11.     begin
    12.       img_thumbs = Magick::Image.read("#{img_thumbs_dir}/#{img_thumbs}.#{img_type}")
    13.     rescue Magick::ImageMagickError  # Вся соль тут. Если нет нужного тхумбса, то после чтения вываливается ошибка, которую мы спасаем. Если всё нормально, то код далее не выполняется
    14.       img_orig = Magick::Image.read("#{img_main_dir}/#{image}").first
    15.       img_size = {:main =>{:cols => img_orig.columns,:rows => img_orig.rows},
    16.         :thumb =>{:cols =>0.0, :rows =>0.0}
    17.       }
    18.       if 'auto' == width and 'auto' == height
    19.         img_size[:thumb][:rows] = img_size[:main][:rows]
    20.         img_size[:thumb][:cols] = img_size[:main][:cols]
    21.       end
    22.       if 'auto' != width and 'auto' == height
    23.         img_size[:thumb][:rows] = ((width.to_f/img_size[:main][:cols])*img_size[:main][:rows]).to_i
    24.         img_size[:thumb][:cols] = width.to_i
    25.       end
    26.       if 'auto' == width and 'auto' != height
    27.         img_size[:thumb][:rows] = height.to_i
    28.         img_size[:thumb][:cols] = ((height.to_f/img_size[:main][:rows])*img_size[:main][:cols]).to_i
    29.       end
    30.       if 'auto' != width and 'auto' != height
    31.         img_size[:thumb][:rows] = height.to_i  
    32.         img_size[:thumb][:cols] = width.to_i        
    33.       end

    34.       img_new = img_orig.resize!(img_size[:thumb][:cols].to_i, img_size[:thumb][:rows].to_i)
    35.       img_new.write "#{img_thumbs_dir}/#{img_thumbs}.#{img_type}"
    36.     end
    37.     img_thumbs = x
    38.     return "#{img_thumbs}.#{img_type}"
    39.   end
    40. end

    Practice shows that specifying only one size in a method with automatic fitting of another is not enough. If you limit only by the width, then the picture will be caught too high and the whole layout can move out. Same thing with height. And in the above code, when specifying both the height and the width, the resize will be without preserving the scale. Below is a piece of php code that implements resize with restrictions both in height and width while maintaining the mass.

    1. $img_size = array(
    2.                         'main'=>array('width'=>imagesx($img_src), 'height'=>imagesy($img_src)),
    3.                         'thumb'=>array('width'=>0, 'height'=>0)
    4.                 );
    5.                
    6.                 if ('auto' == $width && 'auto' == $height) {
    7.                         $img_size['thumb']['height'] =(int) $img_size['main']['height'];
    8.                         $img_size['thumb']['width'] =(int) $img_size['main']['width'];
    9.                 }
    10.                 else if ('auto' != $width && 'auto' == $height) {
    11.                         $img_size['thumb']['width'] = (($img_size['main']['width'] <= $width) ? $img_size['main']['width'] : $width);
    12.                         $img_size['thumb']['height'] = (int) round(($img_size['thumb']['width']/$img_size['main']['width'])*$img_size['main']['height']);
    13.                 }
    14.                 else if ('auto' == $width && 'auto' != $height) {
    15.                         $img_size['thumb']['height'] = (($img_size['main']['height'] <= $height) ? $img_size['main']['height'] : $height);
    16.                         $img_size['thumb']['width'] = (int) round(($height/$img_size['main']['height'])*$img_size['main']['width']);
    17.                 }
    18.                 else if ('auto' != $width && 'auto' != $height) {
    19.                         $img_size['thumb']['height'] = (($img_size['main']['height'] <= $height) ? $img_size['main']['height'] : $height);
    20.                         $img_size['thumb']['width'] = (($img_size['main']['width'] <= $width) ? $img_size['main']['width'] : $width);
    21.                         $Kt = $img_size['thumb']['height']/$img_size['thumb']['width'];//5/1
    22.                         $Km = $img_size['main']['height']/$img_size['main']['width'];//5/1

    23.                         if ($Kt > $Km){
    24.                                 $img_size['thumb']['height'] = $img_size['thumb']['width']*$Km;
    25.                         }
    26.                         else if ($Kt < $Km) {
    27.                                 $img_size['thumb']['width'] = $img_size['thumb']['height']/$Km;
    28.                         }
    29.                 }
    ______________________
    The text is prepared in the Habr Editor from © SoftCoder.ru


    Also popular now: