News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

My first program in MASM32

Started by iZ!, February 22, 2015, 09:46:17 PM

Previous topic - Next topic

iZ!

Success!! :greenclp:

Hello everyone,
I am happy to announce that I created a 24-bit to indexed (16) color bitmap converter which works at lightning speed:)
It's a console type application in which you specify the input and optionally the output file...

>>>EDIT: Only works with certain formats(width and height should probably be divisible by 4)<<<

At least Steve N. aka FORTRANS should be interested:)

In the next version, I'm planning to add an 'ALL' command which will make the program convert the whole directory of BMPs. But this could easily be done with some BASIC or any other programming software by calling my program through console shell.

Here's the code:


            ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
                include \masm32\include\masm32rt.inc
            ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
           
            comment * -----------------------------------------------------
                                    Build this  template with
                                   "CONSOLE ASSEMBLE AND LINK"

                           Author: iZ! (izi@grafitron.net , i.z.i@hotmail.com)

                    ----------------------------------------------------- *
           
   
                .code
           
            start:
               
            ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
           
                call main
                exit
           
            ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
           
            main proc
      LOCAL ptrMem :DWORD                          ; file handle
                LOCAL ptrMem2 :DWORD                          ; file handle
                LOCAL PIXDATALEN :DWORD                          ; file handle
         local     cnt  ;counter - starts with number of pixels and goes to zero
            LOCAL bwrt  :DWORD                          ; variable for bytes written
                LOCAL cloc  :DWORD                          ; current location variable
                LOCAL flen  :DWORD                          ; file length variable
                LOCAL flen2  :DWORD                          ; file length variable
                LOCAL hMem  :DWORD                          ; allocated memory handle
                LOCAL hMem2  :DWORD                          ; allocated memory handle
                LOCAL ptstbrv  :DWORD                          ; allocated memory handle
                LOCAL stbrv  :byte                          ; allocated memory handle
                LOCAL ptbrvs  :DWORD                          ; allocated memory handle
               LOCAL ptbaza  :DWORD                          ; allocated memory handle
               LOCAL hFile :dword
                              LOCAL hFile2  :DWORD                          ; allocated memory handle

              LOCAL ptbrvtab:DWORD                          ; allocated memory handle
              LOCAL ptrColorTbl:DWORD                     ;pointer to the color table of BMP file in memory
              LOCAL TIP:byte

local fnam:dword
local fnam2:dword
mov fnam,alloc(128)
mov fnam2,alloc(128)

mov cnt,0
invoke GetCL,1,fnam

.if len(fnam)==0
print "                   Version 0.1                      ",13,10

print "Usage: 24to4bitBMPconv <SourceBMP> [DestBMP]",13,10
print "Note: SourceBMP must be 24-bit ",13,10
print "      If DestBMP is not specified, the program will rewrite SourceBMP ",13,10
print "Author: iZ! - izi@grafitron.net , i.z.i@hotmail.com ",13,10
print "Enjoy!",13,10
jmp EXIT
.endif

                mov hFile, fopen(fnam)            ; open the existing file again
                mov flen, fsize(hFile)                      ; get its length

invoke GlobalAlloc,0,flen
mov  hMem,eax
invoke GlobalLock,hMem
mov  ptrMem,eax
                mov bwrt, fread(hFile,hMem,flen)            ; read data from file into buffer
                fclose hFile                                ; close the file

mov esi,ptrMem
add esi,28
MOV BL,byte ptr[ESI]
MOV TIP,BL

.if BL!=24

print ".. I need a 24-bit bitmap! .." , 13,10
jmp EXIT

.endif
;----pixel data len
MOV eax,flen
mov edx,0
sub eax,54
mov ecx,3
div ecx
MOV PIXDATALEN,eax
;----========-----


;-----16 color BMP layout-----
shr eax,1
mov flen2,eax
ADD flen2,118
invoke GlobalAlloc, 0, flen2
mov  hMem2,eax
invoke GlobalLock,hMem2
mov  ptrMem2,eax
;-----------------------------

