Results 1 to 32 of 32

Thread: Bitmap rotation: doing it in vc++?

  1. #1

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Bitmap rotation: doing it in vc++?

    Is there an API function in the lines of BitBlt or StretchBlt for rotating
    a bitmap by 90º? In other words, it must transpose the matrix of pixel
    values and thereafter do a horizontal or vertical flip, depending on
    whether the rotation is CW or CCW.
    Last edited by krtxmrtz; May 11th, 2005 at 05:22 AM.
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  2. #2
    PowerPoster
    Join Date
    Dec 2003
    Posts
    4,787

    Re: Block bitmap rotation

    There isnt a specific api function more a use of thema nd coding, have you had a search? there is a few example out there.

    Doe sthis help by NoteMe?
    http://www.vbforums.com/showpost.php...88&postcount=4

  3. #3
    PowerPoster
    Join Date
    Dec 2003
    Posts
    4,787

    Re: Block bitmap rotation


  4. #4
    Hyperactive Member notquitehere188's Avatar
    Join Date
    Dec 2004
    Posts
    403

    Re: Block bitmap rotation

    use plgblt
    it does not automatically rotate it but it can be used for rotating
    It's not just Good, It's Good enough!



    Spelling Eludes Me

  5. #5

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Block bitmap rotation

    Quote Originally Posted by Pino
    I know this thread, I used NoteMe's code when I had to implement rotations by any degree. For 90º rotations however I hoped there was a much faster function, as the one notquitehere188 has suggested.
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  6. #6

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Block bitmap rotation

    Quote Originally Posted by notquitehere188
    use plgblt
    it does not automatically rotate it but it can be used for rotating
    I know you must apply a flip to complete the rotation, but the simple transpose operation is not working for me:
    VB Code:
    1. Pt(0).x = 0
    2.             Pt(0).y = 0
    3.             Pt(1).x = Picture2.ScaleHeight
    4.             Pt(1).y = 0
    5.             Pt(2).x = 0
    6.             Pt(2).y = Picture2.ScaleWidth
    7.             PlgBlt Picture2.hdc, Pt(0), Picture2.hdc, 0, 0, Picture2.ScaleWidth, _
    8.             Picture2.ScaleHeight, ByVal 0&, ByVal 0&, ByVal 0&
    It does just nothing. Can it be used with the same source and destination?
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  7. #7

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Block bitmap rotation

    bump
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  8. #8
    Old Member moeur's Avatar
    Join Date
    Nov 2004
    Location
    Wait'n for Free Stuff
    Posts
    2,712

    Re: Block bitmap rotation

    You can flip the picture using the paintpicture method by supplying a negative value for either the destination height or width

  9. #9

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Block bitmap rotation

    Quote Originally Posted by moeur
    You can flip the picture using the paintpicture method by supplying a negative value for either the destination height or width
    Flipping is not the problem, it's transposing, i.e. from an original matrix A where pixel values are stored with NRow rows and NCol columns, a new matrix B must be created with NCol rows and NRow columns such that:

    B(i,j) = A(j,i)
    for i=1, 2, ..., NRows and j=1, 2, ..., NCols

    If that can be done with a single call to PlgBlt rather than using loops then a 90º rotation is quite straighforward (and I would imagine faster) as it is a combination of a flip followed by a transposition. The problem is I can't get PlgBlt working.
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  10. #10

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Block bitmap rotation

    All right, I'm ready to do it with 2 nested loops. But for large images, even with GetPixel and SetPixel this could be kind of slow, so I thought I'd do it with a VC++ DLL, as some of you folks have recently taught me the basic steps.
    The one question I need an answer to before I get down to business is, how can I pass a picturebox as an argument to the procedure in the DLL?
    Last edited by krtxmrtz; May 11th, 2005 at 05:27 AM.
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  11. #11

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Block bitmap rotation

    Quote Originally Posted by Me
    The one question I need an answer to before I get down to business is, how can I pass a picturebox as an argument to the procedure in the DLL?
    OK, I've solved that. I've made my sub in a C dll and it works nicely. However I've used SetPixel and GetPixel and this doesn't make it fast enough for large pictureboxes.

    My 2 questions to the C experts:
    - Is there really anything to be gained by doing 2 nested loops with SetPixels & GetPixels in VC++ rather than in VB?
    - Is it worth using DIB functions in the VC++ DLL to speed it up?
    Last edited by krtxmrtz; May 11th, 2005 at 10:26 AM.
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  12. #12
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Bitmap rotation: doing it in vc++?

    Rotation by 90 degree should be easy to do in C++, I can do it for yu but right now i'm at work (just starting).

    SetPixel and GetPixel are VERY, VERY.... VERY slow... even though it's API...

    The fastest way to do it is to get the actual bitmap data, and work with the bytes, but you have to understand the bitmap structure for that, it's actually easy...
    Actually, if you do it this way, even in VB will be a significant improvement compared to SetPixel and GetPixel.

    If I forget to do it, remind me in about 10 hours

  13. #13

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Bitmap rotation: doing it in vc++?

    Quote Originally Posted by CVMichael
    If I forget to do it, remind me in about 10 hours
    Well, in about 10 hours I'll probably be in bed counting bytes to catch some sleep... so I remind you now...

    My app reads a large file (ca. 10 Mb) and then plots the contents in a bitmap. I've implemented a part of the code in VC++ to make it faster -and it really is.

    The actual plotting is handled by SetDIBitsToDevice, which is perhaps what you had in mind. However, this part is in VB (I'm using somene else's code that I found in the forum) so,
    (1) I'd like to know if it can improve in terms of speed by converting it to VC++ and
    (2) I'm not sure I'm able to transpose (rotation = flip + transposition) the array of bytes:

    MyByteArray(NBytes)

    where the overall number of bytes is

    NBytes = Rows * (3 * Cols + DBytes)

    DBytes is the number of dummy bytes at the end of each row (so all rows are divisible by 4) like

    RGBR GBRG B000
    RGBR GBRG B000
    RGBR GBRG B000
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  14. #14
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Bitmap rotation: doing it in vc++?

    I downloaded this from my home computer...
    You have to put it in a module.

    Use the GetBitmapData to get the bitmap as an array, so you can manipulate the data, and SetBitmapData to put the data back in the PictureBox.
    For the SetBitmapData, the value param is a long, so you will have to use the VarPtr(YourArray(0)) function to get the array pointer.

    The functions works in 24 bits, so it does not matter how many bits per pixel your screen resolution has, it will always convert to 24 bits. And SetBitmapData function it's expecting that you pass a 24 bit bitmap data to it.

    You will need these functions even when I'll make the C++ rotation, cuz you need to pass the pointer to the data to the DLL.
    VB Code:
    1. Option Explicit
    2.  
    3. Public Const BI_RGB = 0&
    4. Public Const BI_RLE4 = 2&
    5. Public Const BI_RLE8 = 1&
    6.  
    7. Public Const DIB_RGB_COLORS = 0 '  color table in RGBs
    8. Public Const DIB_PAL_COLORS = 1 '  color table in palette indices
    9. Public Const DIB_PAL_INDICES = 2 '  No color table indices into surf palette
    10. Public Const DIB_PAL_PHYSINDICES = 2 '  No color table indices into surf palette
    11. Public Const DIB_PAL_LOGINDICES = 4 '  No color table indices into DC palette
    12.  
    13. Public Const SRCCOPY = &HCC0020         ' (DWORD) dest = source
    14.  
    15. Public Type SAFEARRAYBOUND
    16.     cElements As Long
    17.     lLbound As Long
    18. End Type
    19.  
    20. Public Type SAFEARRAY2D
    21.     cDims As Integer
    22.     fFeatures As Integer
    23.     cbElements As Long
    24.     cLocks As Long
    25.     pvData As Long
    26.     Bounds(0 To 1) As SAFEARRAYBOUND
    27. End Type
    28.  
    29. Public Type BITMAPINFOHEADER '40 bytes
    30.     biSize As Long
    31.     biWidth As Long
    32.     biHeight As Long
    33.     biPlanes As Integer
    34.     biBitCount As Integer
    35.     biCompression As Long
    36.     biSizeImage As Long
    37.     biXPelsPerMeter As Long
    38.     biYPelsPerMeter As Long
    39.     biClrUsed As Long
    40.     biClrImportant As Long
    41. End Type
    42.  
    43. Public Type BITMAPINFO
    44.     bmiHeader As BITMAPINFOHEADER
    45.     bmiColors As Long ' RGBQUAD
    46. End Type
    47.  
    48. Public Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
    49. Public Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
    50. Public Declare Function CreateDIBSection Lib "gdi32" (ByVal hdc As Long, pBitmapInfo As BITMAPINFO, ByVal un As Long, lplpVoid As Long, ByVal handle As Long, ByVal dw As Long) As Long
    51. Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
    52. Public Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
    53. Public Declare Function GetCurrentObject Lib "gdi32" (ByVal hdc As Long, ByVal uObjectType As Long) As Long
    54. Public Declare Function GetObjectType Lib "gdi32" (ByVal hgdiobj As Long) As Long
    55. Public Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
    56. Public Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
    57. Public Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
    58. Public Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpbi As BITMAPINFO, ByVal wUsage As Long) As Long
    59. Public Declare Function SetDIBits Lib "gdi32" (ByVal hdc As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpbi As BITMAPINFO, ByVal wUsage As Long) As Long
    60. Public Declare Function SetDIBitsToDevice Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal dx As Long, ByVal dy As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal Scan As Long, ByVal NumScans As Long, Bits As Any, BitsInfo As BITMAPINFO, ByVal wUsage As Long) As Long
    61. Public Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
    62. Public Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
    63. Public Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
    64.  
    65. Public Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long
    66.  
    67. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    68.  
    69.  
    70. Public Function GetBitmapData(hdc As Long, Width As Long, Height As Long, value() As Byte, Optional ByVal ReSize As Double = 1) As Boolean
    71.     Dim bi As BITMAPINFO, mhDC As Long, bitsPtr As Long, hDIB As Long
    72.     Dim bDibFrom() As Byte, Size As Long, old_bmp As Long, Ret As Long
    73.     Dim RWidth As Integer, RHeight As Integer
    74.     Dim tSAFrom As SAFEARRAY2D
    75.    
    76.     mhDC = CreateCompatibleDC(0)
    77.     If mhDC <> 0 Then
    78.         With bi.bmiHeader
    79.             .biSize = Len(bi.bmiHeader)
    80.            
    81.             If ReSize <> 1 Then
    82.                 RWidth = Width * ReSize
    83.                 .biWidth = RWidth
    84.                 RHeight = Height * ReSize
    85.                 .biHeight = RHeight
    86.             Else
    87.                 .biWidth = Width
    88.                 .biHeight = Height
    89.             End If
    90.            
    91.             .biPlanes = 1
    92.             .biBitCount = 24
    93.             .biCompression = BI_RGB
    94.             .biSizeImage = BytesPerScanLine(.biWidth, .biBitCount) * .biHeight
    95.         End With
    96.        
    97.         hDIB = CreateDIBSection(mhDC, bi, DIB_RGB_COLORS, bitsPtr, 0, 0)
    98.        
    99.         If hDIB <> 0 Then
    100.             old_bmp = SelectObject(mhDC, hDIB)
    101.            
    102.             If ReSize <> 1 Then
    103.                 Ret = StretchBlt(mhDC, 0, 0, Width * ReSize, Height * ReSize, hdc, 0, 0, Width, Height, SRCCOPY)
    104.             Else
    105.                 Ret = BitBlt(mhDC, 0, 0, Width, Height, hdc, 0, 0, SRCCOPY)
    106.             End If
    107.         Else
    108.             DeleteDC mhDC
    109.             Exit Function
    110.         End If
    111.     End If
    112.    
    113.     Size = bi.bmiHeader.biSizeImage
    114.    
    115.     If (Size > 0) Then
    116.         ReDim value(Size - 1)
    117.        
    118.         With tSAFrom
    119.             .cbElements = 1
    120.             .cDims = 2
    121.             .Bounds(0).lLbound = 0
    122.             .Bounds(0).cElements = bi.bmiHeader.biHeight
    123.             .Bounds(1).lLbound = 0
    124.             .Bounds(1).cElements = BytesPerScanLine(bi.bmiHeader.biWidth, bi.bmiHeader.biBitCount)
    125.             .pvData = bitsPtr
    126.         End With
    127.        
    128.         CopyMemory ByVal VarPtrArray(bDibFrom()), VarPtr(tSAFrom), 4
    129.         CopyMemory value(0), bDibFrom(0, 0), Size
    130.        
    131.         'Clear the temporary array descriptor, This is necessary under NT4.
    132.         CopyMemory ByVal VarPtrArray(bDibFrom), 0&, 4
    133.     End If
    134.    
    135.     DeleteObject hDIB
    136.     SelectObject mhDC, old_bmp
    137.     DeleteDC mhDC
    138.    
    139.     GetBitmapData = True
    140. End Function
    141.  
    142. Public Function SetBitmapData(ByVal hdc As Long, ByVal Width As Long, ByVal Height As Long, ByVal value As Long, Optional ByVal ReSize As Double = 1) As Boolean
    143.     Dim bi As BITMAPINFO, mhDC As Long, bitsPtr As Long, hDIB As Long
    144.     Dim bDibFrom() As Byte, old_bmp As Long, Ret As Long
    145.    
    146.     mhDC = CreateCompatibleDC(0)
    147.     If mhDC <> 0 Then
    148.         With bi.bmiHeader
    149.             .biSize = Len(bi.bmiHeader)
    150.             .biWidth = Width
    151.             .biHeight = Height
    152.             .biPlanes = 1
    153.             .biBitCount = 24
    154.             .biCompression = BI_RGB
    155.             .biSizeImage = BytesPerScanLine(.biWidth, .biBitCount) * .biHeight
    156.         End With
    157.        
    158.         hDIB = CreateDIBSection(mhDC, bi, DIB_RGB_COLORS, bitsPtr, 0, 0)
    159.        
    160.         If hDIB <> 0 Then
    161.             old_bmp = SelectObject(mhDC, hDIB)
    162.             Ret = SetDIBits(mhDC, hDIB, 0, bi.bmiHeader.biHeight, ByVal value, bi, DIB_RGB_COLORS)
    163.            
    164.             If ReSize <> 1 Then
    165.                 Ret = StretchBlt(hdc, 0, 0, Width * ReSize, Height * ReSize, mhDC, 0, 0, Width, Height, SRCCOPY)
    166.             Else
    167.                 Ret = BitBlt(hdc, 0, 0, Width, Height, mhDC, 0, 0, SRCCOPY)
    168.             End If
    169.         Else
    170.             DeleteDC mhDC
    171.             Exit Function
    172.         End If
    173.     End If
    174.    
    175.     DeleteObject hDIB
    176.     SelectObject mhDC, old_bmp
    177.     DeleteDC mhDC
    178.    
    179.     SetBitmapData = Ret > 0
    180. End Function
    181.  
    182. Public Function BytesPerScanLine(Width As Long, BitCount As Integer) As Long
    183.     BytesPerScanLine = (Width * BitCount)
    184.     If (BytesPerScanLine Mod 32 > 0) Then BytesPerScanLine = BytesPerScanLine + 32 - (BytesPerScanLine Mod 32)
    185.     BytesPerScanLine = BytesPerScanLine \ 8
    186. End Function

  15. #15
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Bitmap rotation: doing it in vc++?

    Using the functions above, I managed to write the following code, but It does not seem very fast (when it comes to big pictures).
    Is this code any faster than what you have now ?
    VB Code:
    1. Option Explicit
    2.  
    3. Private Declare Function GetTickCount Lib "kernel32" () As Long
    4.  
    5. Private Sub Form_Load()
    6.     Dim StartTick As Long
    7.    
    8.     Picture1.AutoRedraw = True
    9.     Picture1.Picture = LoadPicture(App.Path & "\Test.jpg")
    10.    
    11.     StartTick = GetTickCount
    12.    
    13.     RotatePic Picture1, Picture2
    14.    
    15.     Debug.Print "Time: " & GetTickCount - StartTick
    16. End Sub
    17.  
    18. Private Sub RotatePic(FromPic As PictureBox, ToPic As PictureBox)
    19.     Dim BitData() As Byte, DestBitData() As Byte
    20.     Dim X As Long, Y As Long, FromPos As Long, ToPos As Long
    21.     Dim NewSize As Long, BpslFrom As Long, BpslTo As Long
    22.    
    23.     FromPic.ScaleMode = vbPixels
    24.     GetBitmapData FromPic.hdc, FromPic.ScaleWidth, FromPic.ScaleHeight, BitData
    25.    
    26.     ' reverse width & height
    27.     NewSize = FromPic.ScaleWidth * BytesPerScanLine(FromPic.ScaleHeight, 24)
    28.     ReDim DestBitData(NewSize - 1)
    29.    
    30.     BpslFrom = BytesPerScanLine(FromPic.ScaleWidth, 24)
    31.     BpslTo = BytesPerScanLine(FromPic.ScaleHeight, 24)
    32.    
    33.     For Y = 0 To FromPic.ScaleHeight - 1
    34.         FromPos = Y * BpslFrom
    35.        
    36.         For X = 0 To (FromPic.ScaleWidth - 1) * 3 Step 3
    37.             ToPos = (X \ 3) * BpslTo + Y * 3
    38.            
    39.             DestBitData(ToPos + 0) = BitData(FromPos + X + 0)
    40.             DestBitData(ToPos + 1) = BitData(FromPos + X + 1)
    41.             DestBitData(ToPos + 2) = BitData(FromPos + X + 2)
    42.         Next X
    43.     Next Y
    44.    
    45.     ToPic.AutoRedraw = True
    46.     SetBitmapData ToPic.hdc, FromPic.ScaleHeight, FromPic.ScaleWidth, VarPtr(DestBitData(0))
    47. End Sub
    Last edited by CVMichael; May 12th, 2005 at 05:10 PM.

  16. #16

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Bitmap rotation: doing it in vc++?

    Quote Originally Posted by CVMichael
    Using the functions above, I managed to write the following code, but It does not seem very fast (when it comes to big pictures).
    Is this code any faster than what you have now ?
    Well, it's quite acceptable, certainly much faster than my Set/Get-Pixels. Now I'll have to study your code in detail and see how it can be adapted into my app. Probably I'm gonna need more help so stand by!!!
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  17. #17
    G&G Moderator chemicalNova's Avatar
    Join Date
    Jun 2002
    Location
    Victoria, Australia
    Posts
    4,246

    Re: Bitmap rotation: doing it in vc++?

    It could just be the math thats making it slow. Porting it to C++ might add that little bit of speed you are looking for.

    Visual Studio 6, Visual Studio.NET 2005, MASM

  18. #18

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Bitmap rotation: doing it in vc++?

    Quote Originally Posted by chemicalNova
    It could just be the math thats making it slow. Porting it to C++ might add that little bit of speed you are looking for.
    I will, but first I've got to check my old C books as I've sort of forgotten all about structures and I anticipate I'll have to use some.
    Last edited by krtxmrtz; May 12th, 2005 at 08:51 AM.
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  19. #19
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Bitmap rotation: doing it in vc++?

    You don't have to use any structures, just use a pointer of char array. Everything is pointers in C/C++ ... If you learn to master pointers in C/C++, you can do pretty cool stuff.

    I did not have time to convert it to C++ yesterday, I hope I will have time today after work...
    It should not be that difficult. Actually that's why I did it in VB first, cuz I can test easier in VB, and then when it's working properly, I was planning to convert it, but did not get to it.

    Also, can you tell me what is the difference in time, like how long did your function take, and how long did mine. Then when I finish the C++ one, to see the final time, and the total difference (just for reference, to see how long each method took)
    Last edited by CVMichael; May 12th, 2005 at 10:08 AM.

  20. #20

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Bitmap rotation: doing it in vc++?

    Quote Originally Posted by CVMichael
    You don't have to use any structures, just use a pointer of char array. Everything is pointers in C/C++ ... If you learn to master pointers in C/C++, you can do pretty cool stuff.
    How about the BITMAPINFO type and all that stuff? Is that implicitly declared in windows.h or any other header file?
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  21. #21
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Bitmap rotation: doing it in vc++?

    Don't convert that, it's too difficult, and it won't save much time.
    GetBitmapData + SetBitmapData, together they take 30 ms on my computer, if you do it C++ it won't save much time, just convert the 2 for loops in the RotatePic function, that's it...

    Loops are slow in VB, that's what you have to convert. There are no loops in GetBitmapData and SetBitmapData ,only API functions, that's why you won't get it much faster by converting to C++.

  22. #22

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Bitmap rotation: doing it in vc++?

    Quote Originally Posted by CVMichael
    Don't convert that, it's too difficult, and it won't save much time.
    All right, then that'll be much much easier.
    I'll let you know about the timing, hopefully tomorrow. Thanks a lot.
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  23. #23

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Bitmap rotation: doing it in vc++?

    Now I come to think of it, your code makes use of a few DIB API functions. I understand these result (sometimes?) in vertically inverted images.
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  24. #24
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Bitmap rotation: doing it in vc++?

    Yea, you are right. I think a bitmap is saved inverted in the bmp file, but I think in memory is stored properly (i.e, pos x = 0, y = 0, is pos 0 in the buffer). I did not do any serious bitmap programming for more than a year, I might be wrong...

  25. #25
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Bitmap rotation: doing it in vc++?

    Hehe, what a stupid mistake... I forgot to add "Step 3" to the For Loop, line:
    VB Code:
    1. For X = 0 To (FromPic.ScaleWidth - 1) * 3 [b]Step 3[/b]
    Now it takes half the time in VB...

    I also edited the previous post and added "Step 3" to that line...


    [edit] Is it rotating properly ??
    It seems that it rotates and flips at the same time, I don't think it should do that ?

    Before I was testing with a picture that looked almost the same even if you rotate, but I just tested with a picture wich is more obvious how it rotates... (WINNT.BMP picture in the windows directory )
    Last edited by CVMichael; May 12th, 2005 at 05:21 PM.

  26. #26
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Bitmap rotation: doing it in vc++?

    This can't be right...
    Attached Images Attached Images  

  27. #27
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Bitmap rotation: doing it in vc++?

    Finally, I figured it out !
    I had to inverse either the X or the Y (CW or CCW)
    VB Code:
    1. For Y = 0 To FromPic.ScaleHeight - 1
    2.         FromPos = Y * BpslFrom
    3.        
    4.         For X = 0 To (FromPic.ScaleWidth - 1) * 3 Step 3
    5.             'ToPos = (X \ 3) * BpslTo + Y * 3
    6.             'ToPos = ((FromPic.ScaleWidth - 1) - (X \ 3)) * BpslTo + Y * 3      ' CW
    7.             ToPos = (X \ 3) * BpslTo + ((FromPic.ScaleHeight - 1) - Y) * 3      ' CCW
    8.            
    9.             DestBitData(ToPos + 0) = BitData(FromPos + X + 0)
    10.             DestBitData(ToPos + 1) = BitData(FromPos + X + 1)
    11.             DestBitData(ToPos + 2) = BitData(FromPos + X + 2)
    12.         Next X
    13.     Next Y

    OK, now i'm gonna start converting it to C++ ....

    This is more like it, right ?
    Attached Images Attached Images  

  28. #28
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Bitmap rotation: doing it in vc++?

    DONE !!

    For the WINNT.BMP, in VB it took ~ 250 ms, now it takes 20 ms !

    Here's the C++ code:
    Code:
    _declspec(dllexport) long _stdcall BytesPerScanLine(long width, short bit_count)
    {
    	long ret = width * bit_count;
    	
    	if((ret % 32) > 0) ret += 32 - (ret % 32);
    	
    	return ret >> 3;
    }
    
    _declspec(dllexport) void _stdcall RotateBMPData_CW(char *from_bmp, long width, long height, char *to_bmp)
    {
    	long x, y, h_add;
    	long bpsl_from = BytesPerScanLine(width, 24);
    	long bpsl_to = BytesPerScanLine(height, 24);
    	
    	char *from_pos, *to_pos;
    
    	for(y = 0; y < height; y++)
    	{
    		from_pos = from_bmp + y * bpsl_from;
    		h_add = y * 3;
    
    		for(x = 0; x < width; x++)
    		{
    			to_pos = to_bmp + ((width - 1) - x) * bpsl_to + h_add;
    
    			*(to_pos++) = *(from_pos++);
    			*(to_pos++) = *(from_pos++);
    			*(to_pos++) = *(from_pos++);
    		}
    	}
    }
    
    _declspec(dllexport) void _stdcall RotateBMPData_CCW(char *from_bmp, long width, long height, char *to_bmp)
    {
    	long x, y, h_add;
    	long bpsl_from = BytesPerScanLine(width, 24);
    	long bpsl_to = BytesPerScanLine(height, 24);
    
    	char *from_pos, *to_pos;
    	
    	for(y = 0; y < height; y++)
    	{
    		from_pos = from_bmp + y * bpsl_from;
    		h_add = ((height - 1) - y) * 3;
    		
    		for(x = 0; x < width; x++)
    		{
    			to_pos = to_bmp + x * bpsl_to + h_add;
    			
    			*(to_pos++) = *(from_pos++);
    			*(to_pos++) = *(from_pos++);
    			*(to_pos++) = *(from_pos++);
    		}
    	}
    }
    And the Visual Basic code & declarations:
    VB Code:
    1. Option Explicit
    2.  
    3. Private Declare Function GetTickCount Lib "kernel32" () As Long
    4.  
    5. Private Declare Function BytesPerScanLine2 Lib "BitmapStuff.dll" Alias "BytesPerScanLine" (ByVal Width As Long, ByVal BitCount As Integer) As Long
    6. Private Declare Function RotateBMPData_CW Lib "BitmapStuff.dll" (ByVal ptrFromData As Long, ByVal Width As Long, ByVal Height As Long, ByVal ptrToData As Long) As Long
    7. Private Declare Function RotateBMPData_CCW Lib "BitmapStuff.dll" (ByVal ptrFromData As Long, ByVal Width As Long, ByVal Height As Long, ByVal ptrToData As Long) As Long
    8.  
    9. Private Sub Form_Load()
    10.     Dim StartTick As Long
    11.    
    12.     Picture1.AutoRedraw = True
    13.     Picture1.Picture = LoadPicture(App.Path & "\Test.jpg")
    14.    
    15.     StartTick = GetTickCount
    16.    
    17.     RotatePic Picture1, Picture2
    18.    
    19.     Debug.Print "Time: " & GetTickCount - StartTick
    20. End Sub
    21.  
    22. Private Sub RotatePic(FromPic As PictureBox, ToPic As PictureBox)
    23.     Dim BitData() As Byte, DestBitData() As Byte
    24.     Dim NewSize As Long
    25.    
    26.     FromPic.ScaleMode = vbPixels
    27.     GetBitmapData FromPic.hdc, FromPic.ScaleWidth, FromPic.ScaleHeight, BitData
    28.    
    29.     ' reverse width & height
    30.     NewSize = FromPic.ScaleWidth * BytesPerScanLine2(FromPic.ScaleHeight, 24)
    31.     ReDim DestBitData(NewSize - 1)
    32.    
    33.     RotateBMPData_CW VarPtr(BitData(0)), FromPic.ScaleWidth, FromPic.ScaleHeight, VarPtr(DestBitData(0))
    34.     'RotateBMPData_CCW VarPtr(BitData(0)), FromPic.ScaleWidth, FromPic.ScaleHeight, VarPtr(DestBitData(0))
    35.    
    36.     ToPic.AutoRedraw = True
    37.     SetBitmapData ToPic.hdc, FromPic.ScaleHeight, FromPic.ScaleWidth, VarPtr(DestBitData(0))
    38. End Sub

    I also attached the C++ project with the DLL (In case you don't have the compiler handy)
    I made the C++ project in Visual C++ 6.0, this way you can open it even in newer Visual Studio versions

    Tell me if you need more help...
    Attached Files Attached Files
    Last edited by CVMichael; May 12th, 2005 at 07:51 PM.

  29. #29
    Old Member moeur's Avatar
    Join Date
    Nov 2004
    Location
    Wait'n for Free Stuff
    Posts
    2,712

    Re: Bitmap rotation: doing it in vc++?

    Nice bit of code
    I played around with the VB version and have a few suggestions
    1. The line you changed to fix the flipping problem slowed it down on my computer by a factor of 3 so I went back to the original code and flipped the final image with a paintpicture. You have to paint the picture anyway if you want VB to recognize it.
    2. It may speed things up if you use a copymemory API call in the loop
    3. I also added a line to resize the ToPic
    VB Code:
    1. For Y = 0 To FromPic.ScaleHeight - 1
    2.         FromPos = Y * BpslFrom
    3.        
    4.         For X = 0 To (FromPic.ScaleWidth - 1) * 3 Step 3
    5.             [COLOR=Red]ToPos = (X \ 3) * BpslTo + Y * 3[/COLOR]
    6.             'ToPos = (X \ 3) * BpslTo + ((FromPic.ScaleHeight - 1) - Y) * 3 'CCW
    7.             'ToPos = ((FromPic.ScaleWidth - 1) - (X \ 3)) * BpslTo + Y * 3 'CW
    8.             [COLOR=Red]CopyMemory DestBitData(ToPos), BitData(FromPos + X), 3[/COLOR]
    9.             'DestBitData(ToPos + 0) = BitData(FromPos + X + 0)
    10.             'DestBitData(ToPos + 1) = BitData(FromPos + X + 1)
    11.             'DestBitData(ToPos + 2) = BitData(FromPos + X + 2)
    12.         Next X
    13.     Next Y
    14.    
    15.     ToPic.AutoRedraw = True
    16.     [COLOR=Red]ToPic.Move ToPic.Left, ToPic.Top, FromPic.Height, FromPic.Width[/COLOR]
    17.     SetBitmapData ToPic.hdc, FromPic.ScaleHeight, FromPic.ScaleWidth, VarPtr(DestBitData(0))
    18.    
    19. [COLOR=Red]    Set ToPic.Picture = ToPic.Image
    20.     ToPic.PaintPicture ToPic.Picture, 0, ToPic.Height, ToPic.Width, -ToPic.Height[/COLOR]

  30. #30
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Bitmap rotation: doing it in vc++?

    Not bat moeur, the VB code does it in 80 ms now... (on the same winnt.bmp picture)

    Thanks...

    [edit]Since there are so many posts in this thread, I won't make a new one..

    Anyways, i tested the C++ compared to VB, For a picture of Width=2000, Height=3008, and ran the code 2 times for each...
    In VB (with moeur's addition):
    Time: 9894
    Time: 9804

    In C++
    Time: 2614
    Time: 2524
    Last edited by CVMichael; May 12th, 2005 at 11:25 PM.

  31. #31

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Bitmap rotation: doing it in vc++?

    Quote Originally Posted by CVMichael
    Hehe, what a stupid mistake... I forgot to add "Step 3" to the For Loop, line:
    VB Code:
    1. For X = 0 To (FromPic.ScaleWidth - 1) * 3 [b]Step 3[/b]
    Now it takes half the time in VB...
    Good morning. The lack of that "step 3" also resulted in slightly wrong rotated images though I hadn't as yet noticed because I was first trying with grayscale images.
    Attached Images Attached Images  
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

  32. #32

    Thread Starter
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573

    Re: Bitmap rotation: doing it in vc++?

    CVMichael, that's really great stuff.

    I've been testing it on an old computer (one that really sucks) for 2 bitmaps:
    1. (651 rows x 621 columns)
    With Setpixels: 1950 ms
    With your code in VB: 750 ms
    With your code in VC++: 208 ms
    2. (1189 rows x 1405 columns)
    With Setpixels: 9532 ms
    With your code in VB: 5699 ms
    With your code in VC++: 1001 ms

    I was going to rate you up but I couldn't... because I already did
    Lottery is a tax on people who are bad at maths
    If only mosquitoes sucked fat instead of blood...
    To do is to be (Descartes). To be is to do (Sartre). To be do be do (Sinatra)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width