Qbasicnews.com

Full Version: I need code to copy a 16bit screen to bmp file
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
here is what i have so far. I am copying as 800x600x24 from 800x600x16, since (my) Paint can't handle 16bit for some reason. I'll convert the colors later, but right now I just want it functioning..

Code:
SUB output.bitmap

OPEN "C:\qbasic\test1.bmp" FOR BINARY AS 1
n$ = "BM": PUT #1, , n$
n& = xRes: n& = n& * yRes: n& = n& + 54: PUT #1, , n&
n% = 0: PUT #1, , n%
n% = 0: PUT #1, , n%
n% = 54: PUT #1, , n%
n& = xRes: PUT #1, , n&
n& = yRes: PUT #1, , n&
n% = 1: PUT #1, , n%
n% = 24: PUT #1, , n%
n% = 0: PUT #1, , n%
n% = 54: PUT #1, , n%

n$ = SPACE$(xRes * 3)

FOR y% = yRes TO 1 STEP -1
x2% = 0
FOR x% = 1 TO xRes
x2% = x2% + 3
temp1& = uglPGet(map, x%, y%)
temp2& = temp1& MOD 4096
temp1& = (temp1& - temp2&) / 4096
temp3& = temp2& MOD 32
temp2& = (temp2& - temp3&) / 32
MID$(n$, x2% - 2, 1) = trim$(STR$(temp1&))
MID$(n$, x2% - 1, 1) = trim$(STR$(temp2&))
MID$(n$, x2%, 1) = trim$(STR$(temp3&))
NEXT x%
PUT #1, , n$
NEXT y%
CLOSE
END SUB
AFAIK, BMP doesn't support 16/15 bits pictures, just 24.

Anyhow, 16 bits mode have 5 bits for red, 6 bits for green, 5 bits for blue. The formula is...

Code:
red16% = red24% \ 8
green16% = green24% \ 4
blue16% = blue24% \ 8

byte1% = red16%*8 + green16% \ 8
byte2% = (green16% AND 7) * 32 + blue16%

wrd$ = chr$(byte1%)+chr$(byte2%)
put #file%, , wrd$

The resulting BMP won't be a valid BMP, though.
Quote:AFAIK, BMP doesn't support 16/15 bits pictures, just 24.
Yes it does actually, it's just not supported very much, i believe a few programs will save it in 16 bit like photoshop, but even ms paint does not support it (well it will load it, just not save it)
So you're trying to save a 16 bit screen to a 24 bit bitmap? Wouldn't that mean he needs a 16->24 converter, not a 24->16 converter guys?

Here, just assemble this to a library, or add it to whatever lib your using and reassemble it. I wrote it for my GUI/2D graphics lib.

Code:
; declare sub convert16To24 (byval numPixels%, byval srcSegment%, byval srcOffset%, byval destSegment%, byval destOffset%)
public convert16To24
convert16To24 proc

  push bp
  mov  bp, sp
  push ds
  mov  cx, [bp+14]
  mov  ds, [bp+12]
  mov  si, [bp+10]
  mov  es, [bp+8]
  mov  di, [bp+6]

  c16to24Loop:

    mov  bl, 31
    mov  bh, 255
    mov  al, [si]
    and  al, bl
    mul  bh
    div  bl
    mov  es:[di], al
    mov  bl, 63
    mov  ax, [si]
    shr  ax, 5
    and  al, bl
    mul  bh
    div  bl
    mov  es:[di+1], al
    mov  bl, 31
    mov  al, [si+1]
    shr  al, 3
    and  al, bl
    mul  bh
    div  bl
    mov  es:[di+2], al

    add  si, 2
    cmp  si, 16
    jb   short @F
      sub  si, 16
      mov  ax, ds
      inc  ax
      mov  ds, ax
    @@:

    add  di, 3
    cmp  di, 16
    jb   short @F
      sub  di, 16
      mov  ax, es
      inc  ax
      mov  es, ax
    @@:

    dec  cx
  jnz  short c16to24Loop

  pop  ds
  pop  bp
  ret  10

