|
using Color, Images, ImageView |
|
|
|
function vt340_palette() |
|
pal = RGB[] |
|
push!(pal, RGB(0.00, 0.00, 0.00)) |
|
push!(pal, RGB(0.20, 0.20, 0.80)) |
|
push!(pal, RGB(0.80, 0.13, 0.13)) |
|
push!(pal, RGB(0.20, 0.80, 0.20)) |
|
push!(pal, RGB(0.80, 0.20, 0.80)) |
|
push!(pal, RGB(0.20, 0.80, 0.80)) |
|
push!(pal, RGB(0.80, 0.80, 0.20)) |
|
push!(pal, RGB(0.53, 0.53, 0.53)) |
|
push!(pal, RGB(0.26, 0.26, 0.26)) |
|
push!(pal, RGB(0.33, 0.33, 0.60)) |
|
push!(pal, RGB(0.60, 0.26, 0.26)) |
|
push!(pal, RGB(0.33, 0.60, 0.33)) |
|
push!(pal, RGB(0.60, 0.33, 0.60)) |
|
push!(pal, RGB(0.33, 0.60, 0.60)) |
|
push!(pal, RGB(0.60, 0.60, 0.33)) |
|
push!(pal, RGB(0.80, 0.80, 0.80)) |
|
pal |
|
end |
|
|
|
type SixelFile |
|
s::Array{Uint8} |
|
nc::Int |
|
lc::Int |
|
bc::Int |
|
ip::Int |
|
cp::Int |
|
c::Char |
|
hd::Bool |
|
err::Bool |
|
pars::Array{Int} |
|
function SixelFile() |
|
new(zeros(Uint8,0), 0, 0, 0, 0, 1, '\0', false, false, zeros(Int,7)) |
|
end |
|
end |
|
|
|
function readSixels(sf::SixelFile, filnam::String) |
|
f = open(filnam,"r") |
|
sf.s = read(f,Uint8,filesize(filnam)); |
|
sf.nc = length(sf.s) |
|
close(f) |
|
end |
|
|
|
function sixel(sf::SixelFile) |
|
while true |
|
sf.ip += 1 |
|
if sf.ip>sf.nc; sf.err=true; return; end |
|
sf.c = sf.s[sf.ip] |
|
if sf.c=='\e' || sf.c>' '; break; end |
|
end |
|
end |
|
|
|
function number(sf::SixelFile) |
|
k = 0 |
|
while true |
|
sixel(sf) |
|
if sf.err; return -1; end |
|
if sf.c<'0' || sf.c>'9'; return k; end |
|
k = k*10 + (int(sf.c)-int('0')); |
|
end |
|
end |
|
|
|
function header(sf::SixelFile) |
|
if sf.c=='\e' |
|
sixel(sf) |
|
if sf.c!='P'; return; end |
|
end |
|
ip = 0 |
|
while true |
|
n = number(sf) |
|
if sf.err; return; end |
|
if sf.c=='q'; break; end |
|
ip += 1 |
|
sf.pars[ip] = n |
|
end |
|
sixel(sf) |
|
if sf.err; return; end |
|
if sf.c=='"' |
|
ip = 3 |
|
while true |
|
n = number(sf) |
|
if n<0; break; end |
|
ip += 1 |
|
sf.pars[ip] = n |
|
if sf.c!=';'; break; end |
|
end |
|
end |
|
sf.hd = true |
|
end |
|
|
|
function color(sf::SixelFile) |
|
k = number(sf) |
|
k = rem(k,16) |
|
sf.cp = k+1 |
|
if sf.c!=';'; return; end |
|
d = number(sf) |
|
if sf.c!=';'; return; end |
|
r = number(sf) |
|
if sf.c!=';'; return; end |
|
g = number(sf) |
|
if sf.c!=';'; return; end |
|
b = number(sf) |
|
end |
|
|
|
function color(sf::SixelFile, p::Array) |
|
k = number(sf) |
|
k = rem(k,16) |
|
sf.cp = k+1 |
|
if sf.c!=';'; return; end |
|
d = number(sf) |
|
if sf.c!=';'; return; end |
|
r = number(sf) |
|
if sf.c!=';'; return; end |
|
g = number(sf) |
|
if sf.c!=';'; return; end |
|
b = number(sf) |
|
if d==1 |
|
p[sf.cp] = convert(RGB, HSL((r+240)%360, b/100, g/100)) |
|
elseif d==2 |
|
p[sf.cp] = RGB(r/100,g/100,b/100) |
|
end |
|
end |
|
|
|
function getcolor(cp, p::Array{RGB,1}) |
|
[iround(p[cp].r*255), iround(p[cp].g*255), iround(p[cp].b*255)] |
|
end |
|
|
|
function clear(sf::SixelFile, img::Image, col::Array) |
|
for j=1:size(img.data,3), i=1:size(img.data,2) |
|
img[:,i,j] = col |
|
end |
|
end |
|
|
|
# get dimensions and colors |
|
function pass1(sf::SixelFile, p::Array{RGB,1}) |
|
sf.lc = 0 |
|
sf.bc = 0 |
|
sf.ip = 0 |
|
sf.hd = false |
|
sf.err = false |
|
bc = 0 |
|
sixel(sf) |
|
while !sf.err |
|
c = sf.c |
|
if c=='\e' || c=='\u90' || c=='\u9c' |
|
if sf.hd; break; end |
|
header(sf) |
|
c = sf.c |
|
end |
|
if !sf.hd; sixel(sf); continue; end |
|
if c=='$' |
|
if bc>sf.bc; sf.bc=bc; end |
|
bc = 0 |
|
sixel(sf) |
|
elseif c=='-' |
|
if bc>sf.bc; sf.bc=bc; end |
|
sf.lc += 1 |
|
bc = 0 |
|
sixel(sf) |
|
elseif c=='#' |
|
color(sf,p) |
|
elseif c=='!' |
|
k = number(sf) |
|
bc += k |
|
sixel(sf) |
|
else |
|
bc += 1 |
|
sixel(sf) |
|
end |
|
end |
|
end |
|
|
|
function putsixel(sf::SixelFile, img::Image, col::Array, lc::Int, bc::Int, k::Int) |
|
msk::Uint8 |
|
ic::Uint8 |
|
msk = 0x01 |
|
ic = int(sf.c)-63 |
|
xs = size(img.data,2) |
|
ys = size(img.data,3) |
|
for j=1:6 |
|
if ic&msk>0 |
|
for i=1:k |
|
x = bc+i |
|
y = lc*6+j |
|
if x<=xs && y<=ys; img[:,x,y] = col; end |
|
end |
|
end |
|
msk <<= 1 |
|
end |
|
end |
|
|
|
# put the sixels in the image |
|
function pass2(sf::SixelFile, img::Image, p::Array) |
|
bc::Int |
|
lc::Int |
|
bc = 0 |
|
lc = 0 |
|
sf.ip = 0 |
|
sf.hd = false |
|
sf.err = false |
|
col = getcolor(1,p) |
|
sixel(sf) |
|
while !sf.err |
|
c = sf.c |
|
if c=='\e' || c=='\u90' || c=='\u9c' |
|
if sf.hd; break; end |
|
header(sf) |
|
c = sf.c |
|
end |
|
if !sf.hd; sixel(sf); continue; end |
|
if c=='$' |
|
bc = 0 |
|
sixel(sf) |
|
elseif c=='-' |
|
lc += 1 |
|
bc = 0 |
|
sixel(sf) |
|
elseif c=='#' |
|
color(sf) |
|
col = getcolor(sf.cp, p) |
|
elseif c=='!' |
|
k = number(sf) |
|
putsixel(sf, img, col, lc, bc, k) |
|
bc += k |
|
sixel(sf) |
|
else |
|
putsixel(sf, img, col, lc, bc, 1) |
|
bc += 1 |
|
sixel(sf) |
|
end |
|
end |
|
end |
|
|
|
function ds(filnam::String, bg::Int=0) |
|
sf = SixelFile() |
|
readSixels(sf, filnam) |
|
p = vt340_palette() |
|
pass1(sf,p) |
|
if sf.err; return sf; end |
|
|
|
if sf.pars[6]>0; xs = sf.pars[6]; else; xs = sf.bc; end |
|
if sf.pars[7]>0; ys = sf.pars[7]; else; ys = sf.lc*6; end |
|
|
|
img = Image(Array(Uint8,3,xs,ys), |
|
["limits"=>(0x00,0xff), |
|
"colordim"=>1, |
|
"spatialorder"=>["x","y"], |
|
"colorspace"=>"RGB"]) |
|
|
|
if bg==0 |
|
clear(sf, img, getcolor(1,p)) |
|
elseif bg==1 |
|
clear(sf, img, [0, 0, 0]) |
|
elseif bg==2 |
|
clear(sf, img, [0xff, 0xff, 0xff]) |
|
end |
|
|
|
pass2(sf, img, p) |
|
display(img) |
|
img |
|
end |
|
|
|
# img = ds("") |
|
# imwrite(img,"") |