래스터 화 된 텍스트의 크기를 조정하여 픽셀 화되지 않은 것처럼 보이게합니다.


11

텍스트 편집기에서 입력 한 일부 텍스트의 스크린 샷입니다.

16px 높이의 텍스트

더 큰 크기의 동일한 텍스트입니다.

96px 높이의 텍스트

어떻게 '보이는 공지 사항 앨리어싱이 눈에 띄는 대각선 같은 스트로크와 문자에 xz. 이 문제는 래스터 글꼴이 트루 타입과 같은 "확장 가능한"형식으로 인기를 잃은 주된 이유입니다.

그러나 이것은 래스터 글꼴의 본질적인 문제가 아니며 일반적으로 크기 조절이 일반적으로 구현되는 방식과 관련이 있습니다. 다음 은 임계 값 과 결합 된 간단한 이중선 보간을 사용하는 대체 렌더링 입니다.

쌍 선형 보간으로 렌더링 된 96px 높이의 텍스트

이것은 부드럽지만 이상적이지는 않습니다. 대각선 스트로크는 여전히 울퉁불퉁하고, 같은 곡선 문자 c와는 o여전히 다각형이다. 이것은 특히 큰 크기에서 두드러집니다.

더 좋은 방법이 있습니까?

작업

세 가지 명령 줄 인수를 사용하는 프로그램을 작성하십시오.

resize INPUT_FILE OUTPUT_FILE SCALE_FACTOR

어디

  • INPUT_FILE은 입력 파일의 이름으로, 흰색 배경에 검은 색 텍스트가 포함 된 이미지 파일로 간주됩니다. 편리한 주류 래스터 이미지 형식 (PNG, BMP 등)을 사용할 수 있습니다 .
  • OUTPUT_FILE은 출력 파일의 이름입니다. 래스터 또는 벡터 이미지 형식 일 수 있습니다. ClearType과 유사한 서브 픽셀 렌더링을 수행하는 경우 색상이 나타날 수 있습니다.
  • SCALE_FACTOR는 이미지 크기를 조정할 수있는 양을 나타내는 양의 부동 소수점 값입니다. x x y px 입력 파일과 스케일링 계수 s가 주어지면 출력의 크기는 sx x sy px (정수로 반올림 됨)입니다.

3 차 오픈 소스 이미지 처리 라이브러리를 사용할 수 있습니다.

코드 외에도 첫 번째 이미지를 입력으로 사용하여 1.333, 1.5, 2, 3 및 4 의 배율로 프로그램의 샘플 출력을 포함하십시오 . 비례 간격 글꼴을 포함한 다른 글꼴로 시도해 볼 수도 있습니다.

채점

이것은 인기 콘테스트입니다. 다수의 공감 율에서 공감 률을 뺀 항목이 이깁니다. 정확한 동점 일 경우, 빠른 출전이 이깁니다.

편집 : 항목이 없어 마감일이 연장되었습니다. TBA.

유권자들은 주로 출력 이미지가 얼마나 잘 보이는지, 그리고 둘째는 알고리즘의 단순성 / 우아함을 바탕으로 판단하도록 권장됩니다.


SCALE_FACTOR항상> 1?
kennytm

@kennytm : 예. 스케일 팩터를 명시 적으로 나열하도록 편집했습니다.
dan04

이미지에 한 줄의 텍스트 만 있다고 가정 할 수 있습니까?
GiantTree

@GiantTree : 그렇습니다. 원하는 경우 여러 줄 텍스트를 지원할 수 있지만 필수는 아닙니다.
dan04

답변:


4

RMagick과 함께하는 루비

이 알고리즘은 매우 간단합니다. 다음과 같은 픽셀 패턴을 찾으십시오.

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

다음과 같이 삼각형을 추가하십시오.

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

암호:

#!/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')

출력 (이미지를 단독으로 보려면 아무 것도 클릭) :

1.333

1.333

1.5

1.5

2

2

삼

4

4

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.