Author Topic: StretchBlt Problem  (Read 4097 times)

guga

  • Moderator
  • Member
  • *****
  • Posts: 826
  • Assembly is a state of art.
    • RosAsm
StretchBlt Problem
« on: August 07, 2015, 03:22:17 PM »
Hi Guys

I´m trying to create a variation of StretchBlt function but i´m having problems when adjusting the screen coordinates:(

The problem is with the nXOriginDest, nYOriginDest etc.  My function uses the parameters of the strecthblt to pass them onto the bitblt api.

Code: [Select]
Proc StretchBltEx:
    Arguments @pCImgStruct, @hDCDest, @CX_Img, @CY_Img, @FrameWidth, @FrameHeight, @hdcSrc, @CX_Frame, @CY_Frame, @ImageWidth, @ImageHeight
    Local @byPixel, @hdcImage, @lpvBits, @ImgSize, @hBmp, @DeltaY, @DeltaHeight, @MirrorFlag
    Structure @BITMAP 24, @BITMAP.bmTypeDis 0, @BITMAP.bmWidthDis 4, @BITMAP.bmHeightDis 8, @BITMAP.bmWidthBytesDis 12, @BITMAP.bmPlanesDis 16,
              @BITMAP.bmBitsPixelDis 18, @BITMAP.bmBitsDis 20
    uses ebx, ecx, esi, edi, edx


    mov esi D@pCImgStruct

    If_Or D@FrameWidth = 0, D@FrameHeight = 0, D@ImageWidth = 0, D@ImageHeight = 0, D$esi+CIMAGE.m_ucpBitsDis = 0
        call 'KERNEL32.SetLastError' &ERROR_INVALID_PARAMETER
        xor eax eax
        ExitP
    End_If

    ; Analyse signal, set the flags acordly and then make sure all is positive
    mov D@MirrorFlag 0 ; No mirror
    If_And D@FrameWidth <s 0, D@ImageWidth <s 0
    Else_If_Or D@FrameWidth <s 0, D@ImageWidth <s 0
        inc D@MirrorFlag ; 1 = Mirror in Width (X Axis)
    End_If

    .If_And D@FrameHeight <s 0, D@ImageHeight <s 0
    .Else_If_Or D@FrameHeight <s 0, D@ImageHeight <s 0
        If D@MirrorFlag <> 0 ; Is mirror on width exist ?
            mov D@MirrorFlag 3; 3 = Mirror in Width (X Axis) and Heigth  (Y Axis)
        Else
            mov D@MirrorFlag 2; 2 = Mirror in Heigth (Y Axis)
        End_If
    .End_If

    ; make sure all is positive
    ABS D@FrameWidth, 0 | mov D@FrameWidth eax
    ABS D@ImageWidth, 0  | mov D@ImageWidth eax
    ABS D@FrameHeight, 0 | mov D@FrameHeight eax
    ABS D@ImageHeight, 0 | mov D@ImageHeight eax

    ;call 'gdi32.GetCurrentObject' D@hdcSrc, &OBJ_BITMAP ; USE THIS TO AVOID USING CIMAGE eax = handle to bmp hbmp

    move D@hBmp D$esi+CIMAGE.m_hBmpDis
    call 'RosMem.ZeroMemory' D@BITMAP, Size_Of_BITMAP
    call 'GDI32.GetObjectA' D@hbmp, Size_Of_BITMAP, D@BITMAP ; get informations about the bitmap
    On eax = 0, ExitP ; On error, exit

    ; --------- Here starts the problem !!! __--------

    ;sub D@CY_Img 30 ; Top of the image ?
    ;sub D@CY_Frame 30 ; Negative bottom of the image ?
    ;sub D@FrameHeight 130 ; enlarge image or shrink ?
    ;sub D@ImageHeight 100 ; stretchs the image up. upper left of image ?

    ; deltaY
    mov ecx D@CY_Img | sub ecx D@CY_Frame | mov D@DeltaY ecx
    mov ebx D@FrameHeight | sub ebx D@ImageHeight | mov D@DeltaHeight ebx

    mov eax D@FrameHeight
    ...If eax > D@ImageHeight ; If destyination heitgh is bigger then original

        .If D@DeltaY <s 0
            ; when going up

            mov ebx D@CY_Frame | add D@FrameHeight ebx
            mov eax D@DeltaY | add D@CY_Img eax
            mov D@CY_Frame 0

            mov ebx D@BITMAP.bmHeightDis | mov D@FrameHeight ebx
            move D@ImageHeight D@FrameHeight;D@ImageHeight ebx
            If D@DeltaHeight <> 0

                mov ebx D@DeltaHeight | add D@FrameHeight ebx

            End_If
        .Else
            ; when going down or is at inside the screen
            ;mov D@CY_Img 0 ; top layer
            ;mov D@CY_Frame 0 ; top frame

           ; sub D@ImageHeight 30 ; bottom layer
           mov eax D@DeltaHeight;D@DeltaY

           mov D@FrameHeight 300

        .End_If

    ...Else_If eax <= D@ImageHeight ; if destination height is smaller then original

        .If D@DeltaY <s 0
            ; when going up

            ;mov ebx D@BITMAP.bmHeightDis | sub ebx D@ImageHeight; | shr ebx 1
            move D@ImageHeight D@FrameHeight;D@BITMAP.bmHeightDis
            ;sub D@FrameHeight ebx
            mov eax D@CY_Img ; Top of the image
            mov ebx D@CY_Frame ; Negative bottom of the image            ;add D@CY_Frame  ebx
            mov D@CY_Frame eax
            mov D@CY_Img ebx

        .Else
            ; when going down or is at inside the screen
            mov ebx D@BITMAP.bmHeightDis | sub ebx D@ImageHeight | shr ebx 1
            move D@ImageHeight D@BITMAP.bmHeightDis
            add D@FrameHeight ebx
            ;add D@CY_Frame ebx
            ;mov D@CY_Frame 0
            ;add D@CY_Img 0;ebx


            ;mov ebx D@BITMAP.bmHeightDis | sub ebx D@FrameHeight
            ;add D@FrameHeight ebx
            ;move D@ImageHeight D@FrameHeight

            ;mov ebx D@DeltaHeight | add D@FrameHeight ebx

        .End_If

    ...End_if

;   -------------------------------------------------------- End of computations of cy/cx etc

    move D@hBmp D$esi+CIMAGE.m_hBmpDis
    call resizePixelsok D$esi+CIMAGE.m_ucpBitsDis, D@ImageWidth, D@ImageHeight, D@FrameWidth, D@FrameHeight
    mov ebx eax | xor edx edx | mov edx D@FrameWidth | imul edx D@FrameHeight | shl edx 2
    mov D@lpvBits ebx
    mov D@ImgSize edx

    call 'RosMem.ZeroMemory' OutBmpNfo, Size_Of_BITMAP
    call 'GDI32.GetObjectA' D@hbmp, Size_Of_BITMAP, D@BITMAP ; get informations about the bitmap
    On eax = 0, ExitP ; On error, exit

    ;A bit of information is necessary for GetDIBits to work. So starty filling only what is needed.
    mov D$OutBmpNfo.bmiHeader.biSize Size_of_BITMAPINFO
    move D$OutBmpNfo.bmiHeader.biWidth D@FrameWidth
    move D$OutBmpNfo.bmiHeader.biHeight D@FrameHeight
    mov eax D@BITMAP.bmPlanesDis
    mov W$OutBmpNfo.bmiHeader.biPlanes ax
    mov eax D@BITMAP.bmBitsPixelDis
    mov W$OutBmpNfo.bmiHeader.biBitCount ax
    mov D$OutBmpNfo.bmiHeader.biCompression &BI_RGB ; compression (no)
    call 'GDI32.CreateCompatibleDC' &NULL | mov D@hdcImage eax
    call 'GDI32.SetDIBits' eax, D@hbmp, 0, D$OutBmpNfo.bmiHeader.biHeight, D@lpvBits, OutBmpNfo, &DIB_PAL_COLORS

    call 'GDI32.BitBlt' D@hdcDest, D@CX_Img, D@CY_Img, D@FrameWidth, D@FrameHeight, D@hdcSrc, D@CX_Frame, D@CY_Frame, &SRCCOPY
;;
??????
call 'GDI32.BitBlt' D@hdcDest, D@CX_Img, D@CY_Img, D@FrameWidth, D@FrameHeight, D@hdcSrc, D@CX_Frame, D@CY_Frame, &SRCCOPY
ps.rcPaint.left = D@CX_Img
ps.rcPaint.top = D@CY_Img
ps.rcPaint.right-ps.rcPaint.left = D@FrameWidth = ps.rcPaint.right - D@CX_Img
ps.rcPaint.bottom-ps.rcPaint.top = D@FrameHeight = ps.rcPaint.bottom -D@CY_Frame
ps.rcPaint.left = D@CX_Frame
ps.rcPaint.top = D@CY_Frame
, SRCCOPY
;;

    call 'GDI32.DeleteDC' D@hdcImage

    ; release the allocated memory
    call 'RosMem.VMemFree' D@lpvBits
    mov eax &TRUE

EndP

The simplyfied code without the math is this:

Code: [Select]
Proc StretchBltEx:
    Arguments @pCImgStruct, @hDCDest, @CX_Img, @CY_Img, @FrameWidth, @FrameHeight, @hdcSrc, @CX_Frame, @CY_Frame, @ImageWidth, @ImageHeight
    Local @byPixel, @hdcImage, @lpvBits, @ImgSize, @hBmp, @DeltaY, @DeltaHeight, @MirrorFlag
    Structure @BITMAP 24, @BITMAP.bmTypeDis 0, @BITMAP.bmWidthDis 4, @BITMAP.bmHeightDis 8, @BITMAP.bmWidthBytesDis 12, @BITMAP.bmPlanesDis 16,
              @BITMAP.bmBitsPixelDis 18, @BITMAP.bmBitsDis 20
    uses ebx, ecx, esi, edi, edx


    mov esi D@pCImgStruct

    If_Or D@FrameWidth = 0, D@FrameHeight = 0, D@ImageWidth = 0, D@ImageHeight = 0, D$esi+CIMAGE.m_ucpBitsDis = 0
        call 'KERNEL32.SetLastError' &ERROR_INVALID_PARAMETER
        xor eax eax
        ExitP
    End_If

    ; Analyse signal, set the flags acordly and then make sure all is positive
    mov D@MirrorFlag 0 ; No mirror
    If_And D@FrameWidth <s 0, D@ImageWidth <s 0
    Else_If_Or D@FrameWidth <s 0, D@ImageWidth <s 0
        inc D@MirrorFlag ; 1 = Mirror in Width (X Axis)
    End_If

    .If_And D@FrameHeight <s 0, D@ImageHeight <s 0
    .Else_If_Or D@FrameHeight <s 0, D@ImageHeight <s 0
        If D@MirrorFlag <> 0 ; Is mirror on width exist ?
            mov D@MirrorFlag 3; 3 = Mirror in Width (X Axis) and Heigth  (Y Axis)
        Else
            mov D@MirrorFlag 2; 2 = Mirror in Heigth (Y Axis)
        End_If
    .End_If

    ; make sure all is positive
    ABS D@FrameWidth, 0 | mov D@FrameWidth eax
    ABS D@ImageWidth, 0  | mov D@ImageWidth eax
    ABS D@FrameHeight, 0 | mov D@FrameHeight eax
    ABS D@ImageHeight, 0 | mov D@ImageHeight eax

    ;call 'gdi32.GetCurrentObject' D@hdcSrc, &OBJ_BITMAP ; USE THIS TO AVOID USING CIMAGE eax = handle to bmp hbmp

    move D@hBmp D$esi+CIMAGE.m_hBmpDis
    call 'RosMem.ZeroMemory' D@BITMAP, Size_Of_BITMAP
    call 'GDI32.GetObjectA' D@hbmp, Size_Of_BITMAP, D@BITMAP ; get informations about the bitmap
    On eax = 0, ExitP ; On error, exit

(.........Here should have some math to this work................)

    move D@hBmp D$esi+CIMAGE.m_hBmpDis
    call resizePixelsok D$esi+CIMAGE.m_ucpBitsDis, D@ImageWidth, D@ImageHeight, D@FrameWidth, D@FrameHeight
    mov ebx eax | xor edx edx | mov edx D@FrameWidth | imul edx D@FrameHeight | shl edx 2
    mov D@lpvBits ebx
    mov D@ImgSize edx

    call 'RosMem.ZeroMemory' OutBmpNfo, Size_Of_BITMAP
    call 'GDI32.GetObjectA' D@hbmp, Size_Of_BITMAP, D@BITMAP ; get informations about the bitmap
    On eax = 0, ExitP ; On error, exit

    ;A bit of information is necessary for GetDIBits to work. So starty filling only what is needed.
    mov D$OutBmpNfo.bmiHeader.biSize Size_of_BITMAPINFO
    move D$OutBmpNfo.bmiHeader.biWidth D@FrameWidth
    move D$OutBmpNfo.bmiHeader.biHeight D@FrameHeight
    mov eax D@BITMAP.bmPlanesDis
    mov W$OutBmpNfo.bmiHeader.biPlanes ax
    mov eax D@BITMAP.bmBitsPixelDis
    mov W$OutBmpNfo.bmiHeader.biBitCount ax
    mov D$OutBmpNfo.bmiHeader.biCompression &BI_RGB ; compression (no)
    call 'GDI32.CreateCompatibleDC' &NULL | mov D@hdcImage eax
    call 'GDI32.SetDIBits' eax, D@hbmp, 0, D$OutBmpNfo.bmiHeader.biHeight, D@lpvBits, OutBmpNfo, &DIB_PAL_COLORS

    call 'GDI32.BitBlt' D@hdcDest, D@CX_Img, D@CY_Img, D@FrameWidth, D@FrameHeight, D@hdcSrc, D@CX_Frame, D@CY_Frame, &SRCCOPY

    call 'GDI32.DeleteDC' D@hdcImage

    ; release the allocated memory
    call 'RosMem.VMemFree' D@lpvBits
    mov eax &TRUE

EndP

The images bellow shows better the problem




« Last Edit: August 08, 2015, 12:31:26 AM by guga »
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: StretchBlt Problem
« Reply #1 on: August 07, 2015, 08:05:59 PM »
i really don't understand the RosAsm syntax   :lol:

but, i don't see how you can use BitBlt to perform the same operation as StretchBlt

guga

  • Moderator
  • Member
  • *****
  • Posts: 826
  • Assembly is a state of art.
    • RosAsm
Re: StretchBlt Problem
« Reply #2 on: August 08, 2015, 12:43:24 AM »
Hi Dave

thanks :)

