Recent Changes - Search:


Users


Developers

edit SideBar

LuaScriptPCXLoader

This 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

Edit - History - Print - Recent Changes - Search
Page last modified on July 04, 2007, at 02:11 AM