flat assembler
Message board for the users of flat assembler.

Index > Tutorials and Examples > Creating BMP in FASM

Author
Thread Post new topic Reply to topic
ProMiNick



Joined: 24 Mar 2012
Posts: 804
Location: Russian Federation, Sochi
ProMiNick 23 Sep 2016, 09:33
Code:
;====BITMAP FILE====
format binary as 'bmp'
include 'win32a.inc'
;include 'macro\xdisplay.inc' ; only for debug values

;defs
;ENUM_CLR =================
; not used but useful
CLR_BLACK        = 000000h ;4bit_palIndex=0, 8 bit  = 0
CLR_MAROON       = 800000h                   ;8bit_palIndex=1
CLR_GREEN        = 008000h                   ;8bit_palIndex=2
CLR_OLIVE        = 808000h                   ;8bit_palIndex=3
CLR_NAVY         = 000080h                   ;8bit_palIndex=4
CLR_PURPLE       = 800080h                   ;8bit_palIndex=5
CLR_TEAL         = 008080h                   ;8bit_palIndex=6
CLR_GRAY         = 808080h                   ;8bit_palIndex=7
CLR_Silver       = 0C0C0C0h                  ;8bit_palIndex=8
CLR_RED          = 0FF0000h ;4bit_palIndex=1, 8 bit  = 9
CLR_LIME         = 000FF00h ;4bit_palIndex=2, 8 bit  = 10
CLR_YELLOW       = 0FFFF00h ;4bit_palIndex=3, 8 bit  = 11
CLR_BLUE         = 00000FFh ;4bit_palIndex=4, 8 bit  = 12
CLR_MAGENTA      = 0FF00FFh ;4bit_palIndex=5, 8 bit  = 13
CLR_AQUA         = 000FFFFh ;4bit_palIndex=6, 8 bit  = 14
CLR_WHITE        = 0FFFFFFh ;4bit_palIndex=7, 8 bit  = 15
;==========================

;ENUM_COMPRESSION =========
; 
BMP_CMPRSSN_RAW  = 0000000h
BMP_NO_CMPRSSN   = 0000000h

;image properties==========
; & helpful calculations
WIDTH   = 17            ;Ширина в пикселях
HEIGHT  = 12            ;Высота в пикселях
BPP     = 4             ;Глубина цвета (бит на пиксел: 1,4,8,16,24,32)
COLOR_BPP_MASK = 1 shl BPP -1
COLOR_TMP_MASK = 1 shl (((BPP+7)/8)*8)-1
;display 'COLOR_BPP_MASK = '
;dispHex COLOR_BPP_MASK
;display 13,10,'COLOR_TMP_MASK = '
;dispHex COLOR_TMP_MASK
;display 13,10
COMPRESSION = BMP_CMPRSSN_RAW   ;Метод сжатия, если сжат
GRAYSCALE = 1           ;Флаг того, что изображение исполнено только в серых тонах
CLR_USED = 0            ;желаемое количество индексированных цветов
;количество индексированных цветов не может превышать максимально допустимого количества для данной глубины цвета
CLR_USED = CLR_USED mod (1 shl BPP)
;================================
;расчет количества цветов в палитре
INDEX_COUNT = CLR_USED
if ~CLR_USED
  INDEX_COUNT = 1 shl (BPP and 13)
end if
TMP_COLOR = 000000h     ; иначально должен быть определен, но значение не важно
RAW_WIDTH = (WIDTH*BPP+31) / 8


org 0
BMP.headers:
BMFH BITMAPFILEHEADER 'BM',file_size,0,0,BMP.image
BMIH BITMAPINFOHEADER sizeof.BITMAPINFOHEADER,WIDTH,HEIGHT,1,BPP,COMPRESSION,image_size,0,0,CLR_USED,0
BMP.headers.end:
BMP.data:
BMP.pallette:
  repeat INDEX_COUNT
    if GRAYSCALE and (INDEX_COUNT-1)
      val = 256*(%-1)/(INDEX_COUNT-1)
      if val > 255
        val = 255
      end if
      db val,val,val,0
    end if ; here should be case of not GRAYSCALE pallette, standart colors for 4bit & 8 bit pallette described in ENUM_CLR
  end repeat