;----- ====Copy header====----

  mov edi,ptrMem2
mov esi,ptrMem
mov ecx,54
rep movsb
;----------------------
;----- ====Replace certain data in it====----

mov ebx,ptrMem2
add ebx,2
push flen2
pop dword ptr[ebx]
add ebx,8
mov dword ptr[ebx],118
add ebx,4
mov dword ptr[ebx],40
mov dword ptr[ebx+14],4 ;remembered that one at last:)
;-----===================-----
xor ebx,ebx
mov eax,ptrMem2
mov ptstbrv,eax
add ptstbrv,46
mov ptbaza,eax
add ptbaza,10
mov ptrColorTbl ,eax
add ptrColorTbl,54

push ptrMem
pop esi
add esi,54
mov edi,ptrMem2
add edi,118

MOV EaX,PIXDATALEN
mov cnt,eax
MOV stbrv,1


;B24:
;------===load and convert 3-byte 24bit to 4-byte palette color===----
LODSd
and eax,16777215 ; mask out the highest byte since 24-bit BMP uses 3 bytes per pixel
dec esi
;-----------------=================--------------------------------
mov ebx,ptrColorTbl
mov [ebx],eax

DEC cnt
xor dx,dx
mov dL,7

B240:
;-----main loop----

;-------================---------------
LODSd
and eax,16777215 ; mask out the highest byte since 24-bit BMP uses 3 bytes per pixel
dec esi

;--------------===-=-=-=-=-----===---------------

MOV DH,stbrv  ;Number of colors
mov ebx,ptrColorTbl ;pointer to color table

U1:
cmp eax,[Ebx]
JZ BINGO
ADD Ebx,4

inc cl  ;increase color index

DEC DH
JNZ U1

NI:
;if it went through all known colors and none of them matched then...
mov [ebx],eax
INC stbrv
cmp stbrv,17
jz toomuch


BINGO:
GOON:

; -----=====I could go byte per byte copying of rgb values but for speed reasons I'm doing it in ECX register====-----
test dl,1
jnz drug
rol cl,4
dec dl
jmp goon2
drug:
ror ecx,8

DEC DL
jnz goon2

poln:
mov eax,ecx
stosd
mov dL,8
XOR ECX,ECX

;-------=================================================================-------------
goon2:

DEC cnt
JNZ B1240
jmp pis


B1240:

jmp B240

toomuch:

print "The input image contains more than 16 different colors or",13,10
print "the format is currently not supported. Maybe in future version(s)",13,10
print "Grafitron.net/progs/ ",13,10
print " iZ! ",13,10

EXIT:


         invoke GlobalFree, hMem                                   ; free the allocated memory
invoke GlobalFree, hMem2                                   ; free the allocated memory



 
                ret

pis:

invoke GetCL,2,fnam2

.if len(fnam2)==0
    invoke DeleteFile,fnam
    mov hFile, fcreate(fnam)          ; create the file
    mov bwrt, fwrite(hFile,hMem2,flen2)        ; write data to it
    fclose hFile                                ; close the file
jmp E1
.endif


    mov hFile, fcreate(fnam2)          ; create the file
    mov bwrt, fwrite(hFile,hMem2,flen2)        ; write data to it
    fclose hFile                                ; close the file

E1:

print "Bytes written: ",13,10
print ustr$(flen2),13,10

jmp EXIT

            main endp
           
            ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
           
            end start


rrr314159

Congratulations iZ, but 

I tried it with a picture off the net, a 24-bit bmp of a butterfly, but the result doesn't work. In Windows Photo Viewer it's not able to read the ht, width or depth, something wrong with the header. Obviously it must work for you, so, I don't know.

Minor point, leave off the d: in the include statement:

include d:\masm32\include\masm32rt.inc

instead

include \masm32\include\masm32rt.inc

