Загрузка изображений PCX

Данный код позволяет загружать изображения в формате PCX для вывода в буфер так же просто как и изображения BMP.

Платформы: Linux, Windows
Автор: dafhi

 

'' ---------------------------------
'  PCX Loader by dafhi - 2012 06 22
' ----------------------------------

Type RGBTriple
    As Ubyte  red,grn,blu
End Type

Type RGBQUAD
    As Ubyte  Blu
    As Ubyte  Grn
    As Ubyte  Red
    As Ubyte  Alp
End Type

Type ImageInfo
    As Any Ptr                      img
    As Any Ptr                      pixels
    As Any Ptr                      botleft
    As Integer                      pitchm
    As Integer                      pitch
    As Integer                      wid
    As Integer                      hgt
    As Integer                      widM
    As Integer                      hgtM
    As Single                       midx
    As Single                       midy
    As Single                       diagonal
    As Integer                      bypp
    As Integer                      pitchBy4
    As Integer                      UB1D
    As Integer                      w_plus_h
    Declare Operator Cast() As Any Ptr
    Declare Function Create(Byval pWid As UShort=1,Byval pHgt As UShort=1,Byval pRed As UByte=127,Byval pGrn As UByte=127,Byval pBlu As UByte=127,Byval pAph As UByte=255,Byval bpp_ As UInteger=32) As Any Ptr
    Declare Function ScrInit(Byval pWid As UShort=640,Byval pHgt As UShort=480,Byval bpp_ As UInteger=32,Byval pRed As UByte=127,Byval pGrn As UByte=127,Byval pBlu As UByte=127,Byval pAph As UByte=255) As Any Ptr
    Declare Sub ScrInfo
    Declare Sub Cls( Byval pColor As UInteger=RGBA(0,0,0,0) )
    Declare Sub Destroy
    Declare Destructor
    Private:
    Declare Sub varsCommon
End Type
Operator ImageInfo.Cast () As Any Ptr
    Return  img
End Operator
Destructor ImageInfo
Destroy
End Destructor
Sub ImageInfo.varsCommon
    widM = wid - 1
    hgtM = hgt - 1
    midx = widM * 0.5
    midy = hgtM * 0.5
    UB1D = wid * hgt - 1
    botleft = pixels + pitch * hgtm
    pitchm = pitch - 1
    pitchBy4 = pitch \ 4
    w_plus_h = wid + hgt
    diagonal = Sqr(widM * widM + hgtM * hgtM)
End Sub
Function ImageInfo.Create(Byval pWid As Ushort, Byval pHgt As Ushort, _
    Byval pRed As Ubyte, _
    Byval pGrn As Ubyte, _
    Byval pBlu As Ubyte, _
    Byval pAph As Ubyte, _
    Byval bpp_ As Uinteger) As Any Ptr

    Destroy
    img = Imagecreate( pWid, pHgt, Rgba(pRed,pGrn,pBlu,pAph), bpp_ )
    ImageInfo img, wid, hgt, bypp, pitch, pixels
    varsCommon
    Return img

End Function
Sub ImageInfo.ScrInfo
    Screeninfo wid ,hgt  , , bypp, pitch
    pixels = Screenptr
    varsCommon
End Sub
Function ImageInfo.ScrInit(Byval pWid As Ushort,Byval pHgt As Ushort,Byval bpp_ As Uinteger,Byval pRed As Ubyte,Byval pGrn As Ubyte,Byval pBlu As Ubyte,Byval pAph As Ubyte) As Any Ptr
    Screenres pWid,pHgt,bpp_
    ScrInfo
    Return pixels
End Function
Sub ImageInfo.Destroy()
    If img = 0 Then Exit Sub
    Imagedestroy img
End Sub
Sub ImageInfo.Cls( Byval pColor As Uinteger )
''http://www.freebasic.net/forum/viewtopic.php?t=15809&
Dim As Uinteger cpy_ = (pitch * hgt) Shr 2
Dim As Uinteger Ptr dest = pixels
Asm mov eax, [pcolor]
Asm mov edi, [dest]
Asm mov ecx, [cpy_]
Asm rep stosd
End Sub

Type pcxHeader Field = 1
As Byte  manufacturer = &H0A
As Byte  version              '' 0 = 2.5
'' 2 = 2.8 w/ palette
'' 3 = 2.8 w/o palette
'' 5 = 3.0 or better

As Byte  Encoding             '' 1 = run-length
As Byte  bitsPerPlane         '' 1 2 4 8
As Ushort Xmin
As Ushort YMin
As Ushort Xmax
As Ushort YMax
As Ushort VertDPI             '' can also be img width
As Ushort HorzDPI             '' can also be img height.  Can be absent
As Ubyte  Pal(1 To 48)        '' 16x r,g,b + padding
As Ubyte  reserved
As Ubyte  colorPlanes         ''
As Ushort bytesPerScanLine    ''
As Ushort paltype             '' 1=Color/BW, 2 = Grayscale(ignored in ver 4+)
As Byte  pad(1 To 58)         '' fill header to 128 bytes
End Type

'' http://planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=2303&lngWId=1

Sub Read24Bit(Byref fileName As String,Byref pImg As ImageInfo)

Dim nFreeFile As Integer
Dim hPCX As PCXHeader
Dim bytes() As Ubyte

nFreeFile = Freefile
Open Filename For Binary Lock Write As #nFreeFile
Seek #nFreeFile, 1
Get #nFreeFile, , hPCX
Redim bytes(Lof(nFreeFile) - Len(hPCX) - 1)
Get #nFreeFile, , bytes()
Close #nFreeFile

