News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

still construct my bmp viewer problem again

Started by xiahan, May 03, 2012, 03:44:03 AM

Previous topic - Next topic

xiahan


Local spw:DWORD
...
                mov ebx,bmpinfo.biWidth
push ebx
mov edx,0
mov eax,ebx
mov ecx,3
mul ecx
add ebx,eax
add ebx,edx
mov ecx,4
div ecx
mov eax,4
sub eax,edx
.if eax == 4
mov eax,0
.endif
add eax,ebx
pop ebx
sub eax,ebx
mov spw,eax          ; i get the scanline padding width


                mov ebx,bmpheader.bfSize
                sub ebx,bmpheader.bfOffBits
                ...
                mov eax,ebx                       
add eax,ebx
invoke HeapAlloc,hHeap,8,eax
.if eax
mov pHeap,eax                 ;source buffer
add eax,ebx                     ;destination buffer, i want to transfer the
mov pHeapd,eax               ;bmp data to a new buffer with the RRGGBB order
                                                                      ;with no padding
invoke wsprintf,addr buffer2,addr fmt,pHeap,pHeapd,ebx
invoke MessageBox,0,addr buffer2,addr msgtitle,MB_OK
.endif

now comes the question

invoke ReadFile,hFile,pHeap,ebx,addr rdbytes,0      ; ebx == bmpheader.bfOffBits
                mov esi,pHeap
mov edi,pHeapd


dec esi
add esi,ebx                                       ; esi index the last byte in image data
mov ecx,ebx
.while ecx > 0
mov edx,0
mov eax,ecx
div spw
.if edx == 0
sub esi,3
.endif
mov al,[esi]                 ;error when run, it says the 0x00FFFFFF address can not be read
mov [edi],al                ; how can esi becomes 0x00FFFFFF
dec esi
inc edi
dec ecx
.endw

dedndave

hi Xiahan

i am not sure i understand why you are going to all this trouble
other than getting the width and height of an image, you probably don't have to mess with the file contents, directly
you can use SelectObject to select an HBITMAP into a DC for display   :U

xiahan

you know,it's just for fun, and that's why i try to learn masm.

if i directly use the WINDOWS API i may lost mush joy,

strange  :dazzled: :lol

and can anybody solve my problem?

dedndave

a while back, i wrote a little console app that converts back and forth from BMP to RAW
it only handled 16-color, 256-color, and 24-bit uncompressed BMP's
i was using it with the scolorq dithering program by Derrick Coetzee
http://www.cs.berkeley.edu/~dcoetzee/downloads/scolorq/

i quit working on it, because it was boring - lol
but - i processed the files line-by-line - with small buffers
in other words, i would read one line, process it, then write it
it worked pretty well because windows caches disk data for you
i guess if you are going to display it, you may want to buffer larger pieces

at any rate - i am having a hard time understanding your code   :P

xiahan

maybe my code is some kind of unreadable cuz i'm a beginner

being unfamiliar with the CPU instructions

and don't know how to use them indeed   :lol

xiahan

Quote from: dedndave on May 03, 2012, 10:43:16 AM
a while back, i wrote a little console app that converts back and forth from BMP to RAW
it only handled 16-color, 256-color, and 24-bit uncompressed BMP's
i was using it with the scolorq dithering program by Derrick Coetzee
http://www.cs.berkeley.edu/~dcoetzee/downloads/scolorq/

i quit working on it, because it was boring - lol
but - i processed the files line-by-line - with small buffers
in other words, i would read one line, process it, then write it
it worked pretty well because windows caches disk data for you
i guess if you are going to display it, you may want to buffer larger pieces

at any rate - i am having a hard time understanding your code   :P
i have a look at scolorq, it's written in C++.

faint...

dedndave

well - scolorq was written to work with RAW files - very similar to what you are doing
he uses the header-less variation - 3 bytes per pixel - RGB interleaved order - no end-of-line padding   :P

the way i processed files...
1) open the BMP file, read the standard headers (54 bytes), and validate it
make sure it follows BMP format and that it is a version that you want your program to support

2) determine the file metrics - i can see that you are trying to implement this
get the color depth from BITMAPINFOHEADER.biBitCount and image width from BITMAPINFOHEADER.biWidth
file bytes per line = ((biBitCount * biWidth / 8) + 3) AND (-4)
(applies to uncompressed files only)

get the image height from BITMAPINFOHEADER.biHeight
if it is negative, the first line in the file is the top line of the image
if it is positive, the first line in the file is the bottom line of the image
store the positive value because you will want the unsigned height in the future

multiply (file bytes per line) * (unsigned height) and verify that it is equal to BITMAPINFOHEADER.biSizeImage
i also add the header sizes to that and verify that BITMAPFILEHEADER.bfSize = actual file size = calculated total

from there...
calculate the offset into the file of the top image line
use the file bytes per line to step through each line of the file image data
i use SetFilePointer, then ReadFile
if the biHeight is positive, i subtract the file bytes per line from the pointer for each line
if the biHeight is negative, i add the file bytes per line from the pointer for each line

xiahan

finally i get it done
but the image is truely upside-down (like the documentary says lol:)