One question, why 4-bit? I guess the idea is just to make a much smaller bmp? Or is there some particular use for them, maybe some program that requires them?

Well, if you want to see the bmp that doesn't work (for some reason) let me know.

Again, congrats, because no doubt it does work for you!
I am NaN ;)

iZ!

rrr,
Yea the idea is to save some space.. Years ago I did over 300 images of digital arts and, since I didn't know enough then, I saved them in 24-bit.. Now with this program I'll be able to convert all of those images with one command.
Oh, yeah.. If the source BMP has more than 16 colors, it won't work..
Maybe try creating your own 24-bit BMP with MSPaint..
Or try this one -> http://grafitron.net/slike/digital%20art/galerija1/xx1-ex.bmp

Thanks for your comments, I'll remove the 'd:' ..

rrr314159

Ok that works. I assume those images at grafitron.net are the 300 you did years ago? Pretty cool ... Looks like they have 16 colors so makes a lot of sense to do this conversion. What did u use to create them? Are you still doing computer art? I have some computer art myself, made with MASM; it's all 32 bit and uses lots of colors ... I've thought of displaying it, the way you have. Are there web sites that discuss this sort of thing? Do u try to sell them, have u had any success? Are there "art gallery" sites that you use? Is it a big disadvantage that the pictures are multi-megabyte? ... Perhaps you know a site where I can learn about this topic ... ?

Thanks for any info u might be able to provide ... !
I am NaN ;)

clamicun

And do this...

print "Enjoy!",13,10
inkey "ok"
jmp EXIT

iZ!

rrr,
Yeah, those are the images I did over 5 years ago... I used Turbo Basic for making them..
I sold few of them locally, but very cheap.. I'm still putting it all together..
The idea is to sell pictures in a glass framework and instead of the signature, I'll just put my website address.
I haven't been doing much art lately..
I don't use any 'art-gallery' sites yet so I don't know how it is with their size limitations.

I can offer you 1GB on my server for your digital art for 20eur/year..




FORTRANS

Hi iZ!,

Quote from: iZ! on February 22, 2015, 09:46:17 PM
Success!!

Congratulations.
Quote

Hello everyone,
I am happy to announce that I created a 24-bit to indexed (16) color bitmap converter which works at lightning speed:)
It's a console type application in which you specify the input and optionally the output file...

Give it a try, download the .EXE here ->  http://grafitron.net/progs/24to4bitBMPconv.exe

At least Steve N. aka FORTRANS should be interested:)

   Okay.

Quote from: iZ! on February 22, 2015, 11:26:16 PM
Oh, yeah.. If the source BMP has more than 16 colors, it won't work..
Maybe try creating your own 24-bit BMP with MSPaint..

   Oh.  That's why it blew up on the first one.  Okay, tried it on
one that should have less than 16 colors.  Works, but with some
corruption.  I will try on a new, known good, 16 color image later.

   The program I was working on tried to take any 24-bit BMP and
convert to a 16 or 256 color TGA picture with a good ("optimum")
palette.  Slow, quirky, and a bit too specialized for general use I
suppose.

Regards,

Steve N.

iZ!

Hey Steve,

Alright.. I didn't get that at first time.. I thought you were chasing the same result as me..

rrr314159

Thanks iZ,

I might take you up on your offer, but I have to wait for my check to get here at the end of the month ... then I have to pay the landlord, the cable and the bookie ... but I ought to be able to sell some food stamps, and the cat can do without food for a few days, so perhaps I can swing it  :icon_cool:

But seriously it might be a good idea to gang together, have a website where people can view various artists. I notice you already have one guest, Bori. See what happens; you haven't seen my stuff yet, it might scare people away! I'd post something here but they're all 5 meg and more. The biggest is 94 meg, 6000 by 4000: looks a lot like Peter Max. When I get around to it I'll chop one down to a meg or less (I wonder what the limit is here) and post it.