pallette_size = $ - BMP.pallette
BMP.image:
  repeat HEIGHT
    y=%-1
    repeat WIDTH
      x=%-1            ; x_N(BPP)=PIX_RATE*N+x_0

      x_0 =(8/BPP)-1   ;  вхождение содержащее данные выровненные по байту
      if x_0<0         ; x_0(1) - с 7 элемента,   x_0(4) - с 1 элемента
        x_0=0          ; x_0(24)=x_0(32) = -1 (0й элемент - это сразу, а тут еще раньше чем сразу)
      end if
      PIX_RATE = 8/BPP ; частота пикселей с которой данные выравниваются по байту
      if PIX_RATE<1    ; RATE(1)=8 - каждые 8 элементов
        PIX_RATE=1     ; RATE(4)=2 - каждые 2 элемента
      end if           ; RATE(24)=RATE(32)=~0 - (чаще чем) каждый элемент
      COLOR = -1

      ; Здесь используем функции чтоб модифицировать пиксель
      ; macro ellipse ellipse_color,center,radius,our x, our y
      ; if pixel x,y in ellipse color it by ellipse_color
      ; & other figures ...

      TMP_COLOR = TMP_COLOR shl BPP ; есть пиксель - сдвигаем цвет на число бит на пиксель
      TMP_COLOR = (TMP_COLOR or (COLOR and COLOR_BPP_MASK)) and COLOR_TMP_MASK
      ;==========================================
      ;запись пикселов по байту
      if x mod PIX_RATE = x_0
         db TMP_COLOR and 0FFh
         if BPP>8
           db (TMP_COLOR shr 8) and 0FFh
           if BPP>16
             db (TMP_COLOR shr 16) and 0FFh
             if BPP=32
               db (TMP_COLOR shr 24) and 0FFh
             end if
           end if
         end if
      else if %=WIDTH
        TMP_COLOR = TMP_COLOR shl (BPP*(PIX_RATE -(% mod PIX_RATE)))
        db TMP_COLOR and 0FFh
      end if
      if %=WIDTH
        RAW_ALIGN = (4-(($-BMP.image) mod 4)) mod 4 ;(As temp var not as color)
        if (RAW_ALIGN)
          db (RAW_ALIGN) dup (0)
        end if
      end if
    end repeat
  end repeat
image_size = $ - BMP.image
file.end:
file_size = $
    


For now algorithm create any sized any BPP not compressed BMP with grayscale indexes (or w/o indexes - only in case of 32BPP).
Whole BMP filled by white. Color of every pixel can be changed by its x & y dimensions.

Not grayscale pallette in process...
Compressions in process...
Functions(Macros) to colorize pixel in 1BPP & 32BPP are simple, but in other modes they must interact with pallette indexes - that is in process too...