The bitblt is used after the pixels are resized with  resizePixelsok ( resizePixels in fact This i a function i made for resizing the pixels as the name suggests).

The only problem is that although the image is correctly resized, i´m failing to find the proper points of nxdest (CX_IMG) etc. I´m not being able to find the X and Y coordinates of the image ad the DC.

I´m failing to find tje corrrespondence of the arguments of both api.

Their parameters can be viewed as:

BitBlt (hdcDst, xDst, yDst, cx, cy, hdcSrc, xSrc, ySrc, dwROP) ;

StretchBlt (hdcDst, xDst, yDst, cxDst, cyDst, hdcSrc, xSrc, ySrc, cxSrc, cySrc, dwROP) ;

So, xDst, yDst, xSrc, ySrc seems to be the same for both Apis.

But, i need to find "cx, cy".

Is there some info about the relationship between those coordinates on the screen ?

I mean, cy = xyDst-cySrc ???

In the 2nd screenshot, why yDst (CY_IMG in my code) turns zeroed when the image is above the client window ? Shouldn´t it be negative ?

If i undertood how the parameters works and are related to the coordinates, it could be used to find the proper values.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

rrr314159

  • Member
  • *****
  • Posts: 1381
Re: StretchBlt Problem
« Reply #3 on: August 08, 2015, 01:59:04 AM »
Hi guga,