I started doing "Math Art" almost 40 years ago on an early IBM Color PC. Like you, a few years ago I worked with basic - Liberty Basic, not a bad program - and produced some semi-good pics. With MASM I've recently been able to make them literally 10,000 times faster - now I call it "Math Movie" because it does 30 frames / second. So, it's been an on-going hobby for a long time.

Again, congrats on your successful program ... talk to u later !

I am NaN ;)

dedndave

it's really hard to make sense out of the code
are you converting to 16-bit or 16-color ?

one thing that is easy to overlook...
for any BMP file, the number of bytes in each line is always divisible by 4
the line ends are typically padded with 0, when required

going from 24-bit to 16-color is going to be very lossy, as you must know   :P
i have done a little work in that area, using scolorq by Derrick Coetzee

http://www.cs.berkeley.edu/~dcoetzee/downloads/scolorq/

it is slow, and usually must be run a few times to get desireable results
but, it does a good job of dithering to a 16-color palette

dedndave

here's an example output from scolorq

iZ!

Quote from: dedndave on February 23, 2015, 07:02:48 PM

one thing that is easy to overlook...
for any BMP file, the number of bytes in each line is always divisible by 4
the line ends are typically padded with 0, when required

going from 24-bit to 16-color is going to be very lossy, as you must know   :P
i have done a little work in that area, using scolorq by Derrick Coetzee


I'm only working with BMPs with size of multiples of 640x480, so you might be right about the padding. I haven't tested it on any other formats.
The program I did produces no loss, assuming that the 24-bit BMP doesn't use more than 16 colors. I know there's not many examples of the problem I have..

FORTRANS

Hi Dave,

Quote from: dedndave on February 23, 2015, 07:02:48 PM
going from 24-bit to 16-color is going to be very lossy, as you must know   :P
i have done a little work in that area, using scolorq by Derrick Coetzee

...

it is slow, and usually must be run a few times to get desireable results
but, it does a good job of dithering to a 16-color palette

   Interesting.  My program does the same thing approximately
as scolorq.  The difference in appearance on the Lena picture
might be as much in the dithering as the color selection.  My
16 color result on the Lena image looks a bit smoother.  I wrote
three versions of the Floyd-Steinberg dithering algorithm over
the years.  The Lena image looks as if it will start another round
of debugging on the third version. 

   I will have to read up on that algorithm that scolorq uses.
It might suggest improvements in my program.

Cheers,

Steve N.

dedndave

hi Steve
i tried to understand his code - no luck - lol
you are more familiar with C than i am   :t

Izzy
this is from one of my programs

BMP_HDR STRUCT
  bmfh    BITMAPFILEHEADER <>
;   bfType          dw   ?    ;'BM' file signature
;   bfSize          UINT ?    ;file size
;   bfReserved1     dw   ?    ;must be 0
;   bfReserved2     dw   ?    ;must be 0
;   bfOffBits       UINT ?    ;size of BITMAPINFO, typically 76h, 436h, or 36h
  bmih    BITMAPINFOHEADER <>
;   biSize          UINT ?    ;should be 28h (sizeof BITMAPINFOHEADER)
;   biWidth         dd   ?    ;must be positive, output = input
;   biHeight        dd   ?    ;sign indicates direction, output = input
;   biPlanes        dw   ?    ;must be 1
;   biBitCount      dw   ?    ;4, 8, or 24, other depths not supported by this program
;   biCompression   UINT ?    ;0, compressed formats not supported by this program
;   biSizeImage     UINT ?    ;image lines are always 4 byte multiples
;   biXPelsPerMeter dd   ?    ;output = input (may be 0)
;   biYPelsPerMeter dd   ?    ;output = input (may be 0)
;   biClrUsed       UINT ?    ;ignored, 0 for output file
;   biClrImportant  UINT ?    ;ignored, 0 for output file
BMP_HDR ENDS


that works great for 24-bit images
(for 16-bit images, BITMAPINFO is usually 76h in size)

