|
Users /
LuaScriptPCXLoaderThis LuaScript example will attempt to load and display a 24-bit or 8-bit PCX image file. 1, 2, and 4-bit PCX image files are not supported. View PCX reference documentation here:
hf:setLittleEndian(true)
-- Read header
local hdrVersion = hf:getUInt(16)
local hdrEncoding = hf:getUInt(8)
local numBPP = hf:getUInt(8)
local xMin = hf:getUInt(16)
local yMin = hf:getUInt(16)
local xMax = hf:getUInt(16)
local yMax = hf:getUInt(16)
local w = xMax - xMin + 1
local h = yMax - yMin + 1
local dpiHoriz = hf:getUInt( 16 )
local dpiVert = hf:getUInt( 16 )
hf:skip( 49 * 8 )
local numPlanes = hf:getUInt( 8 )
local numBPL = hf:getUInt( 16 )
-- Validate PCX file
if( w < 1 or h < 1 or numBPP ~= 8 or hdrEncoding ~= 1 ) then
error( ("Invalid or unsupported PCX file: %dx%d, %d bpp, encoding:%d"):format( w, h, numBPP, hdrEncoding ) )
end
hf:print( ("%dx%d PCX; %d bits, %d planes\n"):format( w, h, numBPP, numPlanes ) )
-- Load 256 colour palette
palette = {};
if( numPlanes ~= 3 ) then
-- Get palette data. It starts 768 bytes from the end of the PCX
-- seekSel and lenSel operate in bits, so put 769 bytes into bits
hf:seekSel( hf:lenSel() - 8 * 769 )
-- First character of palette should be 0x0c
local palCode = hf:getUInt( 8 )
if( palCode ~= 0x0C ) then error( "Palette data not found" ); end
for i=0, 255 do
-- Stored palette is BGR - convert to RGB
local r = hf:getUInt(8)
local g = hf:getUInt(8)
local b = hf:getUInt(8)
palette[i] = hf:OR( hf:OR( b, hf:LSH( g, 8 ) ), hf:LSH( r, 16 ) )
-- hf:print( ("palette[%d] = 0x%08x\n"):format( i, palette[i] ) )
end
end
-- Actual image data starts at byte 128, so seek to there (in bits)
hf:seekSel( 8 * 128 )
hf:plotWidth( w )
-- Calculate line lengths for image and buffer, Allocate the buffer scan line
local numBPLFull = w * numPlanes
-- Decode and output each scanline
local iBufferLineLen = numBPL * numPlanes
for iLineCount = 0, h - 1 do
-- Decode line (3 lines for 24-bit)
local lLinePos = 0
local bufLine = {}
while( lLinePos < iBufferLineLen ) do
local c = hf:getUInt( 8 )
-- First 2 bits indicate run of next byte value
if( hf:AND( c, 0xC0 ) == 0xC0 ) then
-- Remaining 6 bits indicate run length
bRunLen = hf:AND( c, 0x3F )
-- Repeated value
local c = hf:getUInt( 8 )
while( bRunLen > 0 ) do
bufLine[lLinePos] = c
bRunLen = bRunLen - 1
lLinePos = lLinePos + 1
end
else
-- Other bytes are directly copied
bufLine[lLinePos] = c
lLinePos = lLinePos + 1
end
end
-- Output decoded pixels
if( numPlanes == 1 ) then
-- 8 bit image; use palette
for x=0,w-1 do
hf:plotRGB8( palette[bufLine[x]] )
end
else
-- 24 bit image; interleave the RGB values
for x=0,w-1 do
hf:plotRGB8( hf:OR( hf:OR( hf:LSH( bufLine[x], 16 ), hf:LSH( bufLine[x+w], 8 ) ), bufLine[x+w*2] ) )
end
end
end
|