ReadWrite Bit maps
Blitz3D Forums/Blitz3D Programming/ReadWrite Bit maps
| ||
I'm having a problem in trying to convert between bitmap images (where pixel status is only considered 0 or 1) and banks. The issue seems to be specifically particular with trying to write the Image data to a bank. I have functions which can read/write accurately from the banks unsing ReadBytes and WriteBytes, so the problem can only be in writing to the banks byte by byte is different somehow (Or I'm missing something glaringly obvious). The Read/WriteBytes theoretically should simply write bytes in sequence, and I believe this does so in 8 bit bytes regardless. This would most likely be related as Isuspect that the Endian of long bytes may cause the sequence to be reversed... Here's a sample of code that highlights the issue: Graphics 1024,768,32 Const SPRITE_MAX=255 Const UNIT_RESOLUTION=8 Const SPR_BIT_DEPTH=8 ;1-8 Sprite Ref : Eight Bits ;Maximum ;9-10 Frames : Two Bits ;0 or 3 Units should never be used, so +1 to raw data ;11-12 Width : Two Bits ;in UNITs - 0 or 3 Units should never be used, so +1 to raw data ;13-14 Height : Two Bits ;in UNITs - 0 or 3 Units should never be used, so +1 to raw data ;15 Reversal : One Bit ;if Reverse direction requires additional animation frames Const SPR_FRAMECOUNT_BYTE_OFFSET=9 Const SPR_FRAMECOUNT_BIT_DEPTH=2 Const SPR_DIMENSIONW_BYTE_OFFSET=11 Const SPR_DIMENSIONW_BIT_DEPTH=2 Const SPR_DIMENSIONH_BYTE_OFFSET=13 Const SPR_DIMENSIONH_BIT_DEPTH=2 Const SPR_ALTREVERSE_BYTE_OFFSET=15 ;Whether reverse Direction has separate animations Const SPR_ALTREVERSE_BIT_DEPTH=1 Const MAX_FRAMES=4 Const Root$="C:\Users\A User\Documents\Some Directory\" Type SPRITE Field Reference Field Frames Field FrameBank[MAX_FRAMES] Field Width Field Height Field Reversal End Type Global Count MakeSpriteData Function MakeSpriteData() CountSprites WriteSprites End Function Function CountSprites() Count=0 Local Directory=ReadDir(Root) Local File$ Local Path$ File=NextFile(Directory) While (File<>"") Path$=Root+File If (FileType(Path)=1) If (Right(File,3)="bmp") Count=Count+1 End If End If File=NextFile(Directory) Wend CloseDir Directory If (Count>SPRITE_MAX) Count=SPRITE_MAX End If End Function Function WriteSprites() Local Directory=ReadDir(Root) Local File$=NextFile(Directory) Local Path$ Local Stream=WriteFile(Root+"Default.spr") WriteByte(Stream,Count) Local counter=0 While (File<>"") And (counter<=Count) Path$=Root+File If (FileType(Path)=1) If (Right(File,3)="bmp") counter=counter+1 ProcessSpriteFile(Path,Stream) End If End If File=NextFile(Directory) Wend CloseFile Stream CloseDir Directory End Function Function ProcessSpriteFile(Path$,Stream) Local Bank Local S.SPRITE S=ReadSprite(Path) WriteSprite(Stream,S) For Bank=1 To S\Frames FreeBank S\FrameBank[Bank-1] Next Delete S End Function Function ReadSprite.SPRITE(Path$) Local Name$=GetName(Path) Local Flags=GetFlags(Name) Local S.SPRITE=New SPRITE S\Reference=Int(Left(Name,Instr(Name," ")-1)) S\Width=Left(Str(Flags),1) S\Height=Mid(Str(Flags),2,1) S\Frames=Mid(Str(Flags),3,1) S\Reversal=Int(Right(Str(Flags),1)) Local Frame Local Bank Local Byte Local Buffer Local Image=LoadAnimImage(Path,S\Width*UNIT_RESOLUTION,S\Height*UNIT_RESOLUTION,0,S\Frames) For Frame=1 To S\Frames Bank=CreateBank(S\Width*S\Height*UNIT_RESOLUTION) Byte=BankSize(Bank) S\FrameBank[Frame-1]=Bank BufferToBank(S,ImageBuffer(Image,Frame-1),Bank,S\Width,S\Height) Next FreeImage Image Return S End Function Function WriteSprite(Stream,S.SPRITE) WriteSpriteToFile(S,Stream) End Function Function BufferToBank(S.SPRITE,Buffer,Bank,Width,Height) LockBuffer Buffer Local X Local Y Local n Local W=Width*UNIT_RESOLUTION Local H=Height*UNIT_RESOLUTION Local Byte Local Pixel For Y=0 To H-1 Byte=0 For X=0 To W-1 Step UNIT_RESOLUTION Pixel=( ReadPixelFast(X+n,Y,Buffer)) If (Pixel=-1) Byte=Byte+(1 Shl n) End If PokeFrameLine(S,Bank,Y,Byte) Next Next UnlockBuffer Buffer End Function Function GetName$(Path$) Return Right(Path,Len(Path)-Len(TrimPath(Path))) End Function Function TrimPath$(FilePath$) If (FilePath<>"") If (((Right(FilePath,1)=".") Or (Right(FilePath,1)="\") Or (Right(FilePath,1)="/"))) Return FilePath End If Local Count Local Char$ Local Length=Len(FilePath) For Count=Length To 1 Step -1 Char=Mid(FilePath,Count,1) If (Char="\") Exit End If Next Return Left(FilePath,Count) End If End Function Function GetFlags(Name$) Local ReferenceEnd=Instr(Name," ") Return Int(Mid(Name,ReferenceEnd+1,4)) End Function Function PokeFrameLine(S.SPRITE,bank,Y,Byte) Select S\Width Case 1: PokeByte bank,Y,Byte Case 2: PokeShort bank,Y*2,Byte Case 4: PokeInt bank,Y*4,Byte Default: RuntimeError "Invalid runlength request: "+S\Width End Select End Function Function WriteSpriteToFile(S.SPRITE,Stream) Local UnitWidth=S\Width Local BitwiseWidth=(UnitWidth Shr True) Local ByteValueWidth=BitwiseWidth Shl (SPR_DIMENSIONW_BYTE_OFFSET-1) Local UnitHeight=S\Height Local BitwiseHeight=(UnitHeight Shr True) Local ByteValueHeight=BitwiseHeight Shl (SPR_DIMENSIONH_BYTE_OFFSET-1) Local Frames=S\Frames Local BitwiseFrames=(S\Frames Shr True) Local ByteValueFrames=BitwiseFrames Shl (SPR_FRAMECOUNT_BYTE_OFFSET-1) Local Reversal=S\Reversal Shl (SPR_ALTREVERSE_BYTE_OFFSET-1) WriteShort Stream,S\Reference+ByteValueWidth+ByteValueHeight+ByteValueFrames+Reversal Local Frame Local Bank Local Byte For Frame=1 To Frames Bank=S\FrameBank[Frame-1] Byte=BankSize(Bank) WriteBytes(Bank,Stream,0,Byte) Next End Function Otherwise, when NOT trying to onvert between image files, the Banks can be read and written perfectly with the following: Function WriteSpritesToFile() ChangeDir DATA_STORE_PATH Local Path$=DATA_STORE_PATH+MRU_SPRITEFILE+".spr" Local Stream=WriteFile(Path) Local S.SPRITE Local Iter WriteByte Stream,SPRITE_COUNT ; For Iter=0 To SPRITE_COUNT ; S=Object.SPRITE(SPRITES[Iter]) For S=Each SPRITE If (S<>Null) WriteSpriteToFile(S,Stream) End If Next ; Next CloseFile Stream Local Message$=WRITEFAILUREMESSAGE If (FileType(Path)=1) If (FileSize(Path)) Message$=WRITESUCCESSMESSAGE End If End If Notify Message End Function Function WriteSpriteToFile(S.SPRITE,Stream) Local UnitWidth=S\Width Local BitwiseWidth=(UnitWidth Shr True) Local ByteValueWidth=BitwiseWidth Shl (SPR_DIMENSIONW_BYTE_OFFSET-1) Local UnitHeight=S\Height Local BitwiseHeight=(UnitHeight Shr True) Local ByteValueHeight=BitwiseHeight Shl (SPR_DIMENSIONH_BYTE_OFFSET-1) Local Frames=S\Frames Local BitwiseFrames=(S\Frames Shr True) Local ByteValueFrames=BitwiseFrames Shl (SPR_FRAMECOUNT_BYTE_OFFSET-1) Local Reversal=S\Reversal Shl (SPR_ALTREVERSE_BYTE_OFFSET-1) WriteShort Stream,S\Reference+ByteValueWidth+ByteValueHeight+ByteValueFrames+Reversal Local Frame Local Bank Local Byte For Frame=1 To Frames Bank=S\FrameBank[Frame-1] Byte=BankSize(Bank) WriteBytes(Bank,Stream,0,Byte) Next End Function Function ImportSpriteFile(FilePath$) Local Stream=ReadFile(FilePath) If (Stream) Local Path$=TrimPath(FilePath) Local Name$=Right(FilePath,Len(FilePath)-Len(Path)) MRU_SPRITEFILE=Left(Name,Len(Name)-4) GetSpritesDataFromStream(Stream) CloseFile Stream End If End Function Function GetSpritesDataFromStream(Stream) SPRITE_COUNT=ReadByte(Stream) GetSpritesFromStream(Stream) End Function Function GetSpritesFromStream(Stream) Local Count For Count=0 To SPRITE_COUNT GetSpriteDataFromStream(Stream) Next End Function Function GetSpriteDataFromStream(Stream) Local S.SPRITE=New SPRITE Local Byte=ReadShort(Stream) S\Reference=GetSpriteReferenceFromByte(Byte) SPRITES[S\Reference]=Handle(S) S\Width=GetFrameWidthUnitsFromByte(Byte) S\Height=GetFrameHeightUnitsFromByte(Byte) S\Frames=GetFramesFromByte(Byte) S\Reversal=GetReversalFlagFromByte(Byte) SetSpriteBanksFromStream(S,Stream) End Function Function SetSpriteBanksFromStream(S.SPRITE,Stream) Local Frame Local Bank Local Byte For Frame=1 To S\Frames Bank=CreateBank(S\Width*S\Height*UNIT_RESOLUTION) Byte=BankSize(Bank) ReadBytes(Bank,Stream,0,Byte) S\FrameBank[Frame-1]=Bank Next End Function |
| ||
The issue seems to be specifically particular with trying to write the Image data to a bank. Just reading the code, not trying to run it... Writing image data to bank seems to be the BufferToBank function, which contains For X=0 To W-1 Step UNIT_RESOLUTION Pixel=( ReadPixelFast(X+n,Y,Buffer)) If (Pixel=-1) Byte=Byte+(1 Shl n) End If PokeFrameLine(S,Bank,Y,Byte) Next using n as an offset. But n never changes, is always the inital value of zero. |