bmp mode working

This commit is contained in:
Bob Omb 2015-12-06 20:56:06 -08:00
parent 3282417d7f
commit 8a918daa7b
10 changed files with 530 additions and 96 deletions

190
init.lua
View File

@ -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
View 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
View 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
View 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
View 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,
})

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
rasters/demo/biomes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB