bmp mode working
This commit is contained in:
parent
3282417d7f
commit
8a918daa7b
190
init.lua
190
init.lua
@ -1,8 +1,8 @@
|
||||
PROCESSOR = "tiff8" -- options are: "py", "gm", "magick", "imlib2", "pngLua"
|
||||
PROCESSOR = "native" -- options are: "native", "py", "gm", "magick", "imlib2"
|
||||
--imlib2 treats 16-bit as 8-bit and requires imlib2, magick requires magick wand -- magick is the most tested mode
|
||||
--gm does not work and requires graphicksmagick, py is bit slow and requires lunatic-python to be built, and the PIL,
|
||||
--imlib2 treats 16-bit as 8-bit and requires imlib2, magick requires magick wand
|
||||
--convert uses commandline imagemagick "convert" or graphicsmagick "gm convert" ("convert.exe" or "gm.exe convert")
|
||||
--png locks up and does not work... tiff8 is for uncompressed grayscale 8-bit tiffs only
|
||||
--native handles png, tiff, and bmp files but none currently only bmp works and only on 24 bit images with good headers
|
||||
MODPATH = minetest.get_modpath("realterrain")
|
||||
WORLDPATH = minetest.get_worldpath()
|
||||
RASTERS = MODPATH .. "/rasters/"
|
||||
@ -17,7 +17,7 @@ local imagesize = ie.require "imagesize"
|
||||
|
||||
--[[package.path = (MODPATH.."/lib/luasocket/?.lua;"..MODPATH.."/lib/luasocket/?/init.lua;"..package.path)
|
||||
local socket = ie.require "socket"--]]
|
||||
local py, gm, magick, imlib2, convert, png
|
||||
local native, py, gm, magick, imlib2, convert
|
||||
if PROCESSOR == "py" then
|
||||
package.loadlib("/usr/lib/x86_64-linux-gnu/libpython2.7.so", "*") --may not need to explicitly state this
|
||||
package.path = (MODPATH.."/lib/lunatic-python-bugfix-1.1.1/?.lua;"..package.path)
|
||||
@ -37,12 +37,9 @@ elseif PROCESSOR == "gm" then
|
||||
gm = ie.require "graphicsmagick"
|
||||
elseif PROCESSOR == "convert" then
|
||||
convert = "convert" -- could also be convert.exe, "gm convert" or "gm.exe convert"
|
||||
elseif PROCESSOR == "png" then
|
||||
package.path = (MODPATH.."/lib/pngLua/?.lua;"..MODPATH.."/lib/pngLua/?/init.lua;"..package.path)
|
||||
ie.require "png"
|
||||
png = true
|
||||
elseif PROCESSOR == "tiff8" then
|
||||
tiff8 = true
|
||||
elseif PROCESSOR == "native" then
|
||||
dofile(MODPATH.."/lib/iohelpers.lua")
|
||||
dofile(MODPATH.."/lib/imageloader.lua")
|
||||
end
|
||||
local realterrain = {}
|
||||
realterrain.settings = {}
|
||||
@ -57,9 +54,9 @@ realterrain.settings.zoffset = 0
|
||||
realterrain.settings.waterlevel = 0
|
||||
realterrain.settings.alpinelevel = 1000
|
||||
|
||||
realterrain.settings.fileelev = 'demo/dem.tif'
|
||||
realterrain.settings.fileelev = 'demo/dem.bmp'
|
||||
realterrain.settings.elevbits = 8 --@todo remove this setting when magick autodetects bitdepth
|
||||
realterrain.settings.filecover = 'demo/biomes.tif'
|
||||
realterrain.settings.filecover = 'demo/biomes.bmp'
|
||||
realterrain.settings.coverbits = 8 --@todo remove this setting when magick autodetects bitdepth
|
||||
|
||||
realterrain.settings.fileinput = ''
|
||||
@ -562,9 +559,9 @@ realterrain.input3 = {}
|
||||
function realterrain.init()
|
||||
local mode = realterrain.get_mode()
|
||||
local imageload
|
||||
if gm then imageload = gm.Image
|
||||
elseif magick then imageload = magick.load_image
|
||||
elseif imlib2 then imageload = imlib2.image.load
|
||||
if PROCESSOR == "gm" then imageload = gm.Image
|
||||
elseif PROCESSOR == "magick" then imageload = magick.load_image
|
||||
elseif PROCESSOR == "imlib2" then imageload = imlib2.image.load
|
||||
end
|
||||
local rasternames = {}
|
||||
table.insert(rasternames, "elev")
|
||||
@ -575,45 +572,38 @@ function realterrain.init()
|
||||
for k,rastername in next, rasternames do
|
||||
|
||||
if realterrain.settings["file"..rastername] ~= "" then
|
||||
if tiff8 then
|
||||
if PROCESSOR == "native" then
|
||||
--use imagesize to get the dimensions and header offset
|
||||
local width, length, format = imagesize.imgsize(RASTERS..realterrain.settings["file"..rastername])
|
||||
|
||||
if format == "image/tiff" then
|
||||
print(rastername..": format: "..format)
|
||||
if string.sub(format, -3) == "bmp" or string.sub(format, -6) == "bitmap" then
|
||||
dofile(MODPATH.."/lib/loader_bmp.lua")
|
||||
local bitmap, e = imageloader.load(RASTERS..realterrain.settings["file"..rastername])
|
||||
if e then print(e) end
|
||||
realterrain[rastername].image = bitmap
|
||||
realterrain[rastername].width = width
|
||||
realterrain[rastername].length = length
|
||||
realterrain[rastername].bits = tonumber(realterrain.settings[rastername.."bits"])
|
||||
realterrain[rastername].format = "bmp"
|
||||
elseif format == "image/png" then
|
||||
dofile(MODPATH.."/lib/loader_png.lua")
|
||||
local bitmap, e = imageloader.load(RASTERS..realterrain.settings["file"..rastername])
|
||||
if e then print(e) end
|
||||
realterrain[rastername].image = bitmap
|
||||
realterrain[rastername].width = realterrain[rastername].image.width
|
||||
realterrain[rastername].length = realterrain[rastername].image.height
|
||||
realterrain[rastername].format = "png"
|
||||
elseif format == "image/tiff" then
|
||||
local file = io.open(RASTERS..realterrain.settings["file"..rastername], "rb")
|
||||
realterrain[rastername].image = file
|
||||
realterrain[rastername].width = width
|
||||
realterrain[rastername].length = length
|
||||
realterrain[rastername].bits = tonumber(realterrain.settings[rastername.."bits"])
|
||||
realterrain[rastername].format = "tiff"
|
||||
else
|
||||
print("tiff8 processor requires an uncompressed 8-bit grayscale tiff file")
|
||||
return
|
||||
print("your file should be an uncompressed tiff, png or bmp")
|
||||
end
|
||||
elseif png then
|
||||
--@todo use imagesize to determine format
|
||||
local function get_png(filename)
|
||||
local ok, r = pcall(pngImage, filename)
|
||||
if not ok then return nil, r end -- NOTE: r == error message
|
||||
return r
|
||||
end
|
||||
|
||||
local img, e = get_png(RASTERS..realterrain.settings["file"..rastername]) --@todo locks up, no error!
|
||||
if not img then
|
||||
print(e)
|
||||
return nil, e
|
||||
end
|
||||
--@todocheck if the image is a png and if so load it
|
||||
realterrain[rastername].image = img
|
||||
img = nil
|
||||
if realterrain[rastername].image then
|
||||
realterrain[rastername].width = realterrain[rastername].image.width
|
||||
realterrain[rastername].length = realterrain[rastername].image.height
|
||||
else
|
||||
print("your "..rastername.." file is missing or is not a PNG (should be: "..realterrain.settings["file"..rastername].."), maybe delete or edit world/realterrain_settings")
|
||||
realterrain[rastername] = {}
|
||||
end
|
||||
|
||||
elseif py then
|
||||
elseif PROCESSOR == "py" then
|
||||
py.execute(rastername.." = Image.open('"..RASTERS..realterrain.settings["file"..rastername] .."')")
|
||||
py.execute(rastername.."_w, "..rastername.."_l = "..rastername..".size")
|
||||
realterrain[rastername].width = tonumber(tostring(py.eval(rastername.."_w")))
|
||||
@ -631,12 +621,12 @@ function realterrain.init()
|
||||
else
|
||||
realterrain[rastername].image = imageload(RASTERS..realterrain.settings["file"..rastername])
|
||||
if realterrain[rastername].image then
|
||||
if gm then
|
||||
if PROCESSOR == "gm" then
|
||||
realterrain[rastername].width, realterrain[rastername].length = realterrain[rastername].image:size()
|
||||
else--imagick or imlib2
|
||||
realterrain[rastername].width = realterrain[rastername].image:get_width()
|
||||
realterrain[rastername].length = realterrain[rastername].image:get_height()
|
||||
if magick then
|
||||
if PROCESSOR == "magick" then
|
||||
realterrain[rastername].bits = realterrain.settings[rastername.."bits"]
|
||||
end
|
||||
end
|
||||
@ -692,6 +682,7 @@ function realterrain.generate(minp, maxp)
|
||||
local x1 = maxp.x
|
||||
local y1 = maxp.y
|
||||
local z1 = maxp.z
|
||||
|
||||
local x0 = minp.x
|
||||
local y0 = minp.y
|
||||
local z0 = minp.z
|
||||
@ -1133,52 +1124,63 @@ end
|
||||
--the raw get pixel method that uses the selected method and accounts for bit depth
|
||||
function realterrain.get_raw_pixel(x,z, rastername) -- "rastername" is a string
|
||||
local r,g,b
|
||||
local width, length
|
||||
width = realterrain[rastername].width
|
||||
length = realterrain[rastername].length
|
||||
--check to see if the image is even on the raster, otherwise skip
|
||||
if ( x >= 0 and x < realterrain[rastername].width )
|
||||
and ( z >= 0 and z < realterrain[rastername].length ) then
|
||||
if ( x >= 0 and x < width ) and ( z >= 0 and z < length ) then
|
||||
--print(rastername..": x "..x..", z "..z)
|
||||
if tiff8 then
|
||||
local file = realterrain[rastername].image
|
||||
if not file then
|
||||
print("tiff8 problem retrieving file handle")
|
||||
end
|
||||
--print(file)
|
||||
local width, length
|
||||
width = realterrain[rastername].width
|
||||
length = realterrain[rastername].length
|
||||
|
||||
|
||||
if realterrain[rastername].bits == 8 then
|
||||
file:seek("set", ((z) * width) + x)
|
||||
r = file:read(1)
|
||||
if r then
|
||||
r = r:byte() -- -32?
|
||||
|
||||
r = tonumber(r)
|
||||
--print(r)
|
||||
else
|
||||
print(rastername..": nil value encountered at x: "..x..", z: "..z)
|
||||
r = nil
|
||||
if PROCESSOR == "native" then
|
||||
if realterrain[rastername].format == "bmp" then
|
||||
local bitmap = realterrain[rastername].image
|
||||
local c
|
||||
if bitmap.pixels[z] and bitmap.pixels[z][x] then
|
||||
c = bitmap.pixels[z][x]
|
||||
r = c.r
|
||||
g = c.g
|
||||
b = c.b
|
||||
end
|
||||
else
|
||||
file:seek("set", ((z) * width * 2) + (x*2)+1)
|
||||
local r1 = file:read(1)
|
||||
local r2 = file:read(1)
|
||||
if r1 and r2 then
|
||||
r = tonumber(r1:byte()) + tonumber(r2:byte())
|
||||
--print(r)
|
||||
elseif realterrain[rastername].format == "png" then
|
||||
local bitmap = realterrain[rastername].image
|
||||
local c
|
||||
if bitmap.pixels[z] and bitmap.pixels[z][x] then
|
||||
c = bitmap.pixels[z][x]
|
||||
r = c.r
|
||||
g = c.g
|
||||
b = c.b
|
||||
end
|
||||
elseif realterrain[rastername].format == "tiff" then
|
||||
local file = realterrain[rastername].image
|
||||
if not file then
|
||||
print("tiff mode problem retrieving file handle")
|
||||
end
|
||||
--print(file)
|
||||
|
||||
if realterrain[rastername].bits == 8 then
|
||||
file:seek("set", ((z) * width) + x)
|
||||
r = file:read(1)
|
||||
if r then
|
||||
r = r:byte() -- -32?
|
||||
|
||||
r = tonumber(r)
|
||||
--print(r)
|
||||
else
|
||||
print(rastername..": nil value encountered at x: "..x..", z: "..z)
|
||||
r = nil
|
||||
end
|
||||
else
|
||||
print(rastername..": one of two bytes is nil")
|
||||
file:seek("set", ((z) * width * 2) + (x*2)+1)
|
||||
local r1 = file:read(1)
|
||||
local r2 = file:read(1)
|
||||
if r1 and r2 then
|
||||
r = tonumber(r1:byte()) + tonumber(r2:byte())
|
||||
--print(r)
|
||||
else
|
||||
print(rastername..": one of two bytes is nil")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
elseif png then
|
||||
local pixel = img.scanLines[y].pixels[x]
|
||||
r=pixel.R
|
||||
g=pixel.G
|
||||
b=pixel.B
|
||||
elseif py then
|
||||
elseif PROCESSOR == "py" then
|
||||
if realterrain[rastername].mode == "RGB" then
|
||||
py.execute(rastername.."_r, "..rastername.."_g,"..rastername.."_b = "..rastername.."_pixels["..x..", "..z.."]")
|
||||
r = tonumber(tostring(py.eval(rastername.."_r")))
|
||||
@ -1190,12 +1192,12 @@ function realterrain.get_raw_pixel(x,z, rastername) -- "rastername" is a string
|
||||
--print(r)
|
||||
else
|
||||
if realterrain[rastername].image then
|
||||
if magick then
|
||||
if PROCESSOR == "magick" then
|
||||
r,g,b = realterrain[rastername].image:get_pixel(x, z) --@todo change when magick autodetects bit depth
|
||||
r = math.floor(r * (2^realterrain[rastername].bits))
|
||||
g = math.floor(g * (2^realterrain[rastername].bits))
|
||||
b = math.floor(b * (2^realterrain[rastername].bits))
|
||||
elseif imlib2 then
|
||||
elseif PROCESSOR == "imlib2" then
|
||||
r = realterrain[rastername].image:get_pixel(x, z).red
|
||||
g = realterrain[rastername].image:get_pixel(x, z).green
|
||||
b = realterrain[rastername].image:get_pixel(x, z).blue
|
||||
@ -1270,9 +1272,9 @@ end
|
||||
function realterrain.get_enumeration(rastername, xstart, width, zstart, length) --raster is a string so py can use it
|
||||
local enumeration
|
||||
|
||||
if gm then
|
||||
if PROCESSOR == "gm" then
|
||||
enumeration = realterrain[rastername].image:clone():crop(width,length,xstart,zstart):format("txt"):toString()
|
||||
elseif magick then
|
||||
elseif PROCESSOR == "magick" then
|
||||
local tmpimg
|
||||
tmpimg = realterrain[rastername].image:clone()
|
||||
tmpimg:crop(width,length,xstart,zstart)
|
||||
@ -1304,7 +1306,7 @@ function realterrain.build_heightmap(xstart, xend, zstart, zend, get_cover, get_
|
||||
if mode.get_input3 then table.insert(rasternames, "input3") end
|
||||
for k,rastername in next, rasternames do
|
||||
|
||||
if py then
|
||||
if PROCESSOR == "py" then
|
||||
--py.execute(rastername.."_pixels = "..rastername..".load()")
|
||||
for z = zstart, zend, 1 do
|
||||
if not pixels[z] then pixels[z] = {} end
|
||||
@ -1323,7 +1325,7 @@ function realterrain.build_heightmap(xstart, xend, zstart, zend, get_cover, get_
|
||||
end
|
||||
end
|
||||
local enumeration
|
||||
if gm or magick then
|
||||
if PROCESSOR == "gm" or PROCESSOR == "magick" then
|
||||
enumeration = realterrain.get_enumeration(rastername, xstart, width, zstart, length)
|
||||
--print("entire enumeration: "..enumeration)
|
||||
local entries = 0
|
||||
@ -1331,7 +1333,7 @@ function realterrain.build_heightmap(xstart, xend, zstart, zend, get_cover, get_
|
||||
local mincol, maxcol, minrow, maxrow
|
||||
local firstline = true
|
||||
for k,line in next, string.split(enumeration, "\n") do
|
||||
if magick and firstline then
|
||||
if PROCESSOR == "magick" and firstline then
|
||||
firstline = false --first line is a head in IM but not GM
|
||||
else
|
||||
entries = entries + 1
|
||||
|
96
lib/imageloader.lua
Normal file
96
lib/imageloader.lua
Normal file
@ -0,0 +1,96 @@
|
||||
|
||||
imageloader = { }
|
||||
|
||||
local types = { }
|
||||
|
||||
local bmp_meta = {
|
||||
__index = bmp_methods,
|
||||
}
|
||||
|
||||
--[[
|
||||
typedef = {
|
||||
description = "FOO File",
|
||||
check = func(filename), --> bool
|
||||
load = func(filename), --> table or (nil, errormsg)
|
||||
}
|
||||
]]
|
||||
|
||||
function imageloader.register_type(def)
|
||||
types[#types + 1] = def
|
||||
end
|
||||
|
||||
local function find_loader(filename)
|
||||
for _,def in ipairs(types) do
|
||||
local r = def.check(filename)
|
||||
if r then
|
||||
return def
|
||||
end
|
||||
end
|
||||
return nil, "imageloader: unknown file type"
|
||||
end
|
||||
|
||||
function imageloader.load(filename)
|
||||
local def, e = find_loader(filename)
|
||||
if not def then return nil, e end
|
||||
if e then print(e) end
|
||||
local r, e = def.load(filename)
|
||||
if r then
|
||||
r = setmetatable(r, bmp_meta)
|
||||
end
|
||||
return r, e
|
||||
end
|
||||
|
||||
function imageloader.type(filename)
|
||||
local def, e = find_loader(filename)
|
||||
if not def then return nil, e end
|
||||
return def.description
|
||||
end
|
||||
--[[
|
||||
function imageloader.to_schematic(bmp, pal)
|
||||
local data = { }
|
||||
local datai = 1
|
||||
for z = 1, bmp.h do
|
||||
for x = 1, bmp.w do
|
||||
local c = bmp.pixels[z][bmp.w + 1 - x]
|
||||
local i = palette.bestfit_color(pal, c)
|
||||
if (i == 1) and ((c.r ~= 255) or (c.g ~= 0) or (c.r ~= 255)) then
|
||||
print("WARNING: wrong color taken as transparency:"
|
||||
..(("at (%d,%d): [R=%d,G=%d,B=%d]"):format(x, z, c.r, c.g, c.b))
|
||||
)
|
||||
end
|
||||
local node = pal[i].node
|
||||
data[datai] = { name=node }
|
||||
datai = datai + 1
|
||||
end
|
||||
end
|
||||
return {
|
||||
size = { x=bmp.w, y=1, z=bmp.h },
|
||||
data = data,
|
||||
}
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("loadimage", {
|
||||
description = "Load an image file into the world at current position",
|
||||
params = "<filename>",
|
||||
func = function(name, param)
|
||||
param = param:trim()
|
||||
if param == "" then
|
||||
minetest.chat_send_player(name, "[imageloader] Usage: /loadimage <filename>")
|
||||
return
|
||||
end
|
||||
minetest.chat_send_player(name, "[imageloader] Loading image...")
|
||||
local bmp, e = imageloader.load(minetest.get_modpath("imageloader").."/images/"..param)
|
||||
if not bmp then
|
||||
minetest.chat_send_player(name, "[imageloader] Failed to load image: "..(e or "unknown error"))
|
||||
return
|
||||
end
|
||||
print(("Image loaded: size: %dx%d"):format(bmp.w, bmp.h))
|
||||
minetest.chat_send_player(name, "[imageloader] Creating schematic...")
|
||||
local schem = imageloader.to_schematic(bmp, palette.wool_palette)
|
||||
print(("Schematic created: size: %dx%dx%d"):format(schem.size.x, schem.size.y, schem.size.z))
|
||||
minetest.chat_send_player(name, "[imageloader] Placing schematic...")
|
||||
local pos = minetest.get_player_by_name(name):getpos()
|
||||
minetest.place_schematic(pos, schem, 0)
|
||||
minetest.chat_send_player(name, "[imageloader] DONE!")
|
||||
end,
|
||||
})--]]
|
49
lib/iohelpers.lua
Normal file
49
lib/iohelpers.lua
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
ioh = { }
|
||||
|
||||
local function read_bytes(f, c, d)
|
||||
|
||||
local s = (d < 0) and c or 1
|
||||
local e = (d < 0) and 1 or c
|
||||
|
||||
local buf = f:read(c)
|
||||
if (not buf) or (buf:len() ~= c) then return nil end
|
||||
|
||||
local r = 0
|
||||
|
||||
for x = s, e, d do
|
||||
r = r * 256
|
||||
r = r + buf:byte(x)
|
||||
end
|
||||
|
||||
return r
|
||||
|
||||
end
|
||||
|
||||
local function write_bytes(f, n, c, d)
|
||||
|
||||
local s = (d < 0) and c or 1
|
||||
local e = (d < 0) and 1 or c
|
||||
|
||||
local buf = ""
|
||||
|
||||
for x = s, e, d do
|
||||
local ch = (n % 256)
|
||||
buf = buf..string.char(ch)
|
||||
n = (n - ch) / 256
|
||||
end
|
||||
|
||||
f:write(buf)
|
||||
|
||||
end
|
||||
|
||||
|
||||
function ioh.read_int16_le(f) return read_bytes(f, 2, -1) end
|
||||
function ioh.read_int32_le(f) return read_bytes(f, 4, -1) end
|
||||
function ioh.read_int16_be(f) return read_bytes(f, 2, 1) end
|
||||
function ioh.read_int32_be(f) return read_bytes(f, 4, 1) end
|
||||
|
||||
function ioh.write_int16_le(f, n) write_bytes(f, n, 2, -1) end
|
||||
function ioh.write_int32_le(f, n) write_bytes(f, n, 4, -1) end
|
||||
function ioh.write_int16_be(f, n) write_bytes(f, n, 2, 1) end
|
||||
function ioh.write_int32_be(f, n) write_bytes(f, n, 4, 1) end
|
251
lib/loader_bmp.lua
Normal file
251
lib/loader_bmp.lua
Normal file
@ -0,0 +1,251 @@
|
||||
|
||||
-- Original file is part of Allegro 4.4.
|
||||
-- BMP loader by Seymour Shlien.
|
||||
-- OS/2 BMP support and BMP save function by Jonas Petersen.
|
||||
-- Translated to Lua by Diego Martínez <lkaezadl3@gmail.com>
|
||||
|
||||
local BI_RGB = 0
|
||||
|
||||
local OS2INFOHEADERSIZE = 12
|
||||
local WININFOHEADERSIZE = 40
|
||||
|
||||
local figetw = ioh.read_int16_le
|
||||
local figetl = ioh.read_int32_le
|
||||
local function fgetc(f) return (f:read(1) or " "):byte() end
|
||||
|
||||
--[[ read_bmfileheader:
|
||||
| Reads a BMP file header and check that it has the BMP magic number.
|
||||
]]
|
||||
local function read_bmfileheader(f, fileheader)
|
||||
|
||||
fileheader.bfType = figetw(f)
|
||||
fileheader.bfSize = figetl(f)
|
||||
fileheader.bfReserved1 = figetw(f)
|
||||
fileheader.bfReserved2 = figetw(f)
|
||||
fileheader.bfOffBits = figetl(f)
|
||||
|
||||
if fileheader.bfType ~= 19778 then return false end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[ read_win_bminfoheader:
|
||||
| Reads information from a BMP file header.
|
||||
]]
|
||||
local function read_win_bminfoheader(f, infoheader)
|
||||
|
||||
local win_infoheader
|
||||
|
||||
local win_infoheader = { }
|
||||
win_infoheader.biWidth = figetl(f)
|
||||
win_infoheader.biHeight = figetl(f)
|
||||
win_infoheader.biPlanes = figetw(f)
|
||||
win_infoheader.biBitCount = figetw(f)
|
||||
win_infoheader.biCompression = figetl(f)
|
||||
win_infoheader.biSizeImage = figetl(f)
|
||||
win_infoheader.biXPelsPerMeter = figetl(f)
|
||||
win_infoheader.biYPelsPerMeter = figetl(f)
|
||||
win_infoheader.biClrUsed = figetl(f)
|
||||
win_infoheader.biClrImportant = figetl(f)
|
||||
|
||||
infoheader.biWidth = win_infoheader.biWidth
|
||||
infoheader.biHeight = win_infoheader.biHeight
|
||||
infoheader.biBitCount = win_infoheader.biBitCount
|
||||
infoheader.biCompression = win_infoheader.biCompression
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[ read_os2_bminfoheader:
|
||||
| Reads information from an OS/2 format BMP file header.
|
||||
]]
|
||||
local function read_os2_bminfoheader(f, infoheader)
|
||||
|
||||
local os2_infoheader = { }
|
||||
|
||||
os2_infoheader.biWidth = figetw(f)
|
||||
os2_infoheader.biHeight = figetw(f)
|
||||
os2_infoheader.biPlanes = figetw(f)
|
||||
os2_infoheader.biBitCount = figetw(f)
|
||||
|
||||
infoheader.biWidth = os2_infoheader.biWidth
|
||||
infoheader.biHeight = os2_infoheader.biHeight
|
||||
infoheader.biBitCount = os2_infoheader.biBitCount
|
||||
infoheader.biCompression = 0
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[ read_24bit_line:
|
||||
| Support function for reading the 24 bit bitmap file format, doing
|
||||
| our best to convert it down to a 256 color palette.
|
||||
]]
|
||||
local function read_24bit_line(length, f, line)
|
||||
|
||||
local ii = 0
|
||||
|
||||
for i = 1, length do
|
||||
local c = { }
|
||||
c.b = fgetc(f)
|
||||
c.g = fgetc(f)
|
||||
c.r = fgetc(f)
|
||||
c.a = 255
|
||||
line[i] = c
|
||||
ii = ii + 1
|
||||
end
|
||||
|
||||
-- padding
|
||||
ii = (ii * 3) % 4
|
||||
if ii ~= 0 then
|
||||
while ii < 4 do
|
||||
fgetc(f)
|
||||
ii = ii + 1
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[ read_32bit_line:
|
||||
| Support function for reading the 32 bit bitmap file format, doing
|
||||
| our best to convert it down to a 256 color palette.
|
||||
]]
|
||||
local function read_32bit_line(length, f, line)
|
||||
|
||||
for i = 1, length do
|
||||
local c = { }
|
||||
c.b = fgetc(f)
|
||||
c.g = fgetc(f)
|
||||
c.r = fgetc(f)
|
||||
c.a = fgetc(f)
|
||||
line[i] = c
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[ read_image:
|
||||
| For reading the noncompressed BMP image format.
|
||||
]]
|
||||
local function read_image(f, bmp, infoheader)
|
||||
|
||||
local i, line, height, dir
|
||||
|
||||
height = infoheader.biHeight
|
||||
line = (height < 0) and 1 or height
|
||||
dir = (height < 0) and 1 or -1
|
||||
height = math.abs(height)
|
||||
|
||||
print(("[imageloader.bmp] size=%dx%d bpp=%d"):format(
|
||||
infoheader.biWidth,
|
||||
infoheader.biHeight,
|
||||
infoheader.biBitCount
|
||||
))
|
||||
|
||||
bmp.pixels = { }
|
||||
|
||||
for i = 1, height do
|
||||
local row = { }
|
||||
bmp.pixels[line] = row
|
||||
if infoheader.biBitCount == 24 then
|
||||
read_24bit_line(infoheader.biWidth, f, row)
|
||||
elseif infoheader.biBitCount == 32 then
|
||||
read_32bit_line(infoheader.biWidth, f, row)
|
||||
else
|
||||
return false
|
||||
end
|
||||
line = line + dir
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
local function get_bmp_infoheader(f)
|
||||
|
||||
local fileheader = { }
|
||||
local infoheader = { }
|
||||
local bmp, biSize
|
||||
local bpp, dest_depth
|
||||
|
||||
if not read_bmfileheader(f, fileheader) then
|
||||
return nil, "loader_bmp: failed to read file header"
|
||||
end
|
||||
|
||||
biSize = figetl(f)
|
||||
|
||||
if biSize == WININFOHEADERSIZE then
|
||||
if not read_win_bminfoheader(f, infoheader) then
|
||||
return nil, "loader_bmp: failed to read info header"
|
||||
end
|
||||
elseif biSize == OS2INFOHEADERSIZE then
|
||||
if not read_os2_bminfoheader(f, infoheader) then
|
||||
return nil, "loader_bmp: failed to read info header"
|
||||
end
|
||||
else
|
||||
return nil, "loader_bmp: unsupported file format"
|
||||
end
|
||||
|
||||
if --[[(infoheader.biBitCount == 8) or (infoheader.biBitCount == 16)
|
||||
or --]](infoheader.biBitCount == 24) or (infoheader.biBitCount == 32) then
|
||||
bpp = infoheader.biBitCount
|
||||
else
|
||||
return nil, "loader_bmp: unsupported color depth "..infoheader.biBitCount
|
||||
end
|
||||
|
||||
if infoheader.biCompression ~= BI_RGB then
|
||||
return nil, "loader_bmp: unsupported compression scheme: "..infoheader.biCompression
|
||||
end
|
||||
|
||||
return infoheader
|
||||
|
||||
end
|
||||
|
||||
--[[ load_bmp_pf:
|
||||
| Like load_bmp, but starts loading from the current place in the PACKFILE
|
||||
| specified. If successful the offset into the file will be left just after
|
||||
| the image data. If unsuccessful the offset into the file is unspecified,
|
||||
| i.e. you must either reset the offset to some known place or close the
|
||||
| packfile. The packfile is not closed by this function.
|
||||
]]
|
||||
local function load_bmp_pf(f)
|
||||
|
||||
local infoheader, e = get_bmp_infoheader(f)
|
||||
|
||||
if not infoheader then return nil, e end
|
||||
|
||||
local bmp = {
|
||||
bpp = bpp,
|
||||
w = infoheader.biWidth,
|
||||
h = math.abs(infoheader.biHeight),
|
||||
}
|
||||
|
||||
read_image(f, bmp, infoheader)
|
||||
|
||||
return bmp
|
||||
|
||||
end
|
||||
|
||||
local function check_bmp(filename)
|
||||
local f, e = io.open(filename, "rb")
|
||||
if not f then return nil, e end
|
||||
local r, e = get_bmp_infoheader(f)
|
||||
if e then print(e) end
|
||||
f:close()
|
||||
return r, e
|
||||
end
|
||||
|
||||
local function load_bmp(filename)
|
||||
local f, e = io.open(filename, "rb")
|
||||
if not f then return nil, e end
|
||||
local r, e = load_bmp_pf(f)
|
||||
f:close()
|
||||
return r, e
|
||||
end
|
||||
|
||||
imageloader.register_type({
|
||||
description = "Windows or OS/2 Bitmap",
|
||||
load = load_bmp,
|
||||
check = check_bmp,
|
||||
})
|
37
lib/loader_png.lua
Normal file
37
lib/loader_png.lua
Normal file
@ -0,0 +1,37 @@
|
||||
package.path = (MODPATH.."/lib/pngLua/?.lua;"
|
||||
..MODPATH.."/lib/pngLua/?/init.lua;"
|
||||
..package.path)
|
||||
|
||||
require "png"
|
||||
|
||||
local function get_png(filename)
|
||||
local ok, r = pcall(pngImage, filename)
|
||||
if not ok then return nil, r end -- NOTE: r == error message
|
||||
return r
|
||||
end
|
||||
|
||||
local function load_png(filename)
|
||||
local img, e = get_png(filename)
|
||||
if not img then return nil, e end
|
||||
local pixels = { }
|
||||
local bmp = {
|
||||
w = img.width, h = img.height,
|
||||
pixels = pixels,
|
||||
}
|
||||
for y = 1, bmp.h do
|
||||
local oline = { }
|
||||
local iline = img.scanLines[y]
|
||||
pixels[y] = oline
|
||||
for x = 1, bmp.w do
|
||||
local pixel = iline.pixels[x]
|
||||
oline[x] = { r=pixel.R, g=pixel.G, b=pixel.B }
|
||||
end
|
||||
end
|
||||
return bmp
|
||||
end
|
||||
|
||||
imageloader.register_type({
|
||||
description = "Portable Network Graphics",
|
||||
load = load_png,
|
||||
check = get_png,
|
||||
})
|
@ -3,7 +3,6 @@ Stream = class()
|
||||
Stream.data = ""
|
||||
Stream.position = 1
|
||||
Stream.__name = "Stream"
|
||||
|
||||
function Stream:bsRight(num, pow)
|
||||
return math.floor(num / 2^pow)
|
||||
end
|
||||
@ -21,7 +20,7 @@ function Stream:bytesToNum(bytes)
|
||||
return n
|
||||
end
|
||||
|
||||
function Stream:__init(param)
|
||||
function Stream:__init(param) --@todo realterrain note: gets this far 3 times then does nothing...
|
||||
if (param.inputF ~= nil) then
|
||||
self.data = io.open(param.inputF, "rb"):read("*all")
|
||||
end
|
||||
|
BIN
rasters/demo/biomes.bmp
Executable file
BIN
rasters/demo/biomes.bmp
Executable file
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
BIN
rasters/demo/biomes.png
Normal file
BIN
rasters/demo/biomes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
rasters/demo/dem.bmp
Executable file
BIN
rasters/demo/dem.bmp
Executable file
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
BIN
rasters/demo/dem.png
Normal file
BIN
rasters/demo/dem.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 144 KiB |
Loading…
x
Reference in New Issue
Block a user