Haven't studied your code, but hope this helps.

Quote from: guga
I´m failing to find tje corrrespondence of the arguments of both api.

Their parameters can be viewed as:

BitBlt (hdcDst, xDst, yDst, cx, cy, hdcSrc, xSrc, ySrc, dwROP) ;

StretchBlt (hdcDst, xDst, yDst, cxDst, cyDst, hdcSrc, xSrc, ySrc, cxSrc, cySrc, dwROP) ;

So, xDst, yDst, xSrc, ySrc seems to be the same for both Apis.

But, i need to find "cx, cy".

Is there some info about the relationship between those coordinates on the screen ?

I mean, cy = xyDst-cySrc ???

- When I use these functions:

cx = cxSrc
cy = cySrc

Then after (and this is the part u might be missing?)

Code: [Select]
invoke GetWindowRect, window_handle, addr rect
cxDst = rect.right
cyDst = rect.bottom
I am NaN ;)

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: StretchBlt Problem
« Reply #4 on: August 08, 2015, 04:27:20 AM »
when you resize an image, there is a good likelihood that there is no correspondance
of pixels from the original image to pixels of the resized image (see attached image)

there are a few ways to calculate the color of a pixel from the original pixels
one is the weighted average of the 1, 2, or 4 nearest pixels
the inverse-square law is used to calculate - very time consuming to do an entire image

what i have to ask is, why not just use StretchBlt ?   :redface:

when using StretchBlt, i first set the mode to HALFTONE with SetStretchBltMode
(works best for most image types)

https://msdn.microsoft.com/en-us/library/dd145089%28v=vs.85%29.aspx


dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: StretchBlt Problem
« Reply #5 on: August 08, 2015, 04:31:33 AM »
this little program allows pan-zoom of a BMP file
(notice the trackbar controls and little buttons)
in the menus, you can choose half-tone or color-on-color modes

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: StretchBlt Problem
« Reply #6 on: August 08, 2015, 04:53:55 AM »
this demonstrates HALFTONE mode

notice the zoom control (red circles)
and, in the lower corners, buttons for status bar (S) and center-cursor (+) on/off

you can select seperate modes for reduction and enlargement
View menu - Map Inset - Zoom Modes - Enlarge/Reduce

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: StretchBlt Problem
« Reply #7 on: August 08, 2015, 06:01:06 AM »
per Edgar....

Quote
Use COLORONCOLOR when reducing.
Use HALFTONE and SetBrushOrgEx when enlarging.

I found that some image types may look best if HALFTONE is used whether enlarging or reducing.

guga

  • Moderator
  • Member
  • *****
  • Posts: 826
  • Assembly is a state of art.
    • RosAsm
