Hi,
This is the first working code of this little app. If you don't know what's its use, I tell you Xpm is an image format coded in ASCII, used widely in Linux and not so widely in Windows. The code should work in Linux, but I'm sure it won't. Anyway, I can't get CompilerIf #OS#Windows to work, it's commented in the code.
Feel free to suggest changes, optimizations, etc. Note that it will doesn't check XPM validity, so a crash may happen if your XPM file is malformed. It doesn't support named colors, but it does recognize and handle 48 bit codes (I don't understand why do they use them sometimes). It does not support compressed BMP formats.
I think 16 bpp Xpm files should be loaded as 24 bit so not to lose quality (and give after the posibility of saving as 16 bpp or 24). Well, feedback is welcome.
Code: Select all
; XpmTool Lite v. 0.9
; Xpm viewer/converter to Bmp
; written in PureBasic by El_Choni
; TODO: xpm2ico, bmp2xpm, ico2xpm, load Bmp from memory to view, stretch Bmp, multiple windows, optimizations (maybe a lib)
Structure ImageData
width.l
height.l
colors.l
chars.l
bits.b
EndStructure
#BI_RGB = 0
;CompilerIf #OS #Windows
; Structure BITMAPFILEHEADERX
; bfType.w
; bfSize.l
; bfReserved1.w
; bfReserved2.w
; bfOffBits.l
; EndStructure
; Structure BITMAPINFOHEADERX
; biSize.l
; biWidth.l
; biHeight.l
; biPlanes.w
; biBitCount.w
; biCompression.l
; biSizeImage.l
; biXPelsPerMeter.l
; biYPelsPerMeter.l
; biClrUsed.l
; biClrImportant.l
; EndStructure
;CompilerEndIf
BmpFile.BITMAPFILEHEADER
BmpInfo.BITMAPINFOHEADER
BmpFileName.s
extension.s
XpmData.ImageData
XpmFile.s
pkb.b
ch.s
chcomp.s
bit.b
position.f
md.f
dpad.f
Procedure Mod(dividend.l, divisor.l)
If divisor0
integerquotient = dividend/divisor
remainder = dividend-(integerquotient*divisor)
Else
remainder = 0
EndIf
ProcedureReturn remainder
EndProcedure
Procedure Hex2Num(hexa.s, flag16.b)
If Len(hexa)=12
hexa = Mid(hexa, 1, 2)+Mid(hexa, 5, 2)+Mid(hexa, 9, 2)
EndIf
num = 0
For i = 1 To 5 Step 2
hexcode1 = Asc(Mid(hexa, i, 1)) - 48
If hexcode1>48
hexcode1-39
Else
If hexcode1>16
hexcode1-7
EndIf
EndIf
hexcode2 = Asc(Mid(hexa, i+1, 1)) - 48
If hexcode2>48
hexcode2-39
Else
If hexcode2>16
hexcode2-7
EndIf
EndIf
If flag16 = 16
hexcode = (hexcode1 > 3
hexcode 0
XpmFile = ProgramParameter()
If Len(XpmFile)>0
extension.s = Right(XpmFile, 4)
If extension = ".xpm" Or extension = ".XPM"
Gosub ProcessFile
Gosub ShowImage
EndIf
Else
Files = 0
EndIf
Wend
Repeat
EventID.l = WaitWindowEvent()
Select EventID
Case #PB_EventMenu
Select EventMenuID()
Case 0 ; Open
XpmFile = OpenFileRequester("Open file","","Xpm files (*.xpm)|*.xpm", 0)
If Len(XpmFile)>0
extension.s = Right(XpmFile, 4)
If extension = ".xpm" Or extension = ".XPM"
Gosub ProcessFile
Gosub ShowImage
EndIf
EndIf
Case 1 ; Quit
Quit = 1
Case 2 ; About
If OpenWindow(1, WindowX()+64, WindowY()+32, 320, 96, #PB_Window_SystemMenu, "About XpmTool Lite")
If CreateGadgetList(WindowID())
TextGadget(0, 5, 5, WindowWidth()-10, WindowHeight()-10, "XpmTool Lite v. 0.9"+Chr(10)+"View and convert between Xpm and Bmp files."+Chr(10)+"Written in PureBasic by El_Choni")
EndIf
EndIf
EndSelect
Case #PB_EventCloseWindow
If EventWindowID() = 0
Quit = 1
Else
CloseWindow(1)
EndIf
Case #PB_EventRepaint
If loaded
UseWindow(0)
StartDrawing(WindowOutput())
DrawImage(UseImage(0), 4, 4)
StopDrawing()
EndIf
EndSelect
Until Quit = 1
EndIf
End
ProcessFile:
If ReadFile(0, XpmFile)
FileSize = FileSize(XpmFile)
Buffer = AllocateMemory(0, FileSize, 0)
ReadData(Buffer, FileSize)
CloseFile(0)
Seeker = Buffer
While PeekB(Seeker)34
Seeker+1
Wend
Seeker+1
; Header data
XpmHeader = Seeker
stop = 0
While stop = 0
pkb = PeekB(Seeker)
If pkb=32 Or pkb=9
Seeker+1
Else
stop = 1
EndIf
Wend
For n = 0 To 3
Anchor = Seeker
stop = 0
While stop = 0
pkb = PeekB(Seeker)
If pkb32 And pkb9 And pkb34
Seeker+1
Else
stop = 1
EndIf
Wend
PokeB(Seeker, 0)
PokeL(@XpmData+(n*4), Val(PeekS(Anchor)))
PokeB(Seeker, pkb)
stop = 0
If n32 And pkb9
stop = 1
Else
Seeker+1
EndIf
Wend
EndIf
Next n
If loaded
FreeImage(0)
EndIf
Seeker+1
While PeekB(Seeker) 34
Seeker+1
Wend
While PeekB(Seeker) 34
Seeker+1
Wend
Seeker+1
XpmPalette = Seeker
Codes = AllocateMemory(1, XpmData\colors*XpmData\chars, 0)
Palette = AllocateMemory(2, XpmData\colors*4, 0)
If XpmData\colors>2)>2)>2)32 And pkb9 And pkb34
Seeker+1
Else
PokeB(Seeker, 0)
ch = PeekS(Anchor)
PokeB(Seeker, pkb)
stop = 1
EndIf
Wend
PokeL(Palette+((colors-1)*4), Hex2Num(ch, XpmData\bits))
EndIf
For n = 0 To 1
While PeekB(Seeker)34
Seeker+1
Wend
Seeker+1
Next n
Next colors
; Image data
XpmImageData = Seeker
md = XpmData\bits/8
Raw = AllocateMemory(3, XpmData\width*XpmData\height*md+(XpmData\height*dpad), 0)
For rows = 1 To XpmData\height
For cols = 1 To XpmData\width
ch = ""
For n = 1 To XpmData\chars
ch = ch + Chr(PeekB(Seeker+n-1))
Next n
For t = 1 To XpmData\colors
chcomp = ""
For j = 1 To XpmData\chars
chcomp = chcomp + Chr(PeekB(Codes+((t-1)*XpmData\chars)+(j-1)))
Next j
If chcomp = ch
position = ((XpmData\height-rows)*XpmData\width)+(cols-1)
Select XpmData\bits
Case 1
pad = Round((position+((XpmData\height-rows)*dpad*8))/8, 0)
If (t-1)>0
longbyte = $80
For n = 1 To Mod(cols+7, 8)
longbyte = longbyte >> 1
Next n
longbyte | PeekB(Raw+pad)
PokeB(Raw+pad, longbyte)
EndIf
Case 4
pad = Round((position/2)+((XpmData\height-rows)*dpad), 0)
If Mod(cols, 2)
PokeB(Raw+pad, (t-1)*16)
Else
PokeB(Raw+pad, PeekB(Raw+pad)|(t-1));
EndIf
Case 8
PokeB(Raw+position+((XpmData\height-rows)*pad), t-1)
Case 16
PokeW(Raw+(position*2)+((XpmData\height-rows)*pad), PeekW(Palette+((t-1)*4)))
Case 24
PokeL(Raw+(position*3)+((XpmData\height-rows)*pad), PeekL(Palette+((t-1)*4)))
Case 32
PokeL(Raw+(position*4), PeekL(Palette+((t-1)*4)))
EndSelect
t = XpmData\colors
EndIf
Next t
Seeker+XpmData\chars
Next cols
If PeekB(Seeker) = 34
Seeker+1
If rows34
Seeker+1
Wend
Seeker+1
EndIf
EndIf
Next rows
FreeMemory(0)
FreeMemory(1)
; Bmp creating
BmpFile\bfType = 19778
If XpmData\bits>8
RGBQuad = 0
Else
RGBQuad = (XpmData\colors*4)
EndIf
BmpFile\bfOffBits = SizeOf(BITMAPFILEHEADER)+SizeOf(BITMAPINFOHEADER)+RGBQuad+2
BmpFile\bfSize = BmpFile\bfOffBits+(XpmData\width*XpmData\height*md+(XpmData\height*dpad))
BmpFile\bfReserved1 = 0
BmpFile\bfReserved2 = 0
BmpInfo\biSize = SizeOf(BITMAPINFOHEADER)
BmpInfo\biWidth = XpmData\width
BmpInfo\biHeight = XpmData\height
BmpInfo\biPlanes = 1
BmpInfo\biBitCount = XpmData\bits
BmpInfo\biCompression = #BI_RGB; Currently supports only uncompressed images
If BmpInfo\biBitCount c #9EFEA2",
", c #FEC6BE",
"' c #B2E6BA",
") c #CEE6D6",
"! c #FE7662",
"~ c #223A4E",
"{ c #DEDEDE",
"] c #E2E2E2",
"^ c #E2E6E6",
"/ c #0ACA1A",
"( c #4E6AB2",
"_ c #264A5A",
": c #DAFEDA",
". c #FEAEA6",
",. c #465A9E",
"'. c #8AFE8A",
"). c #FEFEFE",
"!. c #3EFE42",
"~. c #E2FEE2",
"{. c #AAFEAE",
"]. c #566EBE",
"^. c #FEA296",
"/. c #121A2A",
"(. c #3A4A82",
"_. c #2E3A66",
":. c #364676",
"+ c #FE5A46",
",+ c #FE9286",
"'+ c #0ACE22",
")+ c #C6FECA",
"!+ c #0ED226",
" (.E.L V B.K.d.i |.|.|.|.|.|.|.|.",
" u (.E.v.V ( K.q.i I |.|.|.|.|.|.",
" q :.t.E.,. | ;.I.H ).).",
").).).`.5 ).).W h ).t `.J j a g #+& ).).).).).).$+).).).0.: ).).",
").).).U o.).).b.=.,+=.a r o.[.& ).5.6 ).).).).).9 S )+F.I.H ).).",
").).).).n.).).).f c f ).).`.h n.).z U ).).).).).` -+* G.@+).).).",
").).).).).).).).).).).).).).).).).).).).).).).).e n n > n ).).).",
").).).).).).).).).).).).).).).).).).).).).).).).e > n U.B ).).).",
").).).).).).).).).).).).).).).).).).).).).).).).).).).).* ~.).).",
").).).).).).).).).).).).).).).).).).).).).).).).e > n > > > R ).).).",
").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).",
").).).).).).).).).).).).).).).).).).).).).).).).).).).).).).).)."};
El_Choni
Edited by - EL_Choni on 12 March 2002 01:47:44
Edited by - EL_Choni on 12 March 2002 01:51:34