Dim As Integer wid = hPCX.XMax - hPCX.XMin + 1
Dim As Integer hgt = hPCX.YMax - hPCX.YMin + 1

pImg.Create(wid,hgt)

Dim scan(wid * 3 - 1) As Ubyte
Dim As Integer ScanUB = Ubound(scan)
Dim As Integer cScanBytes = hPCX.colorPlanes * hPCX.BytesPerScanLine

Dim As Integer palByte, cRead

For Y As Integer = 0 To hgt - 1

Dim As Integer X, cScan
Do

Dim As Integer runLen = bytes(cRead)
If (runLen And &B11000000) = &B11000000 Then
runLen And= &B00111111
cRead += 1
Else
runLen = 1
End If

palbyte = bytes(cRead)

Dim As Integer ResultX = X + runLen
Dim As Integer end_ = ResultX - 1
If end_ > scanUB Then end_ = scanUB

For X = X To end_
scan(x) = palByte
Next
X = ResultX

cRead += 1
cScan += runLen
Loop While cScan < cScanBytes

Dim As Uinteger Ptr pix = pImg.pixels + Y * pImg.pitch
Dim As Integer      src1 = hPCX.bytesPerScanLine
Dim As Integer      src2 = 2*hPCX.bytesPerScanLine
Dim As RGBQUAD Ptr  rgbq = pImg.pixels + Y * pImg.pitch

For x = 0 To pImg.widM
rgbq[x].Red = scan(x)
rgbq[x].Grn = scan(x+src1)
rgbq[x].Blu = scan(x+src2)
rgbq[x].Alp = 255
Next

Next

End Sub
Sub Read8Bit(Byref fileName As String,Byref pImg As ImageInfo)

Dim nFreeFile As Integer
Dim hPCX As PCXHeader
Dim bytes() As Ubyte
Dim Pal(0 To 255) As RGBTriple
Dim PaletteRGB(0 To 255) As Uinteger
Dim PalByte As Ubyte

nFreeFile = Freefile

Open Filename For Binary Lock Write As #nFreeFile

Get #nFreeFile, , hPCX

Redim bytes(Lof(nFreeFile) - Len(hPCX) - Len(Pal) - Len(palByte) - 1)
Get #nFreeFile, , bytes()

Seek #nFreeFile, Lof(nFreeFile) - 768
Get #nFreeFile, , PalByte

Const PalHeader = 12

If PalByte = PalHeader Then
Seek #nFreeFile, Lof(nFreeFile) - 767
Get #nFreeFile, , Pal()
Close #nFreeFile
Else
Close #nFreeFile
? "The PCX that was passed didn't have a 256 colour palette! Can't read it!"
Exit Sub
End If

Dim As Integer wid = hPCX.XMax - hPCX.XMin + 1
Dim As Integer hgt = hPCX.YMax - hPCX.YMin + 1

Dim As Integer cScanBytes = hPCX.colorPlanes * hPCX.BytesPerScanLine

pImg.Create(wid,hgt)

Dim As Integer nBmpPos
Dim As Integer nBytePos

Dim As Integer printy

For Y  As Integer = 0 To hgt - 1

Dim As Integer      BmpX
Dim As Uinteger Ptr pix = pImg.pixels + Y * pImg.pitch

Do

Dim As Integer runLen = bytes(nBytePos)
If (runLen And &B11000000) = &B11000000 Then
runLen And= &B00111111
nBytePos += 1
Else
runLen = 1
End If

palbyte = bytes(nBytePos)

Dim As Integer ResultX = BmpX + runLen
Dim As Integer end_ = ResultX - 1
If end_ > pImg.widM Then end_ = pImg.widM

For BmpX = BmpX To end_
pix[BmpX] = palbyte
Next
BmpX = ResultX

nBytePos += 1

Loop While BmpX < cScanBytes

If nBytePos >= Ubound(bytes) Then
Exit For
Endif

Next Y

For Y As Integer = 0 To pImg.hgtM
Dim As RGBQUAD Ptr  dst = pImg.pixels + y * pImg.pitch
Dim As Uinteger Ptr udst = dst
For X As Integer = 0 To pImg.widM
Dim As Ubyte c_ = dst[x].Blu
dst[x].red = Pal(c_).red
dst[x].grn = Pal(c_).grn
dst[x].blu = Pal(c_).blu
Next
Next
End Sub

Sub LoadPCX(Byref fileName As String,Byref pImg As ImageInfo)

If Lcase(Right(filename,4)) <> ".pcx" Then filename += ".PCX"

'' http://planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=2303&lngWId=1

Dim nFreeFile As Integer
Dim hPCX As PCXHeader

nFreeFile = Freefile
Open Filename For Binary Lock Write As #nFreeFile

Seek #nFreeFile, 1
Get #nFreeFile, , hPCX
Close #nFreeFile

If hPCX.BitsPerPlane = 8 Then
If hPCX.colorPlanes = 1 Then
Read8Bit(Filename,pImg)
Elseif hPCX.colorPlanes = 3 Then
Read24Bit(Filename,pImg)
End If
Else
? "Sorry, can't load that pcx file!"
End If

End Sub


'' ------------
'   Main
' -------------

Screenres 320,240,32

Dim As ImageInfo  Buf

LoadPCX("test.pcx", Buf)
Put (110,80),Buf.img, Pset

Sleep

Скачать