Rasterleştirilmiş metni yeniden boyutlandırın ve pikselsiz görünmesini sağlayın


11

Bu, bir metin düzenleyicisine yazılan bazı metinlerin ekran görüntüsüdür:

16 piksel yüksekliğinde metin

Bu, daha büyük boyutta aynı metindir.

96 piksel yüksekliğinde metin

Örtüşmeninx ve gibi belirgin çapraz darbeleri olan harflerde ne kadar görünür olduğuna dikkat edin z. Raster yazı tiplerinin TrueType gibi "ölçeklenebilir" biçimlerde popülerliğini kaybetmesinin önemli bir nedeni budur.

Ancak, bu, raster yazı tiplerinde, sadece ölçeklendirmenin tipik olarak uygulanma biçiminde doğal bir sorun değildir. Burada basit kullanarak alternatif bir yerinde oldu doğrusal interpolasyon ile kombine eşikleme .

Bilineer enterpolasyon ile oluşturulan 96 piksel yüksekliğinde metin

Bu daha yumuşak ama ideal değil. Çapraz vuruş hala engebeli ve benzeri kavisli harfler cve ohala poligonlardır. Bu özellikle büyük boyutlarda fark edilir.

Peki daha iyi bir yol var mı?

Görev

Üç komut satırı argümanı alan bir program yazın.

resize INPUT_FILE OUTPUT_FILE SCALE_FACTOR

nerede

  • INPUT_FILE, beyaz bir arka plan üzerinde siyah metin içeren bir görüntü dosyası olduğu varsayılan girdi dosyasının adıdır. Uygun olan herhangi bir genel raster görüntü formatını (PNG, BMP, vb.) Kullanabilirsiniz .
  • OUTPUT_FILE, çıktı dosyasının adıdır. Raster veya vektör görüntü formatı olabilir. ClearType benzeri bir alt piksel oluşturma işlemi yapıyorsanız renk tanıtabilirsiniz.
  • SCALE_FACTOR, görüntünün ne kadar yeniden boyutlandırılabileceğini gösteren pozitif bir kayan nokta değeridir. Bir verilen x x y piksel giriş dosyasını ve faktör ölçekleme s , çıkış arasında bir büyüklüğe sahip olacak sx x sy piksel (tam sayıya yuvarlanarak).

Üçüncü taraf açık kaynaklı bir görüntü işleme kütüphanesi kullanabilirsiniz.

Kodunuza ek olarak, ilk görüntümü girdi olarak kullanarak programınızın örnek çıktılarını 1.333, 1.5, 2, 3 ve 4 ölçek faktörlerine ekleyin . Ayrıca, orantılı aralıklı olanlar da dahil olmak üzere diğer yazı tipleriyle de deneyebilirsiniz.

puanlama

Bu bir popülerlik yarışması. En fazla yukarı oy alan eksi aşağı oy alan giriş kazanır. Tam bir bağ olması durumunda, önceki giriş kazanır.

Düzenleme : Girişlerin olmaması nedeniyle süre uzatıldı. TBA.

Seçmenler öncelikle çıktı görüntülerinin ne kadar iyi göründüğüne ve ikincil olarak algoritmanın sadeliğine / zarafetine dayanarak karar vermeye teşvik edilir.


Her SCALE_FACTORzaman> 1 midir?
kennytm

@kennytm: Evet. Ölçek faktörlerini açıkça listelemek için düzenlenmiştir.
dan04

Resimde yalnızca bir metin satırı olduğunu varsayabilir miyiz?
GiantTree

@ DevTree: Evet. İsterseniz çok satırlı metni destekleyebilirsiniz, ancak bu gerekli değildir.
dan04 02

Yanıtlar:


4

Ruby, RMagick ile

Algoritma çok basittir; şöyle görünen piksel desenlerini bulun:

    ####
    ####
    ####
    ####
########
########
########
########

ve bu şekilde görünmeleri için üçgenler ekleyin:

    ####
   #####
  ######
 #######
########
########
########
########

Kod:

#!/usr/bin/ruby

require 'rmagick'
require 'rvg/rvg'
include Magick

img = Image.read(ARGV[0] || 'img.png').first
pixels = []
img.each_pixel{|px, x, y|
    if px.red == 0 && px.green == 0 && px.blue == 0
        pixels.push [x, y]
    end
}

scale = ARGV[2].to_f || 5.0
rvg = RVG.new((img.columns * scale).to_i, (img.rows * scale).to_i)
    .viewbox(0, 0, img.columns, img.rows) {|cnv|
    # draw all regular pixels
    pixels.each do |p|
        cnv.rect(1, 1, p[0], p[1])
    end
    # now collect all 2x2 rectangles of pixels
    getpx = ->x, y { !!pixels.find{|p| p[0] == x && p[1] == y } }
    rects = [*0..img.columns].product([*0..img.rows]).map{|x, y|
        [[x, y], [
            [getpx[x, y  ], getpx[x+1, y  ]],
            [getpx[x, y+1], getpx[x+1, y+1]]
        ]]
    }
    # WARNING: ugly code repetition ahead
    # (TODO: ... fix that)
    # find this pattern:
    # ?X
    # XO
    # where X = black pixel, O = white pixel, ? = anything
    rects.select{|r| r[1][0][1] && r[1][1][0] && !r[1][2][1] }
        .each do |r|
            x, y = r[0]
            cnv.polygon x+1,y+1, x+2,y+1, x+1,y+2
        end
    # OX
    # X?
    rects.select{|r| r[1][0][1] && r[1][3][0] && !r[1][0][0] }
        .each do |r|
            x, y = r[0]
            cnv.polygon x+1,y+1, x+0,y+1, x+1,y+0
        end
    # X?
    # OX
    rects.select{|r| r[1][0][0] && r[1][4][1] && !r[1][5][0] }
        .each do |r|
            x, y = r[0]
            cnv.polygon x+1,y+1, x+0,y+1, x+1,y+2
        end
    # XO
    # ?X
    rects.select{|r| r[1][0][0] && r[1][6][1] && !r[1][0][1] }
        .each do |r|
            x, y = r[0]
            cnv.polygon x+1,y+1, x+2,y+1, x+1,y+0
        end
}
rvg.draw.write(ARGV[1] || 'out.png')

Çıktılar (resmi tek başına görüntülemek için herhangi birini tıklayın):

1,333

1,333

1.5

1.5

2

2

3

3

4

4

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.