Dinamiškas thumbnail ‘o generavimas
- Posted on August 3rd, 2006 filed in RMagick, Ruby on Rails
Vakar vienam iš vystomų projektų reikėjo sukurti foto galerijos funkcionalumą. Nieko ypatingo: tiesiog "thumbnail'ai", kuriuos paspaudus iššoka naujas langas su originalaus dydžio nuotrauka. Kiek panaršius internete sukūriau testinį variantą, kuris rašė dvi bylas: originalą bei thumbnail'ą, tačiau kiek pamąsčius nusprendžiau, jog to paties paveikslo (nors ir skirtingo dydžio) saugojimas bei juo manipuliavimas neatitinka DRY principų =) Tad beliko tik parašyti kodą, kuris dinamiškai formuotu thumbnailą.
Veikimo principas: žemiau pateiktas kodas keliauja į application.rb, ir išbandyti jį galima taip: [jūsų controllerio pavadinimas] / img?src=rails.png
Update: dado1945 prašymu pateikiu sprendimą su thumbnail'ų kešavimų =) (Daugiau apie http kešavimą)
Update2: ištaisiau tikrai kvailą klaidą kai paveiksliukas nekeitė dydžio dėl vienodų matmenų =)
Update3: Rimanto dėka calc_size funkcijos kodas tapo daug gražesnis. Ačiū.
Tikiuosi kažkam padės sutaupyti laiko =)
[ruby]
BASE_SIZE = 200.0
def calc_size(width, height)
ratio = [width, height].max / BASE_SIZE
[width, height].map { |s| s.div ratio }
end
def img
require 'RMagick'
file = "public/images/#{params[:src]}"
if file and File.exists?(file)
req_last_modified = Time.rfc2822(@request.env["HTTP_IF_MODIFIED_SINCE"]) rescue nil
last_modified = File.mtime(file)
@response.headers['Last-Modified'] = last_modified.rfc2822
if req_last_modified and last_modified < = req_last_modified
render_text '', '304 Not Modified'
else
image = Magick::Image.read(file)[0]
width, height = calc_size(image.columns, image.rows)
image.resize!(width, height)
send_data(image.to_blob, :disposition => 'inline', :type => image.mime_type, :filename => file)
end
else
render_text "Image not found!"
end
end
[/ruby]
August 3rd, 2006 at 12:20 pm
Šaunuolis :-) Informacijos saugojimo prasme DRY principo nepažeidei, o pažeidei jį generuodamas tą pačią informaciją kiekvieną kartą kai jos reikia. Vat jeigu cache’intum sugeneruotus thumbnail’us tai jau būtų pilnas sprendimas…
August 10th, 2006 at 9:42 am
Hm, jai įdemiai peržiureti kodą, galima pamatyti kad yra išnaudojamas kešavimas vartotojo puseje - kas parodo, kad serverije gal but nera itin daug vietos, todėl buvo nuspresta išnaudoti processoriaus resursus.
Nors, asmeniškai bučiau linkes į sugeneruotu paveiksliuku kešavima ir mažu peržiuru generavima įkraunant paveiksliuką, bet bendrai, priklauso nuo projekto lankomumo ir serverio apkrovimo.
August 10th, 2006 at 7:49 pm
Pasirinkta paprastumo taktika: su nuotraukomis yra daromos skirtingos manipuliacijos ir daug papraščiau yra tvarkyti vieną bylą ir skirtingai ją atvaizduoti nei originalą ir thumbnailą.
August 16th, 2006 at 10:06 am
o jei nuotraukų yra 100k? ir vienu metu browsinančių vartotojų koks 1k? :) ar ne per didelis overloadas hardwarui?
August 16th, 2006 at 10:27 am
Getting real (scale later) =)
August 16th, 2006 at 5:04 pm
http://www.kanthak.net/opensource/file_column/
August 16th, 2006 at 5:41 pm
Gaila, kad tuose “Getting real (scale later)” niekada nerašo, apie tai kad reikia vis del to 10 kartu apmastyti prieš ką nors darant.
August 16th, 2006 at 5:58 pm
ZaZa, jei kažkas to nežino, gal tegul jie ir nedaro nieko :)
August 16th, 2006 at 7:22 pm
Dar liko pora klaidų calc_size :)
August 17th, 2006 at 4:31 pm
mano variantas:
BASE_SIZE = 200.0
def calc_size(width, height)
ratio = [width, height].max / BASE_SIZE
[width, height].map { |s| s.div ratio }
end
August 18th, 2006 at 12:47 pm
Rimantas, kol kas visa gyvenimo ir darbo praktika rodo, kad tam tikra dalis “kureju/developeriu” kaip tik vadovaujasi visishkai kitokia logika.