Re: StretchBlt Problem
« Reply #8 on: August 08, 2015, 06:02:47 PM »
Hi dave

Many thanks....but, i used it on the original code. The problem is that strecthblt api fails when loading huge files, such as HDR for example. It is too slow and the result is poor of the enlarging the image.

The reduce/enlarge problem i overcome with my own variation of a resizing function. The algorithm is simple to avoid speed isues when dealing with large files. The result seems a bit better then the gdi32 api. Also, internally strecth api uses bitblt already (inside win32k.sys, i mean) but before it reaches the bitblt function, it calls several other functions. So, probably it is slower then if i try to create a own variation of it.

I´ll test for speed and accuracy after i suceed to fix the Coordinates problem .
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: StretchBlt Problem
« Reply #9 on: August 08, 2015, 09:40:46 PM »
i would guess you are trying to stretch an entire image,
when only the portion that needs to be displayed should be stretched

StretchBlt is pretty fast, considering what it does
i suggest you StretchBlt the part you need into a memory DC,
then BitBlt from the memory DC into the display DC

ToutEnMasm

  • Member
  • *****
  • Posts: 1189
    • EditMasm
Re: StretchBlt Problem
« Reply #10 on: August 09, 2015, 02:14:47 AM »
To win time,load the image and create the DC outside WM_PAINT
StretchBlt could also be used outside WM_PAINT,and you will not see how slow it is.
the WM_PAINT must have only to put the image on screen.
Fa is a musical note to play with CL

