Author Topic: How to read the first 4 bits of the byte?  (Read 4975 times)

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
How to read the first 4 bits of the byte?
« on: October 08, 2018, 05:32:14 am »
Hello. As you've surely noticed, I'm not a big friend with bit logical operators AND, XOR and OR. But because I want to get on, I need to thoroughly understand how to get the first 4 bits, or just the last bit of the byte, because the conversion to the string is too slow. Moving back from binary form makes VAL, that's no problem.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: How to read the first 4 bits of the byte?
« Reply #1 on: October 08, 2018, 05:52:30 am »
AND 15 is probably what you're looking for.

00001111 -- last 4 bits would be a total of 15 (decimal).

So let's tak a number like 34.... In binary it'd be: 00100010.

00100010
00001111    AND
-----------
00000010

Result would be 2 -- the last 4 bits of that byte.

************

First 4 would be AND &B11110000  (128 + 64 + 32 + 16..  240).  AND 240

If you're not good at converting, just us &B and type the values directly in binary.  In many cases, I find, it keeps it simple and help preserves the intent of the code nicely.
« Last Edit: October 08, 2018, 05:57:09 am by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: How to read the first 4 bits of the byte?
« Reply #2 on: October 08, 2018, 06:10:17 am »
Exactly it is how to take (quick) the first 4 bits of one byte and the first 4 bits of the second byte, fold a new byte, and then write this byte. I use this to store bitmap in 2/16 colors in the following code, but it is ugly slow:



Code: QB64: [Select]
  1.  
  2.  
  3. imb = _NEWIMAGE(2048, 1024, 256)
  4. _DEST imb
  5. CLS , 14
  6. LINE (100, 100)-(1948, 924), 1, BF
  7. CIRCLE (1024, 512), 150, 0
  8.  
  9.  
  10. Save_BMP imb, "test16.bmp", 2  : REM 0 = 32 bit, 1 = 8 bit, 2 = 4 bit, 3 = 1 bit
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19. SUB Save_BMP (src AS LONG, file AS STRING, typ AS _UNSIGNED _BYTE) 'typ: 0 = 32 bit, 1 = 256 colors, 2 = 16 colors, 3 = 2 colors   PRO KONVERZI NEJPRVE DITHERINGEM UDELEJ 256 clr zdroj a ten uloz. NELZE ulozit primo 32 bit do 8 bit!
  20.     'moje save formule
  21.  
  22.     TYPE BMP_H
  23.         ID AS STRING * 2 'BM                                  a
  24.         Size AS LONG 'celkova velikost souboru
  25.         Reserved0 AS INTEGER '0                               a
  26.         Reserved1 AS INTEGER '0                               a
  27.         Data_Start AS LONG ' startovni oblast dat obrazu. U 32 bitu to je hned po hlave, u ostatnich az po 54 + oblast palety - protoze tahle hlava ma 14, nasleduje druha hlava, ktera ma 40 bytu
  28.     END TYPE
  29.  
  30.     TYPE BMP_I
  31.         Hlava_velikost AS LONG '40                            a
  32.         width AS LONG
  33.         height AS LONG
  34.         planes AS INTEGER '1                                  a
  35.         BPP AS INTEGER '1/4/8/24/32
  36.         Compress AS LONG '0/1/2                               a
  37.         Image_Size AS LONG ' dam nulu                         a
  38.         Xpels AS LONG '0                                      a
  39.         Ypels AS LONG '0                                      a
  40.         Total_Colors AS LONG 'muze byt 0    (0, 256, 16, 2)
  41.         Important_Colors AS LONG '0                           a
  42.     END TYPE
  43.  
  44.     DIM H AS BMP_H
  45.     DIM I AS BMP_I
  46.  
  47.  
  48.     H.Size = (_WIDTH(src) * _HEIGHT(src) * 4) + 54: I.height = _HEIGHT(src): I.width = _WIDTH(src)
  49.     SELECT CASE typ
  50.  
  51.         CASE 0: DIM IM(_WIDTH(src) * _HEIGHT(src) - 1) AS _UNSIGNED LONG
  52.             I.BPP = 32: I.Total_Colors = 0: Depth = 4 '                        32  bit
  53.  
  54.  
  55.         CASE 1: DIM IM2(_WIDTH(src) * _HEIGHT(src) - 1) AS _UNSIGNED _BYTE
  56.             I.BPP = 8: I.Total_Colors = 0: Depth = 1 '                         256 clrs
  57.  
  58.  
  59.  
  60.         CASE 2: DIM IM3((_WIDTH(src) * _HEIGHT(src) - 1) / 2) AS _UNSIGNED _BYTE
  61.             I.BPP = 4: I.Total_Colors = 0: Depth = 1 '                         16  clrs
  62.  
  63.         CASE 3: DIM IM4((_WIDTH(src) * _HEIGHT(src) - 1) / 8) AS _UNSIGNED _BYTE
  64.             I.BPP = 1: I.Total_Colors = 0: Depth = 1 '                         2   clrs
  65.  
  66.  
  67.     END SELECT
  68.  
  69.     H.ID = "BM": H.Reserved0 = 0: H.Reserved1 = 0: I.Hlava_velikost = 40: I.planes = 1: I.Compress = 0: I.Image_Size = 0: I.Xpels = 0: I.Ypels = 0: I.Important_Colors = 0
  70.     DIM M AS _MEM, N AS _MEM
  71.     M = _MEMIMAGE(src)
  72.  
  73.  
  74.     N = _MEMNEW(I.width * I.height * Depth) 'oblast pameti, kde se bude otacet Y
  75.  
  76.     FOR y = (_HEIGHT(src)) - 1 TO 0 STEP -1
  77.         FOR x = 0 TO (_WIDTH(src) - 1)
  78.             SELECT CASE typ
  79.                 CASE 0
  80.                     _MEMGET M, M.OFFSET + o, v
  81.                     _MEMPUT N, N.OFFSET + in(x, y, src&), v
  82.                     o = o + 4
  83.                 CASE 1
  84.                     _MEMGET M, M.OFFSET + o, v2
  85.                     _MEMPUT N, N.OFFSET + in(x, y, src&), v2
  86.                     o = o + 1
  87.                 CASE 2
  88.                     _MEMGET M, M.OFFSET + o, v2
  89.                     uk = uk + 1
  90.                     binar$ = binar$ + RIGHT$(DECtoBIN$(v2), 4)
  91.                     IF uk MOD 2 = 0 THEN
  92.                         IM3(index) = BINtoDEC(binar$)
  93.                         binar$ = ""
  94.                         index = index + 1
  95.                         uk = 0
  96.                     END IF
  97.                     o = o + 1
  98.  
  99.                 CASE 3
  100.                     _MEMGET M, M.OFFSET + o, v2
  101.                     uk = uk + 1
  102.                     binar$ = binar$ + RIGHT$(DECtoBIN$(v2), 1)
  103.                     IF uk MOD 8 = 0 THEN
  104.                         IM4(index) = BINtoDEC(binar$)
  105.                         binar$ = ""
  106.                         index = index + 1
  107.                         uk = 0
  108.                     END IF
  109.                     o = o + 1
  110.             END SELECT
  111.     NEXT x, y
  112.  
  113.  
  114.  
  115.  
  116.     SELECT CASE typ
  117.         CASE 0
  118.             _MEMFREE M
  119.             _MEMGET N, N.OFFSET, IM()
  120.             _MEMFREE N
  121.         CASE 1
  122.             _MEMFREE M
  123.             _MEMGET N, N.OFFSET, IM2()
  124.             _MEMFREE N
  125.         CASE 2, 3
  126.             _MEMFREE M
  127.             _MEMFREE N
  128.     END SELECT
  129.  
  130.  
  131.  
  132.  
  133.  
  134.     ch = FREEFILE
  135.     OPEN file FOR OUTPUT AS #ch: CLOSE #ch: OPEN file FOR BINARY AS #ch
  136.     PUT #ch, , H
  137.     PUT #ch, , I
  138.     SELECT CASE typ
  139.         CASE 0: PUT #ch, , IM()
  140.         CASE 1:
  141.             FOR Palete = 0 TO 255
  142.                 v = _PALETTECOLOR(Palete, src&)
  143.                 PUT #ch, , v
  144.             NEXT
  145.             PUT #ch, , IM2()
  146.  
  147.         CASE 2:
  148.             FOR Palete = 0 TO 15
  149.                 v = _PALETTECOLOR(Palete, src&)
  150.                 PUT #ch, , v
  151.             NEXT
  152.             PUT #ch, , IM3()
  153.  
  154.  
  155.         CASE 3:
  156.             FOR Palete = 0 TO 1
  157.                 v = _PALETTECOLOR(Palete, src&)
  158.                 PUT #ch, , v
  159.             NEXT
  160.             PUT #ch, , IM4()
  161.     END SELECT
  162.  
  163.  
  164. FUNCTION in& (x AS INTEGER, y AS INTEGER, src&)
  165.     in& = _PIXELSIZE(src&) * (y * _WIDTH(src&) + x)
  166.     ' in& = (y * _WIDTH(src&) + x)
  167.  
  168. FUNCTION DECtoBIN$ (vstup)
  169.     FOR rj = 7 TO 0 STEP -1
  170.         IF vstup AND 2 ^ rj THEN DECtoBIN$ = DECtoBIN$ + "1" ELSE DECtoBIN$ = DECtoBIN$ + "0"
  171.     NEXT rj
  172.  
  173. FUNCTION BINtoDEC (b AS STRING)
  174.     BINtoDEC = VAL("&B" + b$)
  175.  

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: How to read the first 4 bits of the byte?
« Reply #3 on: October 08, 2018, 06:35:53 am »
Color compression, I take it?

Bear with me, as I'm still waking up, and let's see if I understand the need.

To get a compressed 8-bit value back into 2 4-bit values, you'd;

LeftHalf = CompressedBit AND 240
RightHalf = CompressedBit AND 15

To put those 2 halves back together into a full 8-bit value, you'd:

CompressedBit = 16 * LeftHalf + RightHalf   (LeftHalf needs to shift 4 places, while the right half stays the same.)

https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: How to read the first 4 bits of the byte?
« Reply #4 on: October 08, 2018, 07:57:32 am »
Yes, this is it. I was able to make a write for 16 colors using this logical operator, it's much faster. The solution was AND 15 for the first pass and the same (but without re-reading the first value) for the second pass. Now I'm banging my head and trying the same thing for a two-color record. Thank You Steve.

Marked as best answer by Petr on October 08, 2018, 05:35:47 am

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: How to read the first 4 bits of the byte?
« Reply #5 on: October 08, 2018, 08:06:12 am »
2 color, as in black and white?

Each bit would represent a pixel.

Take a compressed byte (CB) and just AND (2 ^ pixel) for the value.

CB AND 1 = pixel 0
CB AND 2 = pixel 1
CB AND 4 = pixel 2
CB AND 8
CB AND 16
CB AND 32
CB AND 64
CB AND 128

To go the other direction:

CB = pixel 7 * 128 + pixel 6 * 64 + pixel 5 * 32 + ......  + pixel 1 * 2 + pixel 0
« Last Edit: October 08, 2018, 08:07:37 am by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: How to read the first 4 bits of the byte?
« Reply #6 on: October 08, 2018, 08:16:51 am »
Perfect. Thanks a lot. In fact, even two-color BMPs contain 2 pallet records, so they do not always have to be a black-and-white picture. Only Windows painting does not accept this (while the photo viewer will display it correctly).