_________________
I don`t like to refer by "you" to one person.
My soul requires acronim "thou" instead.
Post 23 Sep 2016, 09:33
View user's profile Send private message Send e-mail Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 23 Sep 2016, 09:48
Thank you for this nice little example! I'm using every opportunity to test such exotic fasm sources with fasmg, and this one required very little changes. I just had to replace initial lines with "struct" definitions and then change the lines that initialize structures so that they use the new syntax, because I have not written a "struct" variant that would take unlabeled values like the one for fasm (I see I may need to write one just to have a tool for quicker adapting code from fasm):
Code:
macro struct? name
        macro ends?! 
                        end namespace 
                        iterate definition, args@struct 
                                match name:value, definition 
                                        store value at .name 
                                else match name==value, definition 
                                        store value at .name 
                                else match value, definition 
                                        err 'unnamed values not supported' 
                                end match 
                        end iterate 
                end struc 
                virtual at 0 
                        name name 
                        sizeof.name = $ 
                end virtual 
                purge ends? 
        end macro 
        struc name args@struct& 
                label . : sizeof.name 
                namespace . 
end macro

struct BITMAPINFOHEADER
  biSize          dd ?
  biWidth         dd ?
  biHeight        dd ?
  biPlanes        dw ?
  biBitCount      dw ?
  biCompression   dd ?
  biSizeImage     dd ?
  biXPelsPerMeter dd ?
  biYPelsPerMeter dd ?
  biClrUsed       dd ?
  biClrImportant  dd ?
ends

struct BITMAPFILEHEADER
  bfType      dw ?
  bfSize      dd ?
  bfReserved1 dw ?
  bfReserved2 dw ?
  bfOffBits   dd ?
ends

;defs 
;ENUM_CLR ================= 
; not used but useful 
CLR_BLACK        = 000000h ;4bit_palIndex=0, 8 bit  = 0 
CLR_MAROON       = 800000h                   ;8bit_palIndex=1 
CLR_GREEN        = 008000h                   ;8bit_palIndex=2 
CLR_OLIVE        = 808000h                   ;8bit_palIndex=3 
CLR_NAVY         = 000080h                   ;8bit_palIndex=4 
CLR_PURPLE       = 800080h                   ;8bit_palIndex=5 
CLR_TEAL         = 008080h                   ;8bit_palIndex=6 
CLR_GRAY         = 808080h                   ;8bit_palIndex=7 
CLR_Silver       = 0C0C0C0h                  ;8bit_palIndex=8 
CLR_RED          = 0FF0000h ;4bit_palIndex=1, 8 bit  = 9 
CLR_LIME         = 000FF00h ;4bit_palIndex=2, 8 bit  = 10 
CLR_YELLOW       = 0FFFF00h ;4bit_palIndex=3, 8 bit  = 11 
CLR_BLUE         = 00000FFh ;4bit_palIndex=4, 8 bit  = 12 
CLR_MAGENTA      = 0FF00FFh ;4bit_palIndex=5, 8 bit  = 13 
CLR_AQUA         = 000FFFFh ;4bit_palIndex=6, 8 bit  = 14 
CLR_WHITE        = 0FFFFFFh ;4bit_palIndex=7, 8 bit  = 15 
;========================== 

;ENUM_COMPRESSION ========= 
;  
BMP_CMPRSSN_RAW  = 0000000h 
BMP_NO_CMPRSSN   = 0000000h 

;image properties========== 
; & helpful calculations 
WIDTH   = 17            ;?????? ? ???????? 
HEIGHT  = 12            ;?????? ? ???????? 
BPP     = 4             ;??????? ????? (??? ?? ??????: 1,4,8,16,24,32) 
COLOR_BPP_MASK = 1 shl BPP -1 
COLOR_TMP_MASK = 1 shl (((BPP+7)/8)*8)-1 
;display 'COLOR_BPP_MASK = ' 
;dispHex COLOR_BPP_MASK 
;display 13,10,'COLOR_TMP_MASK = ' 
;dispHex COLOR_TMP_MASK 
;display 13,10 
COMPRESSION = BMP_CMPRSSN_RAW   ;????? ??????, ???? ???? 
GRAYSCALE = 1           ;???? ????, ??? ??????????? ????????? ?????? ? ????? ????? 
CLR_USED = 0            ;???????? ?????????? ??????????????? ?????? 
;?????????? ??????????????? ?????? ?? ????? ????????? ??????????? ??????????? ?????????? ??? ?????? ??????? ????? 
CLR_USED = CLR_USED mod (1 shl BPP) 
;================================ 
;?????? ?????????? ?????? ? ??????? 
INDEX_COUNT = CLR_USED 
if ~CLR_USED 
  INDEX_COUNT = 1 shl (BPP and 13) 
end if 
TMP_COLOR = 000000h     ; ????????? ?????? ???? ?????????, ?? ???????? ?? ????? 
RAW_WIDTH = (WIDTH*BPP+31) / 8 


org 0 
BMP.headers:
BMFH BITMAPFILEHEADER bfType:'BM', bfSize:file_size, bfOffBits:BMP.image
BMIH BITMAPINFOHEADER biSize:sizeof.BITMAPINFOHEADER, biWidth:WIDTH, biHeight:HEIGHT, biPlanes:1,\
                      biBitCount:BPP, biCompression:COMPRESSION, biSizeImage:image_size, biClrUsed:CLR_USED
BMP.headers.end: 
BMP.data: 
BMP.pallette: 
  repeat INDEX_COUNT 
    if GRAYSCALE and (INDEX_COUNT-1) 
      val = 256*(%-1)/(INDEX_COUNT-1) 
      if val > 255 
        val = 255 
      end if 
      db val,val,val,0 
    end if ; here should be case of not GRAYSCALE pallette, standart colors for 4bit & 8 bit pallette described in ENUM_CLR 
  end repeat 
pallette_size = $ - BMP.pallette 
BMP.image: 
  repeat HEIGHT 
    y=%-1 
    repeat WIDTH 
      x=%-1            ; x_N(BPP)=PIX_RATE*N+x_0 

      x_0 =(8/BPP)-1   ; 1? ????????? ?????????? ?????? ??????????? ?? ????? 
      if x_0<0         ; x_0(1) - ? 7 ????????,   x_0(4) - ? 1 ???????? 
        x_0=0          ; x_0(24)=x_0(32) = -1 (0? ??????? - ??? ?????, ? ??? ??? ?????? ??? ?????) 
      end if 
      PIX_RATE = 8/BPP ; ??????? ???????? ? ??????? ?????? ????????????? ?? ????? 
      if PIX_RATE<1    ; RATE(1)=8 - ?????? 8 ????????? 
        PIX_RATE=1     ; RATE(4)=2 - ?????? 2 ???????? 
      end if           ; RATE(24)=RATE(32)=~0 - (???? ???) ?????? ??????? 
      COLOR = -1 

      ; ????? ?????????? ??????? ???? ?????????????? ??????? 
      ; macro ellipse ellipse_color,center,radius,our x, our y 
      ; if pixel x,y in ellipse color it by ellipse_color 
      ; & other figures ... 

      TMP_COLOR = TMP_COLOR shl BPP ; ???? ??????? - ???????? ???? ?? ????? ??? ?? ??????? 
      TMP_COLOR = (TMP_COLOR or (COLOR and COLOR_BPP_MASK)) and COLOR_TMP_MASK 
      ;========================================== 
      ;?????? ???????? ?? ????? 
      if x mod PIX_RATE = x_0 
         db TMP_COLOR and 0FFh 
         if BPP>8 
           db (TMP_COLOR shr 8) and 0FFh 
           if BPP>16 
             db (TMP_COLOR shr 16) and 0FFh 
             if BPP=32 
               db (TMP_COLOR shr 24) and 0FFh 
             end if 
           end if 
         end if 
      else if %=WIDTH 
        TMP_COLOR = TMP_COLOR shl (BPP*(PIX_RATE -(% mod PIX_RATE))) 
        db TMP_COLOR and 0FFh 
      end if 
      if %=WIDTH 
        RAW_ALIGN = (4-(($-BMP.image) mod 4)) mod 4 ;(As temp var not as color) 
        if (RAW_ALIGN) 
          db (RAW_ALIGN) dup (0) 
        end if 
      end if 
    end repeat 
  end repeat 
image_size = $ - BMP.image 
file.end: 
file_size = $    
The only two lines in the main source text that got changed are these two:
Code:
BMFH BITMAPFILEHEADER bfType:'BM', bfSize:file_size, bfOffBits:BMP.image
BMIH BITMAPINFOHEADER biSize:sizeof.BITMAPINFOHEADER, biWidth:WIDTH, biHeight:HEIGHT, biPlanes:1,\
                      biBitCount:BPP, biCompression:COMPRESSION, biSizeImage:image_size, biClrUsed:CLR_USED    
Post 23 Sep 2016, 09:48
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.