guga

  • Moderator
  • Member
  • *****
  • Posts: 826
  • Assembly is a state of art.
    • RosAsm
Re: StretchBlt Problem
« Reply #11 on: August 12, 2015, 02:48:22 PM »
Thanks guys I guess i´m suceeding to understand the math behind this api. I could be able to find the corresponding parameters of the RECT struture related to the image in the dc.

Now i´m computing the coordinates, and also it seems that i can also find the coordinates of the current working (The client area where the bitmap is located) without other apis.

A couple of things i found interesting. The stretch api returns True even when the destination and width/height have both negative values. This is weird because it should return a error.

When we have nWidthSrc and nWidthDest negative (both), it means that the bitmap is located outside the X-Axis. So, the api must return zero or another error code (Invalid parameters for example).

The same happens when nHeightDest and NHeightSrc are both negatives.

Interesting is that the msdn documentation says nothing about it. It only states that when the signs of thme are different the image is mirrored, but it says nothing when both are negative.

This info is particular usefull, when building a app with a Dc that moves along the screen (when you are moving it with the mouse, for example). Whenever both parameters are negative, the strecth api can be avoided from the computation to speed it up. Why it would speed up ? Because even thought the function returns true on this condition, it is completelly useless because the image is outside the visible area.


« Last Edit: August 13, 2015, 01:11:19 AM by guga »
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: StretchBlt Problem
« Reply #12 on: August 12, 2015, 08:39:19 PM »
coordinates may be negative
it simply means there is an offset in the image location
for places where there is no image to draw, it's likely you will get black

if both width and height are negative, it is mirrored on both axis
that is the same as rotating it 180 degrees   :P

there are many ways to speed up the paint code
the PAINTSTRUCT structure has a RECT inside it (rcPaint)
that RECT tells you what portion of the client area requires update
so, if you only generate the part that is needed, you can save a lot of time

what i often do, in this respect, is draw the entire client area into a memory DC
and BitBlt only the RECT required by rcPaint into the display DC
even though you may spend time drawing unnecessary image area,
drawing into a memory DC is generally very fast
drawing into a display DC is much slower
that makes the code fairly simple

guga

  • Moderator
  • Member
  • *****
  • Posts: 826
  • Assembly is a state of art.
    • RosAsm
Re: StretchBlt Problem
« Reply #13 on: August 22, 2015, 11:03:30 PM »
HGuys

I succeded making an alternative variation of the Api (At least for Y coord). It loads, enlarge, reduce images of 12 Mb or bigger:) Btw..i´ll fix a small problem of X coord later.

But, i have a doubt on the algorithm ued by strecth api.

It seems it uses nearest neighbour or bilinear algorithms to perform the enlarging/shrinking, but when i tried to implement the nearest neighbour i´m having incorrect results.

I built an variation of the algorithm seem here

http://tech-algorithm.com/articles/nearest-neighbor-image-scaling/

Code: [Select]
public int[] resizePixels(int[] pixels,int w1,int h1,int w2,int h2) {
    int[] temp = new int[w2*h2] ;
    double x_ratio = w1/(double)w2 ;
    double y_ratio = h1/(double)h2 ;
    double px, py ;
    for (int i=0;i<h2;i++) {
        for (int j=0;j<w2;j++) {
            px = Math.floor(j*x_ratio) ;
            py = Math.floor(i*y_ratio) ;
            temp[(i*w2)+j] = pixels[(int)((py*w1)+px)] ;
        }
    }
    return temp ;
}