convert16To24 endp

Or if you want qbasic code, this is untested (I'm writing it just now), but it should work:
Code:
' assuming pixel16% contains 16 bit pixel to convert

blue% = pixel16% AND 31
green% = (pixel16% \ 32) AND 63

' Make sure the sign bit doesn't mess things up:
unsignedPixel16& = 0
unsignedPixel16& = unsignedPixel16& OR pixel16%

red% = (unsignedPixel16& \ 2048) AND 31

' blue currently ranges from 0 to 31, so we scale it up to 0 though 255:
blue% = (blue% * 255) \ 31
' simple bitshifting here would be faster, but would also have a
' darkening effect, as it inserts blanks bits

' ditto for green, which is 6 bit (0 to 63)
green% = (green% * 255) \ 63

' and red is 5 bit:
red% = (red% * 255) \ 31

' Are BMPs blue-green-red, or red-green-blue? (goes to wotsit.org to refresh memory)... ah, red-green-blue

bytesToWriteToFile$ = CHR$(red%) + CHR$(green%) + CHR$(blue%)

PUT #BmpFile, , bytesToWriteToFile$

Or, if you're using Future.Library, which keeps red, green, and blue in separate bytes even in 16 bit mode:
Code:
' pixel16& assumed to contain color returned by Future.POINT&,
' rgb2Color&, or some other Future function in a 16 bit mode

blue% = pixel16& AND 31
green% = (pixel16& \ &H100) AND 63
red% = (pixel16& \ &H10000) AND 31

(and then scale them up a write them to the file as in the previous example)

And, as to the BMP format, YPI's 8 bit bmp saver could be adapted to save from 16 bit to 24 bit. Just change to number of bits feild from 8 to 24, remove the code that writes out the palette, then put in one of the 3 converters.
Thanks, but that is unnecessary.

I need code for the header, not the conversion.
Ok then. check out YPI. There are are several bmp loaders and savers, all written in qbasic. If you want bmp file format reference reference, go to http://www.wotsit.org/ - they've got documentation for lots of different file formats.
none of them are 16 bit and they use INP stuff. This is the part that I really really would like: the palette (after ClrImportant). What the hell should I do there for a regular palette?

This is what he does for 4bit screen 12:

Code:
FOR Colors = 0 TO 15
   OUT &H3C6, &HFF
   OUT &H3C7, Colors
   AllColorz$ = AllColorz$ + CHR$(INP(&H3C9) * 4) + CHR$(INP(&H3C9) * 4) +
   CHR$(INP(&H3C9) * 4) + CHR$(0)
NEXT Colors
PUT #255, , AllColorz$: AllColorz$ = ""

IF (WindowsBMPInfoHeader.Widthz MOD 2) = 1 THEN
   WindowsBMPInfoHeader.Widthz = WindowsBMPInfoHeader.Widthz + 1
END IF

IF (4 - ((WindowsBMPInfoHeader.Widthz MOD 8) \ 2)) <> 4 THEN
   Padding$ = SPACE$((4 - ((WindowsBMPInfoHeader.Widthz MOD 8) \ 2)))
END IF
You don't included a palette when it's a 24 bit bitmap.
why is the

OUT &H3C6, &HFF

inside the FOR/NEXT loop? It isn't going to change. (It's also the default value. Unless some program explicitly changed the value at that register (the "pelmask register"), FFh is the value that's going to be there since boot-up/power-on.) More importantly, though, if you're using a bit depth higher than 8, I don't see how the value at 3C6h could possibly matter. It only affects *attributes*, i.e., values that serve as indices into the palette registers, and 15, 16, 24, and 32-bit video modes don't use the palette registers.
tell me then why my sub doesn't work as it should. I updated the code (first message) with what I am using now.

It does save as a bmp 1.37 megs of data but Paint gives an error.
Pages: 1 2