the way microsoft defines the BITMAPINFO structure is a little off (it works in C)
Hutch has used this definition, following the ms definition

BITMAPINFO STRUCT
  bmiHeader  BITMAPINFOHEADER <>
  bmiColors  RGBQUAD <>
BITMAPINFO ENDS


as you can see, there is only one RGBQUAD defined (that may work for 16-bit images)
but, for 16-color or 256-color bitmaps, you have to define your own structure

BITMAPINFO16 STRUCT
  bmiHeader    BITMAPINFOHEADER <>
  bmiColors    RGBQUAD 16 dup(<>)
BITMAPINFO16 ENDS


now, you can create a proper BMP header for 16-bit files

BMP_HDR16 STRUCT
  bmfh    BITMAPFILEHEADER <>
  bmih    BITMAPINFO16 <>
BMP_HDR16 ENDS

iZ!

Quote from: dedndave on February 24, 2015, 02:57:38 AM
i tried to understand his code - no luck - lol
you are more familiar with C than i am   :t

Izzy
...

:)
why C?

I kinda understand the STRUCTURE block but the rest seems too complicated.
I prefer to do it directly in memory/registers.
Thanks but I'll stick to my bytes:) :


bfType 2 The characters "BM"
bfSize 4 The size of the file in bytes
bfReserved1 2 Unused - must be zero
bfReserved2 2 Unused - must be zero
--10
bfOffBits 4 Offset to start of Pixel Data
--14
biSize 4 Header Size - Must be at least 40
--18
biWidth 4 Image width in pixels
biHeight 4 Image height in pixels
biPlanes 2 Must be 1
--28
biBitCount 2 Bits per pixel - 1, 4, 8, 16, 24, or 32
biCompression 4 Compression type (0 = uncompressed)
biSizeImage 4 Image Size - may be zero for uncompressed images
biXPelsPerMeter 4 Preferred resolution in pixels per meter
biYPelsPerMeter 4 Preferred resolution in pixels per meter
--46
biClrUsed 4 Number Color Map entries that are actually used
biClrImportant 4 Number of significant colors


The Color Table

If we are dealing with images having a bit depth of 8 or less, then the pixel data
is actually an index into a color palette. For instance, in a 4-bit image there are
a maximum of 16 colors in the palette. If the data for a particular pixel is, say,
9, then the color that is used for that pixel is given by the tenth entry in the
table (because the numbering starts with 0 and not 1).

In all versions of BMP files starting with Version 3 (Win3x), the color entries
occupy 4 bytes each so that they can be efficiently read and written as single
32-bit values. Taken as a single value, the four bytes are ordered as follows:
[ZERO][RED][GREEN][BLUE]. Due to the Little Endian format, this means that the Blue
value comes first followed by the green and then the red. A fourth, unused, byte
comes next which is expected to be equal to 0.

If we are dealing with 16-bit or 32-bit images,
then the Color Table contains a set of bit masks
used to define which bits in the pixel data to
associate with each color. Note that the original
Version 3 BMP format did not support these image
types. Instead, these were an extension of the
format developed for WindowsNT. For both the
16-bit and the 32-bit variants, the color masks
are 32-bits long with the green mask being first
and the blue mask being last. In both cases the
bit masks start with the most significant bits,
meaning that for the 16-bit images the least significant
two bytes are zero. The format requires that the
bits in each mask be contiguous and that the masks
be non-overlapping. The most common bit masks for
16-bit images are RGB555 and RGB565 while the most
common bitmasks for 32-bit images are RGB888 and
RGB101010.

If we are dealing with a 24-bit image, then there is no Color Table present.





I've put this together from here -> http://www.dragonwins.com/domains/getteched/bmp/bmpfileformat.htm

So thanks to William Louis Bahn, the author of this page. Without this article, I wouldn't be able to make my program.
There's also .WAV file explained on this website. But I haven't managed to slowly go through it yet.