Code archives/File Utilities/Pub.PCXLoader

This code has been declared by its author to be Public Domain code.

Download source code

Pub.PCXLoader by gman2005
Pretty basic as it only loads 8bit 256 color images with a palette. full mod download at:

2006_01_14 PCXLoader Mod

PCXLoader Sample

extract contained files to mod/pub.mod/pcxloader.mod

this works like all other pixmap loaders. just import the lib and call LoadPixmap.
Strict

Rem
bbdoc: PCX loader.  Only supports 8bit 256 color palette PCX images.
End Rem
Module Pub.PCXLoader

ModuleInfo "Version: 1.00"
ModuleInfo "Author: gman"
ModuleInfo "License: freebie"

Import BRL.Pixmap
Import BRL.Bank

Type TPixmapLoaderPCX Extends TPixmapLoader

	Method LoadPixmap:TPixmap( file:TStream )
		Local retval:TPixmap=Null
		
		Local PCXData:Byte[]
		Local PaletteData:Int[]

		Local header:SPCXHeader=New SPCXHeader
		header.fillFromReader(file,SPCXHeader.size,0,0)

		' Return If the header is wrong
		If (header.Manufacturer <> $0a And header.Encoding <> $01) Then Return Null

		' Return If this isn't a supported type
		If ((header.BitsPerPixel < 8) Or (header.BitsPerPixel > 24))
			DebugLog("Unsupported bits per pixel in PCX file ("+header.BitsPerPixel+").")
			Return Null
		EndIf

		Local pos:Int = StreamPos(file)
		Local palIndicator:Byte
				
		' check the PAL indicator
		SeekStream(file,StreamSize(file)-769)

		palIndicator=ReadByte(file)

		If ( palIndicator <> 12 )
			DebugLog("Unsupported pal indicator in PCX file ("+palIndicator+").")
			Return Null
		EndIf
					
		' read palette
		PaletteData = PaletteData[..256]
		Local tempPalette:Byte Ptr=ReadString(file,768).ToCString()
		
		' convert the red,green,blue of the palette into colors				
		For Local i:Int=0 To 255
			PaletteData[i]=($ff000000 | ..
				tempPalette[i*3+0] Shl 16 | ..
				tempPalette[i*3+1] Shl 8 | ..
				tempPalette[i*3+2])								
		Next
		tempPalette=Null

		SeekStream(file,pos)

		Local width:Int, height:Int
		width = header.XMax - header.XMin + 1
		height = header.YMax - header.YMin + 1
				
		' read in the image data
		Local offset:Long,imagebytes:Long
		Local cnt:Int,char:Byte
				
		imagebytes = header.BytesPerLine * header.Planes * (1 + header.Ymax - header.Ymin)
		PCXData=PCXData[..imagebytes]
		Local bufr:Byte Ptr=Varptr(PCXData[0])
	
		Local written:Int		
		For offset = 0 To imagebytes-1    ' /* increment by cnt below */

			' read in the next char and see if we have read past the end of file
          	If Not encget(char,cnt,file) Then Exit

			' store the data, repeat the char cnt times if needed
               For Local i:Int = 0 To cnt-1
				bufr[0]=char
               	bufr:+1
			Next

			written:+ cnt

			' check to see if we have written enough
			If written>=imagebytes Then Exit
		Next

		' create the pixmap									
		Local tmpptr:Byte Ptr=Varptr(PCXData[0])
		retval=CreatePixmap(width,height,PF_RGB888)				
		
		For Local y:Int=0 To height-1				
			For Local x:Int=0 To width-1
				WritePixel(retval,x,y,PaletteData[tmpptr[0]])
				tmpptr:+1
			Next
		Next				
		
		header=Null
		bufr=Null
		tmpptr=Null
		PaletteData=Null
		PCXData=Null

		Return retval
	End Method
End Type

New TPixmapLoaderPCX

Private 

Rem
/* This procedure reads one encoded block from the image file And stores a
count And data byte.

Return result:  1 = valid data stored, Null = out of data in file */
EndRem
Function encget:Int(pbyt:Byte Var,pcnt:Int Var,fid:TStream)
	Local i:Byte
     pcnt = 1        '/* assume a "run" length of one */

	If Eof(fid) Then Return Null Else i=ReadByte(fid)

	If ($C0 = ($C0 & i))
		pcnt = $3F & i
		If Eof(fid) Then Return Null Else i=ReadByte(fid)
	EndIf

	pbyt = i
     Return 1
EndFunction

Type SPCXHeader Extends PACK_STRUCT
	Global size:Int=128

	Field Manufacturer:Byte
	Field Version:Byte
	Field Encoding:Byte
	Field BitsPerPixel:Byte
	Field XMin:Short
	Field YMin:Short
	Field XMax:Short
	Field YMax:Short
	Field HorizDPI:Short
	Field VertDPI:Short
	Field Palette:Byte[48]
	Field Reserved:Byte
	Field Planes:Byte
	Field BytesPerLine:Short
	Field PaletteType:Short
	Field HScrSize:Short
	Field VScrSize:Short
	Field Filler:Byte[54]

	Method fillFromBank(bank:TBank,start:Int=0)
		Local i:Int
		
		Manufacturer=PeekByte(bank,start)
		Version=PeekByte(bank,start+1)
		Encoding=PeekByte(bank,start+2)
		BitsPerPixel=PeekByte(bank,start+3)
		XMin=PeekShort(bank,start+4)
		YMin=PeekShort(bank,start+6)
		XMax=PeekShort(bank,start+8)
		YMax=PeekShort(bank,start+10)
		HorizDPI=PeekShort(bank,start+12)
		VertDPI=PeekShort(bank,start+14)
		
		For i=0 To 47
			Palette[i]=PeekByte(bank,start+16+i)
		Next
		
		Reserved=PeekByte(bank,start+64)
		Planes=PeekByte(bank,start+65)
		BytesPerLine=PeekShort(bank,start+66)
		PaletteType=PeekShort(bank,start+68)
		HScrSize=PeekShort(bank,start+70)
		VScrSize=PeekShort(bank,start+72)
		For i=0 To 53
			Filler[i]=PeekByte(bank,start+74+i)
		Next		
	EndMethod
	
EndType

' generic type for reading in PACK_STRUCT structures from files
Type PACK_STRUCT
	Global size:Int=0
			
	Method fillFromBank(bank:TBank,start:Int)
	EndMethod

	' returns true if successful
	Method fillFromReader:Int(fileToRead:TStream,tbsize:Int,readeroffset:Int=0,bankoffset:Int=0)
		If Not fileToRead Then Return False
		
		' create the bank
		Local structbank:TBank=CreateBank(tbsize)
		
		' read from the file
		structbank.Read(fileToRead,readeroffset,tbsize)
		
		' populate the STRUCT with what was read
		fillFromBank(structbank,bankoffset)
		
		' clear out the bank
		structbank=Null
		
		Return True
	EndMethod
	
	Method getBank:TBank()
		Return Null
	EndMethod	
EndType

Comments

None.

Code Archives Forum