I ported it to RosAsm, but i added a Starting and Ending area of the inputed image to process. For example, given an image of 640*480, i would like to enlarge only a specific area of the image so the result will be a 1024*720. But, also, I would like to limit the visible area. So, if the enlarging image exceeds the area of the client window it will keep the image proportion. Example, let´s say the visible area is only 800*600. I would like to "view" a resized image from width = 640 to 1024 and height=480 to 720, but limited to a view area of 800*600 (So allowing cropping)

Example of the porting code:

YStart = 30 --> Starting at YPos 30 (CYStart)
YEnd = 290 --> Ending at YPos 290 (CYEnd)
XStart = 120 --> Starting at XPos 120 (CXStart)
XEnd = 500 --> Ending at XPos 500 (CXEnd)

SrcWidth = 640 (WidthSrc)
SrcHeight = 480 (HeightSrc)

TargetWidth = 1024 (WidthDest)
Targetheight = 720 (HeightDest)

MaxViewHeight = 800 (CYDestMax)
MaxViewWidth = 600 (CXDestMax)

Code: [Select]

Proc resizePixelsEx:
    Arguments @Pixels, @CYStart, @CYEnd, @CXStart, @CXEnd, @WidthSrc, @HeightSrc, @WidthDest, @HeightDest, @CYDestMax, @CXDestMax
    Local @TempMem, @iCounter, @jCounter, @X2, @Y2, @MemPix
    Uses ebx, esi, edi, ecx, edx


    xor eax eax
    xor edx edx
    mov edx D@WidthDest | imul edx D@CYDestMax | shl edx 2

    mov D@MemPix 0 | lea eax D@MemPix
    call 'RosMem.VMemAlloc' eax, edx
    mov D@TempMem eax

    fild D@WidthSrc | fidiv D@WidthDest | fstp R$x_ratio
    fild D@HeightSrc | fidiv D@HeightDest | fstp R$y_ratio

    mov D@iCounter 0
    mov eax D@iCounter
    mov esi D@Pixels

    ; Get Starting pos
    mov ecx D@CYStart | imul ecx D@WidthSrc | add ecx D@CXStart |  shl ecx 2;D@X
    add esi ecx

    mov edi D@TempMem
    mov edx D@WidthDest |  shl edx 2 | add edx esi

    .While eax < D@CYDestMax;@HeightDest

        ;mov eax D@HeightDest
        mov D@jCounter 0
        mov eax D@jCounter
        While eax < D@CXDestMax;@WidthDest

            fild F@jCounter | fmul R$x_ratio | fistp F$CxMax
            fild F@iCounter | fmul R$y_ratio | fistp F$CyMax

;;
            X2 = (CyMax*Width1)+CxMax = ((iCounter*y_ratio)*Width1)+(jCounter*x_ratio)
            Y2 = (iCounter*Width2)+jCounter
;;

            lea eax D@X2 | fild F$CyMax | fimul F@WidthSrc | fiadd F$CxMax | fistp F$eax | mov eax D$eax
            lea ecx D@Y2 | fild F@iCounter | fimul F@WidthDest | fiadd F@jCounter | fistp F$ecx | mov ecx D$ecx

            mov eax D$esi+eax*4
            mov D$edi+ecx*4 eax

            inc D@jCounter
            mov eax D@jCounter
        End_While

        inc D@iCounter
        mov eax D@iCounter
    .End_While

    mov eax D@TempMem

EndP

The tests on a 4*2 image with a zoom of 196.50 gave me this result



See, the black pixels area ? This  should not to be black but filled tih the proper collors as in the Original Api. I´m pretty sure the problem is with the resizing/scaling algorithm but i´m unable to find the proper solution.

The image should be a bit more to the right and a bit on tht top. Teh proportions are Ok, but the displacement of it is wrong.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com