mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2024-11-01 08:10:58 +11:00
Added bmp.lua and a logo that's more detailed yet smaller than the current one.
Also, the logo is now stored as a BMP. Turnaround time on that thing is one click, we're nowhere near done reaping the benefits of indexed colour, etc.
This commit is contained in:
parent
c5b58e79ff
commit
899a3b2521
@ -4,8 +4,14 @@
|
|||||||
local event = require("event")(neo)
|
local event = require("event")(neo)
|
||||||
local neoux = require("neoux")(event, neo)
|
local neoux = require("neoux")(event, neo)
|
||||||
local braille = require("braille")
|
local braille = require("braille")
|
||||||
|
local bmp = require("bmp")
|
||||||
local icecap = neo.requireAccess("x.neo.pub.base", "loadimg")
|
local icecap = neo.requireAccess("x.neo.pub.base", "loadimg")
|
||||||
local qt = icecap.open("/logo.data", false)
|
local qt = icecap.open("/logo.bmp", false)
|
||||||
|
|
||||||
|
local header = qt.read(bmp.headerMinSzBMP)
|
||||||
|
|
||||||
|
local lcBase = bmp.headerMinSzBMP
|
||||||
|
local lcWidth = 1
|
||||||
|
|
||||||
local lc = {}
|
local lc = {}
|
||||||
local lcdq = {}
|
local lcdq = {}
|
||||||
@ -18,26 +24,46 @@ for i = 1, queueSize do
|
|||||||
end
|
end
|
||||||
local function getLine(y)
|
local function getLine(y)
|
||||||
if not lc[y] then
|
if not lc[y] then
|
||||||
local idx = (y - 1) * 120
|
local idx = y * lcWidth
|
||||||
qt.seek("set", idx)
|
qt.seek("set", lcBase + idx - 1)
|
||||||
if lcdq[1] then
|
if lcdq[1] then
|
||||||
lc[table.remove(lcdq, 1)] = nil
|
lc[table.remove(lcdq, 1)] = nil
|
||||||
end
|
end
|
||||||
table.insert(lcdq, y)
|
table.insert(lcdq, y)
|
||||||
lc[y] = qt.read(120) or ""
|
lc[y] = qt.read(lcWidth)
|
||||||
end
|
end
|
||||||
return lc[y]
|
return lc[y]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local bitmap = bmp.connect(function (i)
|
||||||
|
if i >= lcBase then
|
||||||
|
local ld = getLine(math.floor((i - lcBase) / lcWidth))
|
||||||
|
i = ((i - lcBase) % lcWidth) + 1
|
||||||
|
return ld:byte(i) or 0
|
||||||
|
end
|
||||||
|
return header:byte(i) or 0
|
||||||
|
end)
|
||||||
|
|
||||||
|
qt.seek("set", bitmap.paletteAddress - 1)
|
||||||
|
header = header .. qt.read(bitmap.paletteCol * 4)
|
||||||
|
lcBase = bitmap.dataAddress
|
||||||
|
lcWidth = bitmap.dsSpan
|
||||||
|
|
||||||
local running = true
|
local running = true
|
||||||
|
|
||||||
neoux.create(20, 10, nil, neoux.tcwindow(20, 10, {
|
local function decodeRGB(rgb)
|
||||||
braille.new(1, 1, 20, 10, {
|
return math.floor(rgb / 65536) % 256, math.floor(rgb / 256) % 256, rgb % 256
|
||||||
|
end
|
||||||
|
|
||||||
|
local bW, bH = math.ceil(bitmap.width / 2), math.ceil(bitmap.height / 4)
|
||||||
|
neoux.create(bW, bH, nil, neoux.tcwindow(bW, bH, {
|
||||||
|
braille.new(1, 1, bW, bH, {
|
||||||
selectable = true,
|
selectable = true,
|
||||||
get = function (window, x, y, bg, fg, selected, colour)
|
get = function (window, x, y, bg, fg, selected, colour)
|
||||||
local data = getLine(y)
|
if bitmap.ignoresPalette then
|
||||||
local idx = ((x - 1) * 3) + 1
|
return decodeRGB(bitmap.getPixel(x - 1, y - 1, 0))
|
||||||
return data:byte(idx) or 255, data:byte(idx + 1) or 0, data:byte(idx + 2) or 255
|
end
|
||||||
|
return decodeRGB(bitmap.getPalette(bitmap.getPixel(x - 1, y - 1, 0)))
|
||||||
end
|
end
|
||||||
}, 1)
|
}, 1)
|
||||||
}, function (w)
|
}, function (w)
|
||||||
|
@ -120,7 +120,7 @@ return {
|
|||||||
},
|
},
|
||||||
files = {
|
files = {
|
||||||
"apps/app-klogo.lua",
|
"apps/app-klogo.lua",
|
||||||
"data/app-klogo/logo.data"
|
"data/app-klogo/logo.bmp"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
["app-flash"] = {
|
["app-flash"] = {
|
||||||
|
BIN
code/data/app-klogo/logo.bmp
Normal file
BIN
code/data/app-klogo/logo.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
250
code/libs/bmp.lua
Normal file
250
code/libs/bmp.lua
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
-- This is released into the public domain.
|
||||||
|
-- No warranty is provided, implied or otherwise.
|
||||||
|
|
||||||
|
-- bmp: Portable OC BMP/DIB library
|
||||||
|
-- Flexible: Reading can be set to
|
||||||
|
-- ignore first 14 bytes,
|
||||||
|
-- allowing reuse of the library on
|
||||||
|
-- ICO/CUR data. Yes, really.
|
||||||
|
|
||||||
|
-- handle(i, valDiv, valMod)
|
||||||
|
local function bitsCore(i, fieldOfs, fieldWidth, handle)
|
||||||
|
local adv = math.floor(fieldOfs / 8)
|
||||||
|
i = i + adv
|
||||||
|
fieldOfs = fieldOfs - (adv * 8)
|
||||||
|
-- above 3 lines are a removable optimization
|
||||||
|
while fieldWidth > 0 do
|
||||||
|
local bitsHere = math.min(fieldWidth, math.max(0, 8 - fieldOfs))
|
||||||
|
if bitsHere > 0 then
|
||||||
|
local pow1 = math.floor(2 ^ bitsHere)
|
||||||
|
-- offset
|
||||||
|
-- pixels are "left to right" in the MostSigBitFirst stream
|
||||||
|
local aFieldOfs = 8 - (fieldOfs + bitsHere)
|
||||||
|
local pow2 = math.floor(2 ^ aFieldOfs)
|
||||||
|
handle(i, pow2, pow1)
|
||||||
|
fieldWidth = fieldWidth - bitsHere
|
||||||
|
fieldOfs = 0
|
||||||
|
else
|
||||||
|
-- in case the 'adv' opt. gets removed
|
||||||
|
fieldOfs = fieldOfs - 8
|
||||||
|
end
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function encode16(t)
|
||||||
|
return string.char(t % 0x100) .. string.char(math.floor(t / 0x100))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function encode32(t)
|
||||||
|
return encode16(t % 0x10000) .. encode16(math.floor(t / 0x10000))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This & the BMP equivalent return a header,
|
||||||
|
-- a buffer size, and a 1-based data pointer,
|
||||||
|
-- and are used to initially create the image.
|
||||||
|
-- Notably, for bpp <= 8, a paletteSize of 0 is illegal.
|
||||||
|
-- topDown adjusts the order of scanlines.
|
||||||
|
-- cMode adjusts some values.
|
||||||
|
-- IT IS RECOMMENDED YOU PROPERLY SET THE MASK UP.
|
||||||
|
local function prepareDIB(w, h, p, bpp, paletteSize, topDown, cMode)
|
||||||
|
if bpp <= 8 then
|
||||||
|
if paletteSize == 0 then
|
||||||
|
error("A palette size of 0 is invalid for <= 8-bit images. Use 16-bit or 32-bit for no palette, or specify the amount of palette entries.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local scanWB = math.ceil((bpp * w) / 32) * 4
|
||||||
|
local palSize = paletteSize * 4
|
||||||
|
local bufSize = scanWB * h * p
|
||||||
|
|
||||||
|
local aH = h
|
||||||
|
if cMode then
|
||||||
|
-- O.o why change format? who knows!
|
||||||
|
aH = aH * 2
|
||||||
|
bufSize = bufSize + ((math.ceil(w / 32) * 4) * h * p)
|
||||||
|
end
|
||||||
|
if topDown then
|
||||||
|
aH = 0x100000000 - aH
|
||||||
|
end
|
||||||
|
return
|
||||||
|
"\x28\x00\x00\x00" .. -- 0x0E
|
||||||
|
encode32(w) .. -- 0x12
|
||||||
|
encode32(aH) .. -- 0x16
|
||||||
|
encode16(p) .. -- 0x1A
|
||||||
|
encode16(bpp) .. -- 0x1C
|
||||||
|
"\x00\x00\x00\x00" .. -- 0x1E
|
||||||
|
encode32(bufSize) .. -- 0x22
|
||||||
|
"\x00\x00\x00\x00" .. -- 0x26
|
||||||
|
"\x00\x00\x00\x00" .. -- 0x2A
|
||||||
|
encode32(paletteSize) .. -- 0x2E
|
||||||
|
encode32(paletteSize), -- 0x32 then EOH
|
||||||
|
-- -14 here to move back into headless units
|
||||||
|
0x36 + palSize + bufSize - 14,
|
||||||
|
0x36 + palSize + 1 - 14 -- 1-based data pointer
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
headerMinSzBMP = 0x36,
|
||||||
|
headerMinSzDIB = 0x36 - 14,
|
||||||
|
-- get/set are (index) and (index, value) respectively
|
||||||
|
-- they are 1-based
|
||||||
|
-- If "packed" is used, two things happen:
|
||||||
|
-- 1. The +1 offeset for 1-based is replaced
|
||||||
|
-- with packed (so -13 is pure packed-DIB)
|
||||||
|
-- 2. We don't try to use the BMP header
|
||||||
|
connect = function (get, set, cMode, packed)
|
||||||
|
-- NOTE: Internally, BMP addresses are used,
|
||||||
|
-- so that the Wikipedia page can be used
|
||||||
|
-- as a valid reference for header fields.
|
||||||
|
-- verify cMode
|
||||||
|
if cMode ~= nil and cMode ~= "mask" and cMode ~= "colour" then
|
||||||
|
error("Unknown cMode " .. cMode)
|
||||||
|
end
|
||||||
|
-- NOTE: 0-base is used
|
||||||
|
local function get8(i)
|
||||||
|
return get(i + (packed or 1))
|
||||||
|
end
|
||||||
|
local function get16(i)
|
||||||
|
return get8(i) + (256 * get8(i + 1))
|
||||||
|
end
|
||||||
|
local function get32(i)
|
||||||
|
return get16(i) + (65536 * get16(i + 2))
|
||||||
|
end
|
||||||
|
local function set8(i, v)
|
||||||
|
set(i + (packed or 1), v)
|
||||||
|
end
|
||||||
|
local function set32(i, v)
|
||||||
|
local st = encode32(v)
|
||||||
|
set8(i, st:byte(1))
|
||||||
|
set8(i + 1, st:byte(2))
|
||||||
|
set8(i + 2, st:byte(3))
|
||||||
|
set8(i + 3, st:byte(4))
|
||||||
|
end
|
||||||
|
local function getBits(i, fieldOfs, fieldWidth)
|
||||||
|
local v = 0
|
||||||
|
local vp = 1
|
||||||
|
bitsCore(i, fieldOfs, fieldWidth, function (i, valDiv, valMod)
|
||||||
|
local data = math.floor(get8(i) / valDiv) % valMod
|
||||||
|
v = v + (data * vp)
|
||||||
|
vp = vp * valMod
|
||||||
|
end)
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
local function setBits(i, fieldOfs, fieldWidth, v)
|
||||||
|
return bitsCore(i, fieldOfs, fieldWidth, function (i, valDiv, valMod)
|
||||||
|
local data = get8(i)
|
||||||
|
-- Firstly need to eliminate the old data
|
||||||
|
data = data - ((math.floor(data / valDiv) % valMod) * valDiv)
|
||||||
|
-- Now to insert the new data
|
||||||
|
data = data + ((v % valMod) * valDiv)
|
||||||
|
set8(i, data)
|
||||||
|
-- Advance
|
||||||
|
v = math.floor(v / valMod)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
-- direct header reads (all of them)
|
||||||
|
local hdrSize = get32(0x0E)
|
||||||
|
if hdrSize < 0x28 then
|
||||||
|
error("OS/2 Bitmaps Incompatible")
|
||||||
|
end
|
||||||
|
local width = get32(0x12)
|
||||||
|
local height = get32(0x16)
|
||||||
|
local planes = get16(0x1A)
|
||||||
|
local bpp = get16(0x1C)
|
||||||
|
local compression = get32(0x1E)
|
||||||
|
local paletteCol = 0
|
||||||
|
local other = get32(0x2E)
|
||||||
|
paletteCol = other
|
||||||
|
-- postprocess
|
||||||
|
|
||||||
|
-- The actual values used for addressing, for cMode to mess with
|
||||||
|
local basePtr = 14 + hdrSize + (paletteCol * 4)
|
||||||
|
local scanWB = math.ceil((bpp * width) / 32) * 4
|
||||||
|
local monoWB = (math.ceil((bpp * width) / 32) * 4)
|
||||||
|
local planeWB = scanWB * height
|
||||||
|
|
||||||
|
if not packed then
|
||||||
|
basePtr = get32(0x0A) -- 'BM' header
|
||||||
|
end
|
||||||
|
-- negative height means sane coords
|
||||||
|
local upDown = true
|
||||||
|
if height >= 0x80000000 then
|
||||||
|
height = height - 0x100000000
|
||||||
|
height = -height
|
||||||
|
upDown = false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Cursor/Icon
|
||||||
|
if cMode then
|
||||||
|
height = math.floor(height / 2)
|
||||||
|
assert(planes == 1, "planes ~= 1 for cursor")
|
||||||
|
planeWB = planeWB + (monoWB * height)
|
||||||
|
end
|
||||||
|
if cMode == "mask" then
|
||||||
|
if upDown then
|
||||||
|
basePtr = basePtr + (scanWB * height)
|
||||||
|
end
|
||||||
|
bpp = 1
|
||||||
|
scanWB = monoWB
|
||||||
|
paletteCol = 0
|
||||||
|
compression = 3
|
||||||
|
elseif cMode == "colour" then
|
||||||
|
if not upDown then
|
||||||
|
basePtr = basePtr + (monoWB * height)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Check compression
|
||||||
|
if (compression ~= 0) and (compression ~= 3) and (compression ~= 6) then
|
||||||
|
error("compression " .. compression .. " unavailable")
|
||||||
|
end
|
||||||
|
-- paletteSize correction for comp == 0
|
||||||
|
if (bpp <= 8) and (paletteCol == 0) and (compression == 0) then
|
||||||
|
paletteCol = math.floor(2 ^ bpp)
|
||||||
|
end
|
||||||
|
return {
|
||||||
|
width = width,
|
||||||
|
height = height,
|
||||||
|
planes = planes,
|
||||||
|
bpp = bpp,
|
||||||
|
ignoresPalette = (compression ~= 0) or (paletteCol == 0) or (cMode == "mask"),
|
||||||
|
paletteCol = paletteCol,
|
||||||
|
paletteAddress = 14 + hdrSize + (packed or 1),
|
||||||
|
dataAddress = basePtr + (packed or 1),
|
||||||
|
dsFull = get32(0x22),
|
||||||
|
dsSpan = scanWB,
|
||||||
|
dsPlane = planeWB,
|
||||||
|
getPalette = function (i)
|
||||||
|
return get32(14 + hdrSize + (i * 4))
|
||||||
|
end,
|
||||||
|
setPalette = function (i, xrgb)
|
||||||
|
set32(14 + hdrSize + (i * 4), xrgb)
|
||||||
|
end,
|
||||||
|
-- Coordinates are 0-based for sanity. Returns raw colour value.
|
||||||
|
getPixel = function (x, y, p)
|
||||||
|
if upDown then
|
||||||
|
y = height - (1 + y)
|
||||||
|
end
|
||||||
|
local i = basePtr + (y * scanWB) + (p * planeWB)
|
||||||
|
return getBits(i, x * bpp, bpp)
|
||||||
|
end,
|
||||||
|
-- Uses raw colour value.
|
||||||
|
setPixel = function (x, y, p, v)
|
||||||
|
if upDown then
|
||||||
|
y = height - (1 + y)
|
||||||
|
end
|
||||||
|
local i = basePtr + (y * scanWB) + (p * planeWB)
|
||||||
|
setBits(i, x * bpp, bpp, v)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
-- See prepareDIB above for format.
|
||||||
|
prepareBMP = function (...)
|
||||||
|
local head, tLen, dtPtr = prepareDIB(...)
|
||||||
|
tLen = tLen + 14 -- add BM header
|
||||||
|
dtPtr = dtPtr + 14
|
||||||
|
head = "BM" .. encode32(tLen) .. "mRWH" .. encode32(dtPtr - 1) .. head
|
||||||
|
return head, tLen, dtPtr
|
||||||
|
end,
|
||||||
|
prepareDIB = prepareDIB
|
||||||
|
}
|
@ -184,7 +184,10 @@ heldRef = {
|
|||||||
drop = cbs.drop and cTransform(cbs.drop),
|
drop = cbs.drop and cTransform(cbs.drop),
|
||||||
scroll = cbs.scroll and cTransform(cbs.scroll),
|
scroll = cbs.scroll and cTransform(cbs.scroll),
|
||||||
line = function (window, x, y, iy, bg, fg, selected)
|
line = function (window, x, y, iy, bg, fg, selected)
|
||||||
local colour = ((window.getDepth() <= 1) or nil) and colour
|
local colour = colour
|
||||||
|
if window.getDepth() <= 1 then
|
||||||
|
colour = nil
|
||||||
|
end
|
||||||
calcLine(x, y, control.w, window.span, function (xb, yb)
|
calcLine(x, y, control.w, window.span, function (xb, yb)
|
||||||
return cbs.get(window, xb + 1, yb + (iy * 4) - 3, bg, fg, selected, colour)
|
return cbs.get(window, xb + 1, yb + (iy * 4) - 3, bg, fg, selected, colour)
|
||||||
end, colour)
|
end, colour)
|
||||||
|
@ -38,7 +38,8 @@ return {
|
|||||||
"docs/ul-event",
|
"docs/ul-event",
|
||||||
"docs/ul-fmttx",
|
"docs/ul-fmttx",
|
||||||
"docs/ul-neoux",
|
"docs/ul-neoux",
|
||||||
"docs/ul-broil",
|
"docs/ul-brail",
|
||||||
|
"docs/ul-bmp__",
|
||||||
"docs/gp-pedan"
|
"docs/gp-pedan"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
248
repository/docs/ul-bmp__
Normal file
248
repository/docs/ul-bmp__
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
The "bmp" library is a library for
|
||||||
|
the express purpose of reading and
|
||||||
|
writing Windows BMP files and other
|
||||||
|
Windows DIB headers.
|
||||||
|
|
||||||
|
It is written with portability,
|
||||||
|
memory-efficiency, and reusability
|
||||||
|
as it's primary goals.
|
||||||
|
|
||||||
|
With this in mind, it can be used as
|
||||||
|
the backend for an ICO/CUR handling
|
||||||
|
library, works with packed-DIB data,
|
||||||
|
only requires the first 0x36 bytes
|
||||||
|
of a .BMP to be present, and can be
|
||||||
|
used on KittenOS NEO, OpenOS, and
|
||||||
|
just about any place with a desktop
|
||||||
|
Lua interpreter available for use.
|
||||||
|
|
||||||
|
(That said, it's not 5.1-tested.)
|
||||||
|
|
||||||
|
That said, it does not handle all the
|
||||||
|
possible bitmap formats, restricting
|
||||||
|
itself to support of BI_RGB where
|
||||||
|
possible, and BI_BITFIELDS to a
|
||||||
|
limited extent.
|
||||||
|
|
||||||
|
Given this covers most bitmaps that
|
||||||
|
you are likely to generate, do not
|
||||||
|
underestimate the use of this.
|
||||||
|
|
||||||
|
The library has 2 fields:
|
||||||
|
headerMinSzBMP,
|
||||||
|
headerMinSzDIB: The minimum data you
|
||||||
|
must have available when calling
|
||||||
|
connect for a given format.
|
||||||
|
|
||||||
|
The library has 3 functions:
|
||||||
|
|
||||||
|
connect(get, set, cMode, packed):
|
||||||
|
"Connects" to a bitmap. A very real
|
||||||
|
implication of this is that the
|
||||||
|
data get/set accesses is where the
|
||||||
|
actual bitmap is, and this merely
|
||||||
|
provides a way to access it in a
|
||||||
|
useful form (as pixels).
|
||||||
|
Technically, all but 'get' are
|
||||||
|
optional, but I feel it necessary
|
||||||
|
to document them as if they are
|
||||||
|
implicitly left nil by those users
|
||||||
|
who omit them because of their
|
||||||
|
functionality.
|
||||||
|
Due to this section being a rather
|
||||||
|
long length, the paragraph
|
||||||
|
separation is per-argument here.
|
||||||
|
|
||||||
|
get is best described by:
|
||||||
|
function (a) return dt:byte(a) end
|
||||||
|
|
||||||
|
set, which is optional unless you
|
||||||
|
call any of the set* functions in
|
||||||
|
the resulting bitmap, has a longer
|
||||||
|
description:
|
||||||
|
function (a, v)
|
||||||
|
dt = dt:sub(1, a - 1) ..
|
||||||
|
string.char(v) ..
|
||||||
|
dt:sub(a + 1)
|
||||||
|
end
|
||||||
|
Notably, while these are the
|
||||||
|
canonical implementations of these
|
||||||
|
functions, they are by no means
|
||||||
|
the only implementations, and it
|
||||||
|
is the purpose of these callbacks
|
||||||
|
to allow choice in how you write
|
||||||
|
them.
|
||||||
|
|
||||||
|
cMode exists for cursor and icon
|
||||||
|
handling. These images are split
|
||||||
|
via a very horrifying mechanism
|
||||||
|
into an AND mask, and a XOR mask.
|
||||||
|
The XOR mask typically contains
|
||||||
|
what could be called the actual
|
||||||
|
image - the AND mask then acts
|
||||||
|
as a sort of alpha mask, blacking
|
||||||
|
out the areas where the XOR mask
|
||||||
|
is then projected onto.
|
||||||
|
It can be one of three values.
|
||||||
|
It can be nil, in which case this
|
||||||
|
is an ordinary DIB, with no evil
|
||||||
|
nonsense applied to it -
|
||||||
|
It can be "colour", in which case
|
||||||
|
the XOR mask (the actual image in
|
||||||
|
most cases) is shown -
|
||||||
|
And it can be "mask", in which case
|
||||||
|
the AND mask is accessed instead.
|
||||||
|
(Notably, bpp, paletteSize, and
|
||||||
|
ignoresPalette changes to the
|
||||||
|
1bpp mask format in use here.)
|
||||||
|
|
||||||
|
packed exists for the use of those
|
||||||
|
bitmaps that don't have a BMP file
|
||||||
|
header, the usual "BM". In this
|
||||||
|
case, you can remove support for
|
||||||
|
gap1 but allow yourself to avoid
|
||||||
|
the BM header as a result.
|
||||||
|
If not nil, it is how much to
|
||||||
|
offset the indexes from 0-based
|
||||||
|
offsets into a .BMP file to the
|
||||||
|
final positions.
|
||||||
|
The following table is useful for
|
||||||
|
understanding this:
|
||||||
|
1: Standard 1-indexed BMP handling,
|
||||||
|
but with no gap1 support (!)
|
||||||
|
-13: Standard 1-indexed handling of
|
||||||
|
a packed DIB (no BMP header),
|
||||||
|
such as a BITMAP or ICON
|
||||||
|
resource (set cMode if ICON)
|
||||||
|
-9: Standard 1-indexed handling of
|
||||||
|
a CURSOR resource, which has
|
||||||
|
a 2-short hotspot header
|
||||||
|
|
||||||
|
prepareDIB(w, h, p, bpp, paletteSize
|
||||||
|
, topDown, cMode) -> hd, sz, dp:
|
||||||
|
(See prepareBMP if you want a .BMP
|
||||||
|
file, but this describes how to
|
||||||
|
use the arguments and returns.)
|
||||||
|
This prepares a packed DIB, and
|
||||||
|
returns three values:
|
||||||
|
1. The header. (The palette, in
|
||||||
|
the 4-byte-per-colour form,
|
||||||
|
will follow immediately.)
|
||||||
|
2. The buffer size, including the
|
||||||
|
header in 1. The bytes that
|
||||||
|
are not specified can be
|
||||||
|
initialized in any fashion,
|
||||||
|
as they are part of the colour
|
||||||
|
and later image data itself.
|
||||||
|
3. The pointer to the pixels for
|
||||||
|
BM creation.
|
||||||
|
|
||||||
|
w, h, p, and bpp are the usual -
|
||||||
|
width, height, planes, pixel depth
|
||||||
|
- but the paletteSize needs note.
|
||||||
|
If the BPP is <= 8, then the size
|
||||||
|
of the palette must not be 0.
|
||||||
|
This is to avoid unintentionally
|
||||||
|
triggering legacy features in the
|
||||||
|
BMP format.
|
||||||
|
|
||||||
|
topDown and cMode are essentially
|
||||||
|
booleans that can safely be nil,
|
||||||
|
where nil is interpreted as false.
|
||||||
|
|
||||||
|
topDown indicates that the image is
|
||||||
|
to be top-down rather than the
|
||||||
|
standard upsidedown form of a BMP.
|
||||||
|
This may look odd if streaming a
|
||||||
|
BMP, so the option, while rather
|
||||||
|
an odd one, has been included.
|
||||||
|
|
||||||
|
cMode indicates that this image is
|
||||||
|
intended for use in an ICON or
|
||||||
|
CURSOR resource of some form, and
|
||||||
|
should thus contain an AND mask.
|
||||||
|
|
||||||
|
prepareBMP(...):
|
||||||
|
This prepares a .BMP file. It has
|
||||||
|
the same arguments and returns as
|
||||||
|
prepareDIB, and indeed wraps it.
|
||||||
|
|
||||||
|
Bitmap objects, while not read-only,
|
||||||
|
do not particularly change if you
|
||||||
|
write to them.
|
||||||
|
|
||||||
|
Going out of bounds with a bitmap
|
||||||
|
object will have hilarious results.
|
||||||
|
|
||||||
|
...Don't do it.
|
||||||
|
|
||||||
|
Anyway, they have these fields:
|
||||||
|
|
||||||
|
width, height, planes: The usuals.
|
||||||
|
(NOTE: Due to lack of examples,
|
||||||
|
it is assumed that planes are a
|
||||||
|
dimension more major than height.
|
||||||
|
If this isn't the case, someone
|
||||||
|
do tell me, preferably with an
|
||||||
|
example and a way to open it that
|
||||||
|
does not involve this library, so
|
||||||
|
I can test and correct all of the
|
||||||
|
code involving them.)
|
||||||
|
bpp: Bits per pixel. This specifies
|
||||||
|
a limit on numbers passed to
|
||||||
|
and from the bitmap object,
|
||||||
|
of 1 << bpp (2 ^ bpp).
|
||||||
|
A number may not be equal to
|
||||||
|
or exceed this limit.
|
||||||
|
ignoresPalette: Used to indicate
|
||||||
|
the palette is worthless and does
|
||||||
|
not affect image contents in any
|
||||||
|
way at all. If one exists.
|
||||||
|
paletteCol: The amount of colours in
|
||||||
|
the palette. Multiply by 4 for a
|
||||||
|
byte count.
|
||||||
|
paletteAddress: Useful for caching,
|
||||||
|
the palette starts at this get/set
|
||||||
|
address.
|
||||||
|
dataAddress: Useful for caching,
|
||||||
|
the data starts at this get/set
|
||||||
|
address.
|
||||||
|
dataFull: The size of the data of
|
||||||
|
the image, according to the image.
|
||||||
|
dsSpan: This is a hint for the cache
|
||||||
|
and cannot be relied upon to be
|
||||||
|
correct, only >= 1:
|
||||||
|
Scanline length in bytes.
|
||||||
|
dsPlane: This is a hint for the
|
||||||
|
cache and cannot be relied upon to
|
||||||
|
be correct, only >= 1:
|
||||||
|
Plane length in bytes.
|
||||||
|
getPalette(i): Gets the XRGB value
|
||||||
|
of colour i as an integer.
|
||||||
|
Do not go out of range of I.
|
||||||
|
setPalette(i, v): Sets the XRGB
|
||||||
|
value of colour i as an integer.
|
||||||
|
Do not go out of range of I or V.
|
||||||
|
getPixel(x, y, p): Returns the pixel
|
||||||
|
value at X, Y, P. Do not go out of
|
||||||
|
the range of X, Y or P.
|
||||||
|
setPixel(x, y, p, v): Sets the pixel
|
||||||
|
value at X, Y, P to V. Do not go
|
||||||
|
out of the range of X, Y, P, or V.
|
||||||
|
|
||||||
|
...in other words, about as much
|
||||||
|
usability as a BufferedImage with
|
||||||
|
getGraphics and createGraphics taken
|
||||||
|
out of it for some crazy reason.
|
||||||
|
|
||||||
|
The primary use of this library is
|
||||||
|
because people like to use formats
|
||||||
|
they happen to have actually heard
|
||||||
|
of before, and everything but BMP is
|
||||||
|
too complicated for low-memory OSes
|
||||||
|
to stream from disk.
|
||||||
|
|
||||||
|
-- This is released into
|
||||||
|
the public domain.
|
||||||
|
-- No warranty is provided,
|
||||||
|
implied or otherwise.
|
Loading…
Reference in New Issue
Block a user