#!ruby -Ku # -*- mode: ruby; coding: utf-8 -*- # Last updated: <2017/04/08 23:17:51 +0900> # # scalenx.rb # # pixel scalking , Scale2x, Scale3x # # Author: mieki256 # License: GPL # # Original algorithm by Andrea Mazzoleni. # Scale2x # http://www.scale2x.it/ module ScaleNx # pixel scaling, Scale2x # @param src [Array] pixel data array # @return [Array] 2x pixel data array def scale2x(src) width, height = src[0].size, src.size nwidth, nheight = width * 2, height * 2 dst = Array.new(nheight).map { Array.new(nwidth) } dy = 0 dx = 0 height.times do |y| y0 = (y > 0)? y - 1 : y y1 = y y2 = (y < height - 1)? y + 1 : y ay0 = src[y0] ay1 = src[y1] ay2 = src[y2] width.times do |x| x0 = (x - 1 >= 0)? x - 1 : x x1 = x x2 = (x + 1 < width)? x + 1 : x a = ay0[x0] b = ay0[x1] c = ay0[x2] d = ay1[x0] e = ay1[x1] f = ay1[x2] g = ay2[x0] h = ay2[x1] i = ay2[x2] if b != h && d != f e0 = (d == b)? d : e e1 = (b == f)? f : e e2 = (d == h)? d : e e3 = (h == f)? f : e else e0 = e e1 = e e2 = e e3 = e end dst[dy][dx] = e0 dst[dy][dx + 1] = e1 dst[dy + 1][dx] = e2 dst[dy + 1][dx + 1] = e3 dx += 2 end dy += 2 dx = 0 end return dst end # pixel scaling, Scale3x # @param src [Array] pixel data array # @return [Array] 3x pixel data array def scale3x(src) width, height = src[0].size, src.size nwidth, nheight = width * 3, height * 3 dst = Array.new(nheight).map { Array.new(nwidth) } dx = 0 dy = 0 height.times do |y| y0 = (y > 0)? y - 1 : y y1 = y y2 = (y < height - 1)? y + 1 : y ay0 = src[y0] ay1 = src[y1] ay2 = src[y2] width.times do |x| x0 = (x - 1 >= 0)? x - 1 : x x1 = x x2 = (x + 1 < width)? x + 1 : x a = ay0[x0] b = ay0[x1] c = ay0[x2] d = ay1[x0] e = ay1[x1] f = ay1[x2] g = ay2[x0] h = ay2[x1] i = ay2[x2] if b != h and d != f e0 = (d == b)? d : e e1 = ((d == b and e != c) or (b == f and e != a))? b : e e2 = (b == f)? f : e e3 = ((d == b and e != g) or (d == h and e != a))? d : e e4 = e e5 = ((b == f and e != i) or (h == f and e != c))? f : e e6 = (d == h)? d : e e7 = ((d == h and e != i) or (h == f and e != g))? h : e e8 = (h == f)? f : e else e0 = e e1 = e e2 = e e3 = e e4 = e e5 = e e6 = e e7 = e e8 = e end dst[dy][dx] = e0 dst[dy][dx + 1] = e1 dst[dy][dx + 2] = e2 dst[dy + 1][dx] = e3 dst[dy + 1][dx + 1] = e4 dst[dy + 1][dx + 2] = e5 dst[dy + 2][dx] = e6 dst[dy + 2][dx + 1] = e7 dst[dy + 2][dx + 2] = e8 dx += 3 end dy += 3 dx = 0 end return dst end end if $0 == __FILE__ # ---------------------------------------- # usage sample require 'dxruby' require 'benchmark' include ScaleNx # convert DXRuby Image to array def conv_image2array(img) w, h = img.width, img.height data = [] h.times do |y| dt = [] w.times do |x| a, r, g, b = img[x, y] dt.push([r, g, b, a]) end data.push(dt) end return data end # convert array to DXRuby Image def conv_array2image(src) w, h = src[0].size, src.size img = Image.new(w, h, [0, 0, 0, 0]) h.times do |y| src[y].each_with_index do |v, x| r, g, b, a = v img[x, y] = [a, r, g, b] end end return img end imagefile = "hq3x_original.png" srcimg = Image.load(imagefile) src = conv_image2array(srcimg) dst2x = nil dst3x = nil Benchmark.bm do |x| x.report do dst2x = scale2x(src) end x.report do dst3x = scale3x(src) end end dstimg2x = conv_array2image(dst2x) dstimg3x = conv_array2image(dst3x) Window.resize(540, 360) Window.minFilter = TEXF_POINT Window.magFilter = TEXF_POINT Window.scale = 2 Window.loop do break if Input.keyPush?(K_ESCAPE) x, y = 0, 0 Window.draw(0, 0, srcimg) x += srcimg.width Window.draw(x, y, dstimg2x) x = 0 y += dstimg2x.height Window.draw(x, y, dstimg3x) end end