Dinamiškas thumbnail ‘o generavimas

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]


11 Responses to “Dinamiškas thumbnail ‘o generavimas”

  1. dado1945 Says:

    Š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…

  2. ZaZa Says:

    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.

  3. admin Says:

    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ą.

  4. mid Says:

    o jei nuotraukų yra 100k? ir vienu metu browsinančių vartotojų koks 1k? :) ar ne per didelis overloadas hardwarui?

  5. admin Says:

    Getting real (scale later) =)

  6. Rimantas Says:

    http://www.kanthak.net/opensource/file_column/

  7. ZaZA Says:

    Gaila, kad tuose “Getting real (scale later)” niekada nerašo, apie tai kad reikia vis del to 10 kartu apmastyti prieš ką nors darant.

  8. Rimantas Says:

    ZaZa, jei kažkas to nežino, gal tegul jie ir nedaro nieko :)

  9. Rimantas Says:

    Dar liko pora klaidų calc_size :)

  10. Rimantas Says:

    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

  11. ZaZa Says:

    Rimantas, kol kas visa gyvenimo ir darbo praktika rodo, kad tam tikra dalis “kureju/developeriu” kaip tik vadovaujasi visishkai kitokia logika.

Leave a Comment