and the display like the kinescope

you will see the effect once you download my zip and run it

ps: source code and execute file together

xiahan

Quote from: dedndave on May 04, 2012, 03:24:15 AM
well - scolorq was written to work with RAW files - very similar to what you are doing
he uses the header-less variation - 3 bytes per pixel - RGB interleaved order - no end-of-line padding   :P

the way i processed files...
1) open the BMP file, read the standard headers (54 bytes), and validate it
make sure it follows BMP format and that it is a version that you want your program to support

2) determine the file metrics - i can see that you are trying to implement this
get the color depth from BITMAPINFOHEADER.biBitCount and image width from BITMAPINFOHEADER.biWidth
file bytes per line = ((biBitCount * biWidth / 8) + 3) AND (-4)
(applies to uncompressed files only)

get the image height from BITMAPINFOHEADER.biHeight
if it is negative, the first line in the file is the top line of the image
if it is positive, the first line in the file is the bottom line of the image
store the positive value because you will want the unsigned height in the future

multiply (file bytes per line) * (unsigned height) and verify that it is equal to BITMAPINFOHEADER.biSizeImage
i also add the header sizes to that and verify that BITMAPFILEHEADER.bfSize = actual file size = calculated total

from there...
calculate the offset into the file of the top image line
use the file bytes per line to step through each line of the file image data
i use SetFilePointer, then ReadFile
if the biHeight is positive, i subtract the file bytes per line from the pointer for each line
if the biHeight is negative, i add the file bytes per line from the pointer for each line

my last revision of my program has made it executable,
and my algorithm is exactly like what you described

but there reminds two shortcoming
1. the speed like the way kinescope display images
2. i found some bitmap's first two byte are not 'BM',but some application defined data
and the 'BM' is after the data
so still many aspects need to be considered

dedndave

there are more flavours of "bmp files" than Baskin has ice cream
maybe you are looking at some sort of DIB or WMF file

xiahan



and eax,0FFFFFFh
;and eax,000000ffh
invoke CreatePen,PS_SOLID,1,eax


i use some mask like above code snippets to isolate the pure red color

with the change of the mask , the output varies colorful

and change some small parts , the image is upside-upside

invoke MoveToEx,hDC,rect.left,rect.bottom,0    ;use rect.bottom insteads of rect.top as Y
inc rect.left
invoke LineTo,hDC,rect.left,rect.bottom

and last , write a useable program is over my imagination

dedndave

well - you are doing it the hard way
and, alas, the wrong way, too

windows is a multi-tasking operating system
that means the user may bring other windows to the front, then switch back to yours
if you try that with your program, you will notice that the image does not get re-drawn

because of this, windows provides a message call-back system
the OS will send your window a WM_PAINT message whenever it should re-draw
there are only a few other times that you should draw to the screen - we will not delve into those, for now
so, to simplify, let's just say "the only time you should draw to the screen is during WM_PAINT"

you can load the bitmap using LoadBitmap or LoadImage
that gives you a handle to the bitmap - let's save it as hbmpBitmap
when you receive a WM_PAINT message, WndProc may respond by drawing or displaying whatever is necessary
here is some really simple code
        .DATA?

hInstance  HINSTANCE ?
hWin       HWND      ?
hbmpBitmap HBITMAP   ?

        .CODE

WndProc PROC hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

        LOCAL   hdcMem   :HDC
        LOCAL   hbmpPrev :HBITMAP
        LOCAL   ps       :PAINTSTRUCT

    .if uMsg==WM_PAINT
        INVOKE  BeginPaint,hWnd,addr ps
        INVOKE  CreateCompatibleDC,eax
        mov     hdcMem,eax
        INVOKE  SelectObject,eax,hbmpBitmap
        mov     hbmpPrev,eax
        mov     ecx,ps.rcPaint.right
        mov     edx,ps.rcPaint.bottom
        sub     ecx,ps.rcPaint.left
        sub     edx,ps.rcPaint.top
        INVOKE  BitBlt,ps.hdc,ps.rcPaint.left,ps.rcPaint.top,ecx,edx,
                hdcMem,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY
        INVOKE  SelectObject,hdcMem,hbmpPrev
        INVOKE  DeleteDC,hdcMem
        INVOKE  EndPaint,hWnd,addr ps

    .elseif uMsg==.........(handle other messages)

    .else
        INVOKE  DefWindowProc,hWnd,uMsg,wParam,lParam
        ret

    .endif

    xor     eax,eax
    ret

WndProc  ENDP


that's a lot easier than parsing through the file and setting pixels, eh ?

dedndave

i am learning new functions, today   :lol
GetBitmapDimensionEx - DOH !

i am 57 - no way i can learn all of these before i die

EDIT - well, that's about a useless function - lol
QuoteThe retrieved dimensions must have been set by the SetBitmapDimensionEx function.
i can store and retrieve values without using an API function
no wonder i didn't know about it

xiahan

i'm 18 just for a while and have a job with low pay

my job and masm are unallied

so i don't write code for profits

the performance does little matter

what i really care is the achievability when the code run as i expected lol

dedndave

here - see if this works for you...