bunkerweb 1.4.0
This commit is contained in:
BIN
deps/src/lua-gd/demos/Vera.ttf
vendored
Normal file
BIN
deps/src/lua-gd/demos/Vera.ttf
vendored
Normal file
Binary file not shown.
20
deps/src/lua-gd/demos/brush.lua
vendored
Executable file
20
deps/src/lua-gd/demos/brush.lua
vendored
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local im = gd.createTrueColor(400, 400)
|
||||
assert(im)
|
||||
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
|
||||
local brush = gd.createFromPng("paper.png")
|
||||
im:setBrush(brush)
|
||||
im:line(60, 60, 70, 70, gd.BRUSHED)
|
||||
im:line(120, 120, 130, 130, gd.BRUSHED)
|
||||
im:line(180, 180, 190, 190, gd.BRUSHED)
|
||||
im:line(240, 240, 250, 250, gd.BRUSHED)
|
||||
im:line(300, 300, 310, 310, gd.BRUSHED)
|
||||
|
||||
im:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
BIN
deps/src/lua-gd/demos/bugs.jpg
vendored
Normal file
BIN
deps/src/lua-gd/demos/bugs.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
14
deps/src/lua-gd/demos/circle.lua
vendored
Executable file
14
deps/src/lua-gd/demos/circle.lua
vendored
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local im = gd.createTrueColor(100, 100)
|
||||
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
local blue = im:colorAllocate(0, 0, 255)
|
||||
|
||||
im:filledRectangle(0, 0, 100, 100, white)
|
||||
im:stringFTCircle(50, 50, 40, 10, 0.9, "./Vera.ttf", 24, "Powered", "by Lua", blue)
|
||||
|
||||
im:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
68
deps/src/lua-gd/demos/clock.lua
vendored
Executable file
68
deps/src/lua-gd/demos/clock.lua
vendored
Executable file
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
-- a cgi script that draws an analog clock with lua and lua-gd
|
||||
-- (c) 2004 Alexandre Erwin Ittner
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local function createClock(size, hours, minutes)
|
||||
local im = gd.createTrueColor(size, size)
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
local gray = im:colorAllocate(128, 128, 128)
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
local blue = im:colorAllocate(0, 0, 128)
|
||||
local cxy = size/2
|
||||
|
||||
im:filledRectangle(0, 0, size, size, white)
|
||||
im:setThickness(math.max(1, size/100))
|
||||
im:arc(cxy, cxy, size, size, 0, 360, black)
|
||||
|
||||
local ang = 0
|
||||
local rang, gsize
|
||||
while ang < 360 do
|
||||
rang = math.rad(ang)
|
||||
if (ang % 90) == 0 then
|
||||
gsize = 0.75
|
||||
else
|
||||
gsize = 0.85
|
||||
end
|
||||
im:line(
|
||||
cxy + gsize * cxy * math.sin(rang),
|
||||
size - (cxy + gsize * cxy * math.cos(rang)),
|
||||
cxy + cxy * 0.9 * math.sin(rang),
|
||||
size - (cxy + cxy * 0.9 * math.cos(rang)),
|
||||
gray)
|
||||
ang = ang + 30
|
||||
end
|
||||
|
||||
im:setThickness(math.max(1, size/50))
|
||||
im:line(cxy, cxy,
|
||||
cxy + 0.45 * size * math.sin(math.rad(6*minutes)),
|
||||
size - (cxy + 0.45 * size * math.cos(math.rad(6*minutes))),
|
||||
blue)
|
||||
|
||||
im:setThickness(math.max(1, size/25))
|
||||
rang = math.rad(30*hours + minutes/2)
|
||||
im:line(cxy, cxy,
|
||||
cxy + 0.25 * size * math.sin(rang),
|
||||
size - (cxy + 0.25 * size * math.cos(rang)),
|
||||
blue)
|
||||
|
||||
im:setThickness(1)
|
||||
local sp = math.max(1, size/20)
|
||||
im:filledArc(cxy, cxy, sp, sp, 0, 360, black, gd.ARC)
|
||||
|
||||
return im
|
||||
end
|
||||
|
||||
local dh = os.date("*t")
|
||||
local im = createClock(100, dh.hour, dh.min)
|
||||
|
||||
print("Content-type: image/png")
|
||||
print("Refresh: 60") -- Ask browser to reload the image after 60s
|
||||
print("Pragma: no-cache") -- Can mozilla understand this?
|
||||
print("Expires: Thu Jan 01 00:00:00 UTC 1970") -- Marks as expired
|
||||
print("")
|
||||
|
||||
io.write(im:pngStr())
|
||||
|
||||
16
deps/src/lua-gd/demos/colortransparent.lua
vendored
Executable file
16
deps/src/lua-gd/demos/colortransparent.lua
vendored
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local im = gd.createPalette(90, 90)
|
||||
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
local blue = im:colorAllocate(0, 0, 255)
|
||||
local red = im:colorAllocate(255, 0, 0)
|
||||
|
||||
im:colorTransparent(white)
|
||||
im:filledRectangle(10, 10, 50, 50, blue)
|
||||
im:filledRectangle(40, 40, 80, 80, red)
|
||||
|
||||
im:gif("out.gif")
|
||||
os.execute("xdg-open out.gif")
|
||||
30
deps/src/lua-gd/demos/counter.lua
vendored
Executable file
30
deps/src/lua-gd/demos/counter.lua
vendored
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env lua
|
||||
-- counter.lua -- a web counter in Lua!
|
||||
-- (c) 2004 Alexandre Erwin Ittner
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local datafile = "counter.txt"
|
||||
local fp = io.open(datafile, "r+")
|
||||
local cnt = 0
|
||||
if fp then
|
||||
cnt = tonumber(fp:read("*l")) or 0
|
||||
fp:seek("set", 0)
|
||||
else
|
||||
fp = io.open(datafile, "w")
|
||||
assert(fp)
|
||||
end
|
||||
cnt = cnt + 1
|
||||
fp:write(cnt .."\n")
|
||||
fp:close()
|
||||
|
||||
local sx = math.max(string.len(tostring(cnt)), 1) * 8
|
||||
local im = gd.create(sx, 15)
|
||||
-- first allocated color defines the background.
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
im:colorTransparent(white)
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
im:string(gd.FONT_MEDIUM, 1, 1, cnt, black)
|
||||
|
||||
print("Content-type: image/png\n")
|
||||
io.write(im:pngStr())
|
||||
12
deps/src/lua-gd/demos/ellipse.lua
vendored
Executable file
12
deps/src/lua-gd/demos/ellipse.lua
vendored
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
local im = gd.createTrueColor(80, 80)
|
||||
assert(im)
|
||||
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
im:filledEllipse(40, 40, 70, 50, white)
|
||||
|
||||
im:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
23
deps/src/lua-gd/demos/fontconfig.lua
vendored
Executable file
23
deps/src/lua-gd/demos/fontconfig.lua
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
-- The fonts used in this example comes with Microsoft operating systems
|
||||
-- and can be downloaded from http://corefonts.sourceforge.net
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local im = gd.createTrueColor(220, 190)
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
local x, y = im:sizeXY()
|
||||
im:filledRectangle(0, 0, x, y, white)
|
||||
|
||||
gd.useFontConfig(true)
|
||||
im:stringFT(black, "Arial", 20, 0, 10, 30, "Standard Arial")
|
||||
im:stringFT(black, "Arial:bold", 20, 0, 10, 60, "Bold Arial")
|
||||
im:stringFT(black, "Arial:italic", 20, 0, 10, 90, "Italic Arial")
|
||||
im:stringFT(black, "Arial:bold:italic", 20, 0, 10, 120, "Italic Bold Arial")
|
||||
im:stringFT(black, "Times New Roman", 20, 0, 10, 150, "Times New Roman")
|
||||
im:stringFT(black, "Comic Sans MS", 20, 0, 10, 180, "Comic Sans MS")
|
||||
|
||||
im:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
31
deps/src/lua-gd/demos/fractal.lua
vendored
Executable file
31
deps/src/lua-gd/demos/fractal.lua
vendored
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
-- Draws the famous Sierpinski triangle with lua-gd
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local size = 500
|
||||
|
||||
local im = gd.createPalette(size, size)
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
|
||||
local m = {}
|
||||
m[math.floor(size/2)] = true
|
||||
|
||||
local n
|
||||
for i = 1, size do
|
||||
n = {}
|
||||
for j = 1, size do
|
||||
if m[j] then
|
||||
im:setPixel(j, i, black)
|
||||
n[j+1] = not n[j+1]
|
||||
n[j-1] = not n[j-1]
|
||||
end
|
||||
end
|
||||
m = n
|
||||
end
|
||||
|
||||
im:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
|
||||
52
deps/src/lua-gd/demos/gd-open-any.lua
vendored
Normal file
52
deps/src/lua-gd/demos/gd-open-any.lua
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
--
|
||||
-- Open images automatically according to the file magic number.
|
||||
-- Part of Lua-GD
|
||||
--
|
||||
|
||||
|
||||
local gd = require("gd")
|
||||
local io = require("io")
|
||||
|
||||
local magics = {
|
||||
{ "\137PNG", gd.createFromPng },
|
||||
{ "GIF87a", gd.createFromGif },
|
||||
{ "GIF89a", gd.createFromGif },
|
||||
{ "\255\216\255\224\0\16\74\70\73\70\0", gd.createFromJpeg },
|
||||
{ "\255\216\255\225\19\133\69\120\105\102\0", gd.createFromJpeg }, -- JPEG Exif
|
||||
}
|
||||
|
||||
--
|
||||
-- Open some common image types according to the file headers
|
||||
--
|
||||
-- Arguments:
|
||||
-- fname: a string with the file name
|
||||
--
|
||||
-- Return values:
|
||||
-- on success, returns a GD image handler.
|
||||
-- on error, returns nil followed by a string with the error description.
|
||||
--
|
||||
|
||||
local function openany(fname)
|
||||
local fp = io.open(fname, "rb")
|
||||
if not fp then
|
||||
return nil, "Error opening file"
|
||||
end
|
||||
|
||||
local header = fp:read(16)
|
||||
if not header then
|
||||
return nil, "Error reading file"
|
||||
end
|
||||
fp:close()
|
||||
|
||||
for _, v in ipairs(magics) do
|
||||
if header:sub(1, #v[1]) == v[1] then
|
||||
return v[2](fname)
|
||||
end
|
||||
end
|
||||
|
||||
return nil, "Image type not recognized"
|
||||
end
|
||||
|
||||
|
||||
return { openany = openany }
|
||||
|
||||
21
deps/src/lua-gd/demos/gifanim.lua
vendored
Executable file
21
deps/src/lua-gd/demos/gifanim.lua
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local im = gd.createPalette(80, 80)
|
||||
assert(im)
|
||||
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
im:gifAnimBegin("out.gif", true, 0)
|
||||
|
||||
for i = 1, 10 do
|
||||
tim = gd.createPalette(80, 80)
|
||||
tim:paletteCopy(im)
|
||||
tim:arc(40, 40, 40, 40, 36*(i-1), 36*i, white)
|
||||
tim:gifAnimAdd("out.gif", false, 0, 0, 5, gd.DISPOSAL_NONE)
|
||||
end
|
||||
|
||||
gd.gifAnimEnd("out.gif")
|
||||
os.execute("xdg-open out.gif")
|
||||
|
||||
24
deps/src/lua-gd/demos/gifanim2.lua
vendored
Executable file
24
deps/src/lua-gd/demos/gifanim2.lua
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local im = gd.createPalette(120, 120)
|
||||
assert(im)
|
||||
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
local blue = {}
|
||||
for i = 1, 20 do
|
||||
blue[i] = im:colorAllocate(0, 0, 120+6*i)
|
||||
end
|
||||
|
||||
im:gifAnimBegin("out.gif", true, 0)
|
||||
for i = 1, 20 do
|
||||
tim = gd.createPalette(120, 120)
|
||||
tim:paletteCopy(im)
|
||||
tim:arc(60, 60, 6*i, 6*i, 0, 360, blue[21-i])
|
||||
tim:gifAnimAdd("out.gif", false, 0, 0, 5, gd.DISPOSAL_NONE)
|
||||
end
|
||||
|
||||
gd.gifAnimEnd("out.gif")
|
||||
os.execute("xdg-open out.gif")
|
||||
|
||||
29
deps/src/lua-gd/demos/gifanim3.lua
vendored
Executable file
29
deps/src/lua-gd/demos/gifanim3.lua
vendored
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local im = gd.createPalette(120, 120)
|
||||
assert(im)
|
||||
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
local blue = {}
|
||||
for i = 1, 20 do
|
||||
blue[i] = im:colorAllocate(0, 0, 120+6*i)
|
||||
end
|
||||
|
||||
local fp = io.open("out.gif", "w")
|
||||
assert(fp, "Failed to open file for writting")
|
||||
|
||||
fp:write(im:gifAnimBeginStr(true, 0))
|
||||
|
||||
for i = 1, 20 do
|
||||
tim = gd.createPalette(120, 120)
|
||||
tim:paletteCopy(im)
|
||||
tim:arc(60, 60, 6*i, 6*i, 0, 360, blue[21-i])
|
||||
fp:write(tim:gifAnimAddStr(false, 0, 0, 5, gd.DISPOSAL_NONE))
|
||||
end
|
||||
|
||||
fp:write(gd.gifAnimEndStr())
|
||||
fp:close()
|
||||
|
||||
os.execute("xdg-open out.gif")
|
||||
BIN
deps/src/lua-gd/demos/lua-gd.png
vendored
Normal file
BIN
deps/src/lua-gd/demos/lua-gd.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
60
deps/src/lua-gd/demos/lualogo.lua
vendored
Executable file
60
deps/src/lua-gd/demos/lualogo.lua
vendored
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
--
|
||||
-- lualogo.lua (c) 2006-11 Alexandre Erwin Ittner <alexandre@ittner.com.br>
|
||||
--
|
||||
-- Drawns the Lua Logo. This script requires fontconfig and the "Helvetica"
|
||||
-- font installed in your system.
|
||||
--
|
||||
--
|
||||
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
gd.useFontConfig(true)
|
||||
|
||||
function makelogo(size)
|
||||
local nsize = 3 * size
|
||||
local im = gd.createTrueColor(nsize, nsize)
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
local blue = im:colorAllocate(0, 0, 128)
|
||||
local gray = im:colorAllocate(170, 170, 170)
|
||||
|
||||
local ediam = nsize * 0.68 -- Earth diameter
|
||||
local mdiam = ediam * (1 - math.sqrt(2) / 2) -- Moon diameter
|
||||
local odiam = ediam * 1.3 -- Orbit diameter
|
||||
local emdist = odiam/2 * 1.05 -- Earth - Moon distance
|
||||
local esdist = odiam/2 * 0.4 -- Earth - Moon shadow distance
|
||||
local mang = 45 -- Moon angle (degrees)
|
||||
local mangr = math.rad(mang)
|
||||
local cxy = nsize/2.0
|
||||
|
||||
im:fill(0, 0, white)
|
||||
im:filledArc(cxy, cxy, ediam, ediam, 0, 360, blue, gd.ARC)
|
||||
|
||||
im:setThickness(math.max(0.02 * ediam, 1))
|
||||
for i = 0, 360, 10 do
|
||||
im:arc(cxy, cxy, odiam, odiam, i, i+5, gray)
|
||||
end
|
||||
im:setThickness(1)
|
||||
|
||||
-- Moon
|
||||
local mcx = cxy + math.sin(math.rad(mang)) * emdist
|
||||
local mcy = cxy - math.cos(math.rad(mang)) * emdist
|
||||
im:filledArc(mcx, mcy, mdiam, mdiam, 0, 360, blue, gd.ARC)
|
||||
|
||||
-- Moon shadow
|
||||
local mscx = cxy + math.sin(math.rad(mang)) * esdist
|
||||
local mscy = cxy - math.cos(math.rad(mang)) * esdist
|
||||
im:filledArc(mscx, mscy, mdiam, mdiam, 0, 360, white, gd.ARC)
|
||||
|
||||
im:stringFT(white, "Helvetica", 0.23*nsize, 0, 0.25*nsize, 0.7*nsize, "Lua")
|
||||
|
||||
-- Implementation of the "Desperate anti-aliasing algorithm" ;)
|
||||
local im2 = gd.createTrueColor(size, size)
|
||||
im2:copyResampled(im, 0, 0, 0, 0, size, size, nsize, nsize)
|
||||
return im2
|
||||
end
|
||||
|
||||
makelogo(140):png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
BIN
deps/src/lua-gd/demos/paper.png
vendored
Normal file
BIN
deps/src/lua-gd/demos/paper.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
16
deps/src/lua-gd/demos/poly.lua
vendored
Executable file
16
deps/src/lua-gd/demos/poly.lua
vendored
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local im = gd.createTrueColor(80, 80)
|
||||
assert(im)
|
||||
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
|
||||
im:polygon( { { 10, 10 }, { 10, 20 }, { 20, 20 }, { 20, 10 } }, white)
|
||||
im:filledPolygon( { { 30, 30 }, { 30, 40 }, { 40, 40 }, { 40, 30 } }, white)
|
||||
im:openPolygon( { { 50, 50 }, { 50, 60 }, { 60, 60 }, { 60, 50 } }, white)
|
||||
|
||||
im:png("out.png")
|
||||
print(os.execute("xdg-open out.png"))
|
||||
36
deps/src/lua-gd/demos/setstyle.lua
vendored
Executable file
36
deps/src/lua-gd/demos/setstyle.lua
vendored
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local im = gd.createPalette(150, 100)
|
||||
assert(im, "Failed to create new image.")
|
||||
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
local red = im:colorAllocate(200, 0, 0)
|
||||
local green = im:colorAllocate(0, 128, 0)
|
||||
local blue = im:colorAllocate(0, 0, 128)
|
||||
|
||||
local style = {}
|
||||
|
||||
for i = 0, 10 do
|
||||
style[#style+1] = red
|
||||
end
|
||||
|
||||
for i = 0, 5 do
|
||||
style[#style+1] = blue
|
||||
end
|
||||
|
||||
for i = 0, 2 do
|
||||
style[#style+1] = green
|
||||
end
|
||||
|
||||
im:setStyle(style)
|
||||
|
||||
for i = 0, 100, 2 do
|
||||
im:line(i, i, i+50, i, gd.STYLED)
|
||||
end
|
||||
|
||||
im:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
|
||||
|
||||
22
deps/src/lua-gd/demos/stdfont.lua
vendored
Executable file
22
deps/src/lua-gd/demos/stdfont.lua
vendored
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local x, y = 140, 110
|
||||
|
||||
local im = gd.createPalette(x, y)
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
|
||||
im:string(gd.FONT_TINY, 10, 10, "gd.FONT_TINY", black)
|
||||
im:string(gd.FONT_SMALL, 10, 20, "gd.FONT_SMALL", black)
|
||||
im:string(gd.FONT_MEDIUM, 10, 35, "gd.FONT_MEDIUM", black)
|
||||
im:string(gd.FONT_LARGE, 10, 48, "gd.FONT_LARGE", black)
|
||||
im:string(gd.FONT_GIANT, 10, 65, "gd.FONT_GIANT", black)
|
||||
|
||||
im:line(60, 93, 70, 93, black)
|
||||
im:string(gd.FONT_SMALL, 80, 86, "= 10 px", black)
|
||||
|
||||
im:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
|
||||
361
deps/src/lua-gd/demos/steg.lua
vendored
Executable file
361
deps/src/lua-gd/demos/steg.lua
vendored
Executable file
@@ -0,0 +1,361 @@
|
||||
#!/usr/bin/env lua
|
||||
--[[
|
||||
|
||||
Steganography with Lua-GD
|
||||
|
||||
Steganography is the technique of writing hidden messages in such a way
|
||||
that no one apart from the intended recipient knows of the existence of
|
||||
the message; this is in contrast to cryptography, where the existence
|
||||
of the message is clear, but the meaning is obscured. Generally a
|
||||
steganographic message will appear to be something else, like a shopping
|
||||
list, an article, a picture, or some other "cover" message. In the
|
||||
digital age, steganography works by replacing bits of useless or unused
|
||||
data in regular computer files (such as graphics, sound, text, HTML, or
|
||||
even floppy disks) with bits of different, invisible information. This
|
||||
hidden information can be plain text, cipher text or even images.
|
||||
|
||||
|
||||
A Simple Example
|
||||
|
||||
If Alice wants to send a secret message to Bob through an insecure
|
||||
channel, she can use some encryption software (like GnuPG) to encrypt
|
||||
the message with Bob's public key. It's a good solution because no
|
||||
one unless Bob will be able to read the message. She can also sign the
|
||||
message so Bob will know that the message really comes from her. BUT,
|
||||
a potential attacker will know that a ciphered message was sent. If the
|
||||
attacker has control over the communication channel, he might block the
|
||||
message in some way that Bob will never receive it. If Alice also HIDES
|
||||
the ciphertext in an unsuspected piece of information (like a photo of her
|
||||
cat) the attacker will not detect it and the message will arrive to Bob.
|
||||
|
||||
This program will help Alice to hide some arbitrary text in a PNG image by
|
||||
replacing the least significant bits of each color channel of some pixels
|
||||
with bits from the encrypted message. PNG or other loseless compression
|
||||
algorithm are mandatory here, since compressing the image with a lossy
|
||||
algorithm will destroy the stored information. The maximum length of the
|
||||
message is limited by the image's size (each byte needs 8 color channels or
|
||||
2 pixels and 2 channels from the next pixel). So, the image must have at
|
||||
least "ceil((length+1)*8/3)" pixels (the extra byte is the NUL marker for
|
||||
the end of the string). So, if Alice's message is "Meet me in the secret
|
||||
place at nine o'clock.", she will encrypt and sign it to something like
|
||||
"PyJYDpz5LCOSHPiXDvLHmVzxLV8qS7EFvZnoo1Mxk+BlT+7lMjpQKs" (imagine Alice's
|
||||
cat walking in you keyboard :). This is the ciphertext that will be sent
|
||||
to Bob through the image.
|
||||
|
||||
The following table shows what happens to the first eight pixels from
|
||||
the image when mixed to the first three bytes from the encrypted message:
|
||||
|
||||
|
||||
+-----+---+----------+-----------------+----------+
|
||||
| Pix | C | Orig img | Message | New img |
|
||||
| # | | bits | Chr | Dec | Bin | bits |
|
||||
+-----+---+----------+-----+-----+-----+----------+
|
||||
| | R | 01010010 | | | 0 | 01010010 |
|
||||
| 1 | G | 00101010 | | | 1 | 00101011 |
|
||||
|_____| B | 00010101 | | | 0 | 00010100 |
|
||||
| | R | 11100100 | P | 080 | 1 | 11100101 |
|
||||
| 2 | G | 00100100 | | | 0 | 00100100 |
|
||||
|_____| B | 01001111 | | | 0 | 01001110 |
|
||||
| | R | 01010010 | | | 0 | 01010010 |
|
||||
| 3 | G | 00101110 |_____|_____|__0__| 00101110 |
|
||||
|_____| B | 00111001 | | | 0 | 00111000 |
|
||||
| | R | 10010110 | | | 1 | 10010111 |
|
||||
| 4 | G | 01011101 | | | 1 | 01011101 |
|
||||
|_____| B | 00100101 | y | 121 | 1 | 00100101 |
|
||||
| | R | 01001001 | | | 1 | 01001001 |
|
||||
| 5 | G | 10110110 | | | 0 | 10110110 |
|
||||
|_____| B | 00010101 | | | 0 | 00010100 |
|
||||
| | R | 00110100 |_____|_____|__1__| 00110101 |
|
||||
| 6 | G | 01000111 | | | 0 | 01000110 |
|
||||
|_____| B | 01001000 | | | 1 | 01001001 |
|
||||
| | R | 01010110 | | | 0 | 01010110 |
|
||||
| 7 | G | 00011001 | | | 0 | 00011000 |
|
||||
|_____| B | 10010100 | J | 074 | 1 | 10010101 |
|
||||
| | R | 00010101 | | | 0 | 00010100 |
|
||||
| 8 | G | 01011010 | | | 1 | 01011011 |
|
||||
| | B | 01010001 | | | 0 | 01010000 |
|
||||
+-----+---+----------+-----+-----+-----+----------+
|
||||
|
||||
|
||||
When Bob wants to read the message he will extract the least significant
|
||||
bit (LSB) from each color channel from some pixels of the image and
|
||||
join them to get the original ciphertext. A NULL character (ASCII #0)
|
||||
will mark the end of the message within the image, so he will know when
|
||||
to stop. Of course, this program will also do this boring job for Bob.
|
||||
|
||||
|
||||
]]
|
||||
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
|
||||
local function getLSB(n)
|
||||
return (n % 2) ~= 0
|
||||
end
|
||||
|
||||
|
||||
-- Bizarre way to do some bit-level operations without bitlib.
|
||||
local function setLSB(n, b)
|
||||
if type(b) == "number" then
|
||||
if b == 0 then
|
||||
b = false
|
||||
else
|
||||
b = true
|
||||
end
|
||||
end
|
||||
if getLSB(n) then
|
||||
if b then
|
||||
return n
|
||||
elseif n > 0 then
|
||||
return n - 1
|
||||
else
|
||||
return n + 1
|
||||
end
|
||||
else
|
||||
if not b then
|
||||
return n
|
||||
elseif n > 0 then
|
||||
return n - 1
|
||||
else
|
||||
return n + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function intToBitArray(n)
|
||||
local ret = {}
|
||||
local i = 0
|
||||
while n ~= 0 do
|
||||
ret[i] = getLSB(n)
|
||||
n = math.floor(n/2)
|
||||
ret.size = i
|
||||
i = i + 1
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
local function printBitArray(a)
|
||||
local i
|
||||
for i = a.size,0,-1 do
|
||||
if a[i] then
|
||||
io.write("1")
|
||||
else
|
||||
io.write("0")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function mergeMessage(im, msg)
|
||||
local w, h = im:sizeXY()
|
||||
msg = msg .. string.char(0)
|
||||
local len = string.len(msg)
|
||||
if h * w < len * 8 then
|
||||
return nil
|
||||
end
|
||||
local x, y = 0, 0
|
||||
local oim = gd.createTrueColor(w, h)
|
||||
local i = 1
|
||||
local a2, c, nc, chr
|
||||
local a = {}
|
||||
local s, e = 1, 1
|
||||
local rgb = {}
|
||||
|
||||
while y < h do
|
||||
c = im:getPixel(x, y)
|
||||
rgb.r = im:red(c)
|
||||
rgb.g = im:green(c)
|
||||
rgb.b = im:blue(c)
|
||||
if i <= len and e - s < 3 then
|
||||
a2 = intToBitArray(string.byte(string.sub(msg, i, i)))
|
||||
for cnt = 7,0,-1 do
|
||||
a[e+7-cnt] = a2[cnt]
|
||||
end
|
||||
i = i + 1
|
||||
e = e + 8
|
||||
end
|
||||
if e - s > 0 then
|
||||
rgb.r = setLSB(rgb.r, a[s])
|
||||
a[s] = nil
|
||||
s = s + 1
|
||||
end
|
||||
if e - s > 0 then
|
||||
rgb.g = setLSB(rgb.g, a[s])
|
||||
a[s] = nil
|
||||
s = s + 1
|
||||
end
|
||||
if e - s > 0 then
|
||||
rgb.b = setLSB(rgb.b, a[s])
|
||||
a[s] = nil
|
||||
s = s + 1
|
||||
end
|
||||
nc = oim:colorResolve(rgb.r, rgb.g, rgb.b)
|
||||
oim:setPixel(x, y, nc)
|
||||
x = x + 1
|
||||
if x == w then
|
||||
x = 0
|
||||
y = y + 1
|
||||
end
|
||||
end
|
||||
return oim, len*8, w*h
|
||||
end
|
||||
|
||||
|
||||
local function getMessage(im)
|
||||
local msg = {}
|
||||
local w, h = im:sizeXY()
|
||||
local x, y = 0, 0
|
||||
local a = {}
|
||||
local s, e = 1, 1
|
||||
local b = 0
|
||||
local c
|
||||
while y <= h do
|
||||
c = im:getPixel(x, y)
|
||||
a[e] = getLSB(im:red(c))
|
||||
a[e+1] = getLSB(im:green(c))
|
||||
a[e+2] = getLSB(im:blue(c))
|
||||
e = e + 2
|
||||
if e - s >= 7 then
|
||||
b = 0
|
||||
for p = s, s+7 do
|
||||
b = b * 2
|
||||
if a[p] then
|
||||
b = b + 1
|
||||
end
|
||||
a[p] = nil
|
||||
end
|
||||
s = s + 8
|
||||
if b == 0 then
|
||||
return table.concat(msg)
|
||||
else
|
||||
msg[#msg+1] = string.char(b)
|
||||
end
|
||||
end
|
||||
e = e + 1
|
||||
x = x + 1
|
||||
if x == w then
|
||||
x = 0
|
||||
y = y + 1
|
||||
end
|
||||
end
|
||||
return table.concat(msg)
|
||||
end
|
||||
|
||||
|
||||
local function compare(fimg1, fimg2)
|
||||
local im1 = gd.createFromPng(fimg1)
|
||||
if not im1 then
|
||||
print("ERROR: " .. fimg1 .. " bad PNG data.")
|
||||
os.exit(1)
|
||||
end
|
||||
local im2 = gd.createFromPng(fimg2)
|
||||
if not im2 then
|
||||
print("ERROR: " .. fimg2 .. " bad PNG data.")
|
||||
os.exit(1)
|
||||
end
|
||||
local w1, h1 = im1:sizeXY()
|
||||
local w2, h2 = im2:sizeXY()
|
||||
if w1 ~= w2 or h1 ~= h2 then
|
||||
print("ERROR: Images have different sizes.")
|
||||
os.exit(1)
|
||||
end
|
||||
local oim = gd.createTrueColor(w1, h1)
|
||||
local x, y = 0, 0
|
||||
local c1, c2, oc, f, fc
|
||||
while y < h1 do
|
||||
c1 = im1:getPixel(x, y)
|
||||
c2 = im2:getPixel(x, y)
|
||||
if im1:red(c1) ~= im2:red(c2)
|
||||
or im1:green(c1) ~= im2:green(c2)
|
||||
or im1:blue(c1) ~= im2:blue(c2) then
|
||||
oc = oim:colorResolve(im2:red(c2), im2:green(c2), im2:blue(c2))
|
||||
oim:setPixel(x, y, oc)
|
||||
else
|
||||
f = math.floor((im1:red(c1) + im1:green(c1) + im1:blue(c1))/6.0)
|
||||
fc = oim:colorResolve(f, f, f)
|
||||
oim:setPixel(x, y, fc)
|
||||
end
|
||||
x = x + 1
|
||||
if x == w1 then
|
||||
x = 0
|
||||
y = y + 1
|
||||
end
|
||||
end
|
||||
return oim
|
||||
end
|
||||
|
||||
|
||||
local function usage()
|
||||
print("Usage:")
|
||||
print(" lua steg.lua hide <input file> <output file>")
|
||||
print(" lua steg.lua show <input file>")
|
||||
print(" lua steg.lua diff <input file 1> <input file 2> <output file>")
|
||||
print("")
|
||||
print(" hide - Reads a message from stdin and saves into <output file>.")
|
||||
print(" show - Reads a message from <input file> and prints it to stdout.")
|
||||
print(" diff - Compares two images and writes the diff to <output file>.")
|
||||
print("")
|
||||
print(" WARNING: All files used here must be in the PNG format!")
|
||||
end
|
||||
|
||||
|
||||
if not arg[1] or not arg[2] then
|
||||
usage()
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
if arg[1] == "show" then
|
||||
local im = gd.createFromPng(arg[2])
|
||||
if not im then
|
||||
print("ERROR: Bad image data.")
|
||||
os.exit(1)
|
||||
end
|
||||
io.write(getMessage(im))
|
||||
os.exit(0)
|
||||
end
|
||||
|
||||
if arg[1] == "hide" then
|
||||
if not arg[3] then
|
||||
usage()
|
||||
os.exit(1)
|
||||
end
|
||||
local im = gd.createFromPng(arg[2])
|
||||
if not im then
|
||||
print("ERROR: Bad image data.")
|
||||
os.exit(1)
|
||||
end
|
||||
print("Type your message and press CTRL+D to finish.")
|
||||
local msg = io.read("*a")
|
||||
local oim, l, t = mergeMessage(im, msg)
|
||||
if not oim then
|
||||
print("ERROR: Image is too small for the message.")
|
||||
os.exit(1)
|
||||
end
|
||||
if not oim:png(arg[3]) then
|
||||
print("ERROR: Failed to write output file.")
|
||||
os.exit(1)
|
||||
end
|
||||
print(string.format("DONE: %2.1f%% of the image used to store the message.",
|
||||
100.0*l/t))
|
||||
os.exit(0)
|
||||
end
|
||||
|
||||
if arg[1] == "diff" then
|
||||
if not arg[3] and arg[4] then
|
||||
usage()
|
||||
os.exit(1)
|
||||
end
|
||||
local oim = compare(arg[2], arg[3])
|
||||
if not oim:png(arg[4]) then
|
||||
print("ERROR: Failed to write output file.")
|
||||
os.exit(1)
|
||||
end
|
||||
os.exit(0)
|
||||
end
|
||||
|
||||
usage()
|
||||
os.exit(1)
|
||||
|
||||
35
deps/src/lua-gd/demos/test.lua
vendored
Executable file
35
deps/src/lua-gd/demos/test.lua
vendored
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
math.randomseed(os.time())
|
||||
|
||||
local im = gd.createFromJpeg("./bugs.jpg")
|
||||
assert(im)
|
||||
local sx, sy = im:sizeXY()
|
||||
|
||||
local im2 = gd.createTrueColor(2*sx, sy)
|
||||
local black = im2:colorAllocate(0, 0, 0)
|
||||
local white = im2:colorAllocate(255, 255, 255)
|
||||
gd.copy(im2, im, 0, 0, 0, 0, sx, sy, sx, sy)
|
||||
|
||||
local sx2, sy2 = im2:sizeXY()
|
||||
im2:stringUp(gd.FONT_SMALL, 5, sy2-10, gd.VERSION, white)
|
||||
|
||||
for i = 0, 14 do
|
||||
for j = 0, 24 do
|
||||
local rcl = im2:colorAllocate(math.random(255), math.random(255),
|
||||
math.random(255))
|
||||
im2:filledRectangle(sx+20+j*10, i*20+40, sx+30+j*10, i*20+50, rcl)
|
||||
end
|
||||
end
|
||||
|
||||
im2:string(gd.FONT_GIANT, sx+80, 10, "Powered by Lua", white)
|
||||
|
||||
local blackTr = im2:colorAllocateAlpha(0, 0, 0, 80)
|
||||
im2:stringFT(blackTr, "./Vera.ttf", 140, 0, 70, 130, "gd")
|
||||
im2:stringFT(white, "./Vera.ttf", 45, math.pi/5, 340, 250, "FreeType")
|
||||
|
||||
|
||||
im2:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
19
deps/src/lua-gd/demos/test2.lua
vendored
Executable file
19
deps/src/lua-gd/demos/test2.lua
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local im = gd.createFromJpeg("./bugs.jpg")
|
||||
assert(im)
|
||||
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
im:string(gd.FONT_MEDIUM, 10, 10, "Powered by", white)
|
||||
|
||||
local imlua = gd.createFromPng("./lua-gd.png")
|
||||
-- imlua:colorTransparent(imlua:getPixel(0, 0))
|
||||
|
||||
local sx, sy = imlua:sizeXY()
|
||||
gd.copy(im, imlua, 10, 25, 0, 0, sx, sy, sx, sy)
|
||||
im:string(gd.FONT_MEDIUM, 10, 330, "http://ittner.github.com/lua-gd/", white)
|
||||
|
||||
im:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
30
deps/src/lua-gd/demos/ttftext.lua
vendored
Executable file
30
deps/src/lua-gd/demos/ttftext.lua
vendored
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local function boxedtext(im, color, font, size, ang, x, y, text, bcolor)
|
||||
local font = "./" .. font .. ".ttf"
|
||||
local llx, lly, lrx, lry, urx, ury, ulx, uly =
|
||||
im:stringFT(color, font, size, math.rad(ang), x, y, text)
|
||||
im:polygon({ {llx, lly}, {lrx, lry}, {urx, ury}, {ulx, uly} }, bcolor)
|
||||
end
|
||||
|
||||
local im = gd.createTrueColor(400, 400)
|
||||
assert(im)
|
||||
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
local grayt = im:colorAllocateAlpha(255, 255, 255, 70)
|
||||
local bluet = im:colorAllocateAlpha(0, 0, 250, 70)
|
||||
local redt = im:colorAllocateAlpha(255, 0, 0, 0)
|
||||
local greent = im:colorAllocateAlpha(0, 250, 0, 70)
|
||||
local lbluet = im:colorAllocateAlpha(180, 180, 255, 70)
|
||||
local yellowt = im:colorAllocateAlpha(240, 240, 0, 70)
|
||||
|
||||
boxedtext(im, yellowt, "Vera", 300, 0, 60, 350, "A", bluet)
|
||||
boxedtext(im, greent, "Vera", 80, 45, 60, 220, "Ithil", bluet)
|
||||
boxedtext(im, redt, "Vera", 45, 90, 380, 300, "Lua-GD", bluet)
|
||||
boxedtext(im, lbluet, "Vera", 36, 290, 160, 130, "FreeType", bluet)
|
||||
boxedtext(im, grayt, "Vera", 26, 180, 390, 360, "Turn 180<38> before read", bluet)
|
||||
|
||||
im:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
49
deps/src/lua-gd/demos/ttftextex.lua
vendored
Executable file
49
deps/src/lua-gd/demos/ttftextex.lua
vendored
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
gd.useFontConfig(true) -- Use Fontconfig by default.
|
||||
|
||||
local im = gd.createTrueColor(400, 400)
|
||||
assert(im)
|
||||
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
local grayt = im:colorAllocateAlpha(255, 255, 255, 80)
|
||||
local blue = im:colorAllocate(0, 0, 250)
|
||||
local red = im:colorAllocate(255, 0, 0)
|
||||
local green = im:colorAllocate(0, 250, 0)
|
||||
local lblue = im:colorAllocate(180, 180, 255)
|
||||
local yellow = im:colorAllocate(240, 240, 0)
|
||||
|
||||
im:stringFTEx(lblue, "Vera", 20, 0, 40, 40, "Half\nspace",
|
||||
{ linespacing = 0.5 } )
|
||||
|
||||
im:stringFTEx(red, "Vera", 20, 0, 140, 40, "Single\nspace",
|
||||
{ linespacing = 1.0 } )
|
||||
|
||||
im:stringFTEx(green, "Vera", 20, 0, 240, 40, "Double\nspace",
|
||||
{ linespacing = 2.0 } )
|
||||
|
||||
im:stringFTEx(yellow, "Vera", 40, 0, 80, 140, "Distorted!",
|
||||
{ hdpi = 96, vdpi = 30 } )
|
||||
|
||||
|
||||
local k = "Kerniiiiiiiiiiiiiiiiiing?"
|
||||
print(im:stringFTEx(red, "Vera", 30, 0, 10, 200, k, {}))
|
||||
print(im:stringFTEx(red, "Vera", 30, 0, 10, 240, k,
|
||||
{ disable_kerning = true } ))
|
||||
|
||||
for i = 10, 400, 10 do
|
||||
im:line(i, 170, i, 250, grayt)
|
||||
end
|
||||
|
||||
|
||||
local llX, llY, lrX, lrY, urX, urY, ulX, ulY, fontpath =
|
||||
im:stringFTEx(lblue, "Vera", 20, 0, 50, 320, "This font comes from",
|
||||
{ return_font_path_name = true } )
|
||||
|
||||
im:string(gd.FONT_MEDIUM, 10, 340, fontpath, lblue)
|
||||
|
||||
|
||||
im:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
35
deps/src/lua-gd/demos/utf-8.lua
vendored
Executable file
35
deps/src/lua-gd/demos/utf-8.lua
vendored
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env lua
|
||||
-- -*- coding: utf-8 -*-
|
||||
|
||||
-- UTF-8 encoded unicode text. You must use an UTF-8 compatible text editor
|
||||
-- to change this and a compatible Unicode font (FreeSerif is a good one).
|
||||
--
|
||||
-- WARNING: Windows Notepad will add some prefixes, making this file an
|
||||
-- invalid Lua script.
|
||||
|
||||
local gd = require("gd")
|
||||
|
||||
local text = [[
|
||||
⌠ ☾ Lua-GD
|
||||
⌡ Unicode/UTF-8
|
||||
↺↻⇒✇☢☣☠
|
||||
♜♞♝♛♚♝♞♜
|
||||
♟♟♟♟♟♟♟♟
|
||||
♙♙♙♙♙♙♙♙
|
||||
♖♘♗♕♔♗♘♖
|
||||
]]
|
||||
|
||||
local fontname = "FreeSerif" -- Common on Unix systems
|
||||
-- local fontname = "Arial Unicode" -- Common on Windows systems
|
||||
|
||||
gd.useFontConfig(true)
|
||||
|
||||
local im = gd.createTrueColor(180, 180)
|
||||
local white = im:colorAllocate(255, 255, 255)
|
||||
local black = im:colorAllocate(0, 0, 0)
|
||||
local x, y = im:sizeXY()
|
||||
im:filledRectangle(0, 0, x, y, white)
|
||||
im:stringFT(black, fontname, 16, 0, 10, 30, text)
|
||||
|
||||
im:png("out.png")
|
||||
os.execute("xdg-open out.png")
|
||||
Reference in New Issue
Block a user