home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 7_2009-2012.ISO / data / zips / ArtDraw_v_2180655102010.psc / Class / cDIBSection.cls next >
Text File  |  2010-03-29  |  17KB  |  491 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "cDIBSection"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Option Explicit
  15.  
  16. ' ==================================================================
  17. ' FileName:    cDIBSection.cls
  18. ' Author:      Steve McMahon
  19. '
  20. ' A Wrapper around the GDI DIBSection (DIB = Device Independent Bitmap)
  21. ' object.  A DIB gives you full control over colour depth.  The
  22. ' DIBSection object also means that the bitmap bits are allocated
  23. ' into Windows memory, and so can be directly modified by Windows
  24. ' programs.
  25. '
  26. ' This class gives you the control you need in VB over a DIBSection.
  27. '
  28. ' ------------------------------------------------------------------
  29. ' Visit vbAccelerator - advanced, hardcore VB with full source code
  30. ' http://vbaccelerator.com/
  31. ' mailto:steve@vbaccelerator.com
  32. '
  33. ' ==================================================================
  34.  
  35. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
  36.     lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
  37.  
  38. Private Type SAFEARRAYBOUND
  39.     cElements As Long
  40.     lLbound As Long
  41. End Type
  42. Private Type SAFEARRAY2D
  43.     cDims As Integer
  44.     fFeatures As Integer
  45.     cbElements As Long
  46.     cLocks As Long
  47.     pvData As Long
  48.     Bounds(0 To 1) As SAFEARRAYBOUND
  49. End Type
  50. Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long
  51.  
  52. Private Type RGBQUAD
  53.     rgbBlue As Byte
  54.     rgbGreen As Byte
  55.     rgbRed As Byte
  56.     rgbReserved As Byte
  57. End Type
  58. Private Type BITMAPINFOHEADER '40 bytes
  59.     biSize As Long
  60.     biWidth As Long
  61.     biHeight As Long
  62.     biPlanes As Integer
  63.     biBitCount As Integer
  64.     biCompression As Long
  65.     biSizeImage As Long
  66.     biXPelsPerMeter As Long
  67.     biYPelsPerMeter As Long
  68.     biClrUsed As Long
  69.     biClrImportant As Long
  70. End Type
  71. Private Type BITMAPINFO
  72.     bmiHeader As BITMAPINFOHEADER
  73.     bmiColors As RGBQUAD
  74. End Type
  75. Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long) As Long
  76. Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
  77. Private Declare Function GetDesktopWindow Lib "user32" () As Long
  78. ' Note - this is not the declare in the API viewer - modify lplpVoid to be
  79. ' Byref so we get the pointer back:
  80. Private Declare Function CreateDIBSection Lib "gdi32" _
  81.     (ByVal hDC As Long, _
  82.     pBitmapInfo As BITMAPINFO, _
  83.     ByVal un As Long, _
  84.     lplpVoid As Long, _
  85.     ByVal handle As Long, _
  86.     ByVal dw As Long) As Long
  87. Private 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
  88. Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
  89. Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
  90. Private Declare Function DeleteDC Lib "gdi32" (ByVal hDC As Long) As Long
  91. Private Declare Function LoadImage Lib "user32" Alias "LoadImageA" (ByVal hInst As Long, ByVal lpsz As String, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
  92. Private Const BI_RGB = 0&
  93. Private Const BI_RLE4 = 2&
  94. Private Const BI_RLE8 = 1&
  95. Private Const DIB_RGB_COLORS = 0 '  color table in RGBs
  96.  
  97. Private Type BITMAP
  98.     bmType As Long
  99.     bmWidth As Long
  100.     bmHeight As Long
  101.     bmWidthBytes As Long
  102.     bmPlanes As Integer
  103.     bmBitsPixel As Integer
  104.     bmBits As Long
  105. End Type
  106. Private Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
  107. Private Declare Function timeGetTime Lib "winmm.dll" () As Long
  108. Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hDC As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
  109.  
  110. ' Clipboard functions:
  111. Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
  112. Private Declare Function CloseClipboard Lib "user32" () As Long
  113. Private Declare Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As Long) As Long
  114. Private Declare Function EmptyClipboard Lib "user32" () As Long
  115. Private Const CF_BITMAP = 2
  116. Private Const CF_DIB = 8
  117.  
  118. ' Handle to the current DIBSection:
  119. Private m_hDIb As Long
  120. ' Handle to the old bitmap in the DC, for clear up:
  121. Private m_hBmpOld As Long
  122. ' Handle to the Device context holding the DIBSection:
  123. Private m_hDC As Long
  124. ' Address of memory pointing to the DIBSection's bits:
  125. Private m_lPtr As Long
  126. ' Type containing the Bitmap information:
  127. Private m_tBI As BITMAPINFO
  128.  
  129. Public Function CopyToClipboard( _
  130.         Optional ByVal bAsDIB As Boolean = True _
  131.     ) As Boolean
  132. Dim lhDCDesktop As Long
  133. Dim lhDC As Long
  134. Dim lhBmpOld As Long
  135. Dim hObj As Long
  136. Dim lFmt As Long
  137. Dim b() As Byte
  138. Dim tBI As BITMAPINFO
  139. Dim lPtr As Long
  140. Dim hDibCopy As Long
  141.  
  142.     lhDCDesktop = GetDC(GetDesktopWindow())
  143.     If (lhDCDesktop <> 0) Then
  144.         lhDC = CreateCompatibleDC(lhDCDesktop)
  145.         If (lhDC <> 0) Then
  146.             If (bAsDIB) Then
  147.                MsgBox "I don't know how to put a DIB on the clipboard! Copy as bitmap instead!!!"
  148.                 ' Create a duplicate DIBSection and copy
  149.                 ' to the clipboard:
  150.                 'LSet tBI = m_tBI
  151.                 'hDibCopy = CreateDIBSection( _
  152.                 '        lhDC, _
  153.                 '        m_tBI, _
  154.                 '        DIB_RGB_COLORS, _
  155.                 '        lPtr, _
  156.                 '        0, 0)
  157.                 'If (hDibCopy <> 0) Then
  158.                 '    lhBmpOld = SelectObject(lhDC, hObj)
  159.                 '    BitBlt lhDC, 0, 0, Width, Height, m_hDC, 0, 0, vbSrcCopy
  160.                 '    SelectObject lhDC, lhBmpOld
  161.                 '    lFmt = CF_DIB
  162.                 '
  163.                 '     '....
  164.                                     
  165.                 'Else
  166.                 '    hObj = 0
  167.                 'End If
  168.             Else
  169.                 ' Create a compatible bitmap and copy to
  170.                 ' the clipboard:
  171.                 hObj = CreateCompatibleBitmap(lhDCDesktop, Width, Height)
  172.                 If (hObj <> 0) Then
  173.                     lhBmpOld = SelectObject(lhDC, hObj)
  174.                     PaintPicture lhDC
  175.                     SelectObject lhDC, lhBmpOld
  176.                     lFmt = CF_BITMAP
  177.                     ' Now set the clipboard to the bitmap:
  178.                     If (OpenClipboard(0) <> 0) Then
  179.                         EmptyClipboard
  180.                         If (SetClipboardData(lFmt, hObj) <> 0) Then
  181.                             CopyToClipboard = True
  182.                         End If
  183.                         CloseClipboard
  184.                     End If
  185.                 End If
  186.             End If
  187.             DeleteDC lhDC
  188.         End If
  189.         DeleteDC lhDCDesktop
  190.     End If
  191. End Function
  192.  
  193. Public Function CreateDIB( _
  194.         ByVal lhDC As Long, _
  195.         ByVal lWidth As Long, _
  196.         ByVal lHeight As Long, _
  197.         ByRef hDib As Long _
  198.     ) As Boolean
  199.     With m_tBI.bmiHeader
  200.         .biSize = Len(m_tBI.bmiHeader)
  201.         .biWidth = lWidth
  202.         .biHeight = lHeight
  203.         .biPlanes = 1
  204.         .biBitCount = 24
  205.         .biCompression = BI_RGB
  206.         .biSizeImage = BytesPerScanLine * .biHeight
  207.     End With
  208.     hDib = CreateDIBSection( _
  209.             lhDC, _
  210.             m_tBI, _
  211.             DIB_RGB_COLORS, _
  212.             m_lPtr, _
  213.             0, 0)
  214.     CreateDIB = (hDib <> 0)
  215. End Function
  216. Public Function CreateFromPicture( _
  217.         ByRef picThis As StdPicture _
  218.     )
  219. Dim lhDC As Long
  220. Dim lhDCDesktop As Long
  221. Dim lhBmpOld As Long
  222. Dim tBMP As BITMAP
  223.     
  224.     GetObjectAPI picThis.handle, Len(tBMP), tBMP
  225.     If (Create(tBMP.bmWidth, tBMP.bmHeight)) Then
  226.         lhDCDesktop = GetDC(GetDesktopWindow())
  227.         If (lhDCDesktop <> 0) Then
  228.             lhDC = CreateCompatibleDC(lhDCDesktop)
  229.             DeleteDC lhDCDesktop
  230.             If (lhDC <> 0) Then
  231.                 lhBmpOld = SelectObject(lhDC, picThis.handle)
  232.                 LoadPictureBlt lhDC
  233.                 SelectObject lhDC, lhBmpOld
  234.                 DeleteObject lhDC
  235.             End If
  236.         End If
  237.     End If
  238. End Function
  239. Public Function Create( _
  240.         ByVal lWidth As Long, _
  241.         ByVal lHeight As Long _
  242.     ) As Boolean
  243.     ClearUp
  244.     m_hDC = CreateCompatibleDC(0)
  245.     If (m_hDC <> 0) Then
  246.         If (CreateDIB(m_hDC, lWidth, lHeight, m_hDIb)) Then
  247.             m_hBmpOld = SelectObject(m_hDC, m_hDIb)
  248.             Create = True
  249.         Else
  250.             DeleteObject m_hDC
  251.             m_hDC = 0
  252.         End If
  253.     End If
  254. End Function
  255. Public Property Get BytesPerScanLine() As Long
  256.     ' Scans must align on dword boundaries:
  257.     BytesPerScanLine = (m_tBI.bmiHeader.biWidth * 3 + 3) And &HFFFFFFFC
  258. End Property
  259.  
  260. Public Property Get Width() As Long
  261.     Width = m_tBI.bmiHeader.biWidth
  262. End Property
  263. Public Property Get Height() As Long
  264.     Height = m_tBI.bmiHeader.biHeight
  265. End Property
  266.  
  267. Public Sub LoadPictureBlt( _
  268.         ByVal lhDC As Long, _
  269.         Optional ByVal lSrcLeft As Long = 0, _
  270.         Optional ByVal lSrcTop As Long = 0, _
  271.         Optional ByVal lSrcWidth As Long = -1, _
  272.         Optional ByVal lSrcHeight As Long = -1, _
  273.         Optional ByVal eRop As RasterOpConstants = vbSrcCopy _
  274.     )
  275.     If lSrcWidth < 0 Then lSrcWidth = m_tBI.bmiHeader.biWidth
  276.     If lSrcHeight < 0 Then lSrcHeight = m_tBI.bmiHeader.biHeight
  277.     BitBlt m_hDC, 0, 0, lSrcWidth, lSrcHeight, lhDC, lSrcLeft, lSrcTop, eRop
  278. End Sub
  279.  
  280.  
  281. Public Sub PaintPicture( _
  282.         ByVal lhDC As Long, _
  283.         Optional ByVal lDestLeft As Long = 0, _
  284.         Optional ByVal lDestTop As Long = 0, _
  285.         Optional ByVal lDestWidth As Long = -1, _
  286.         Optional ByVal lDestHeight As Long = -1, _
  287.         Optional ByVal lSrcLeft As Long = 0, _
  288.         Optional ByVal lSrcTop As Long = 0, _
  289.         Optional ByVal eRop As RasterOpConstants = vbSrcCopy _
  290.     )
  291.     If (lDestWidth < 0) Then lDestWidth = m_tBI.bmiHeader.biWidth
  292.     If (lDestHeight < 0) Then lDestHeight = m_tBI.bmiHeader.biHeight
  293.     BitBlt lhDC, lDestLeft, lDestTop, lDestWidth, lDestHeight, m_hDC, lSrcLeft, lSrcTop, eRop
  294. End Sub
  295.  
  296. Public Property Get hDC() As Long
  297.     hDC = m_hDC
  298. End Property
  299. Public Property Get hDib() As Long
  300.     hDib = m_hDIb
  301. End Property
  302. Public Property Get DIBSectionBitsPtr() As Long
  303.     DIBSectionBitsPtr = m_lPtr
  304. End Property
  305. Public Sub RandomiseBits( _
  306.         Optional ByVal bGray As Boolean = False _
  307.     )
  308. Dim bDib() As Byte
  309. Dim X As Long, Y As Long
  310. Dim lC As Long
  311. Dim tSA As SAFEARRAY2D
  312. Dim xEnd As Long
  313.     
  314.     ' Get the bits in the from DIB section:
  315.     With tSA
  316.         .cbElements = 1
  317.         .cDims = 2
  318.         .Bounds(0).lLbound = 0
  319.         .Bounds(0).cElements = m_tBI.bmiHeader.biHeight
  320.         .Bounds(1).lLbound = 0
  321.         .Bounds(1).cElements = BytesPerScanLine()
  322.         .pvData = m_lPtr
  323.     End With
  324.     CopyMemory ByVal VarPtrArray(bDib()), VarPtr(tSA), 4
  325.  
  326.     ' random:
  327.     Randomize Timer
  328.     
  329.     xEnd = (Width - 1) * 3
  330.     If (bGray) Then
  331.         For Y = 0 To m_tBI.bmiHeader.biHeight - 1
  332.             For X = 0 To xEnd Step 3
  333.                 lC = Rnd * 255
  334.                 bDib(X, Y) = lC
  335.                 bDib(X + 1, Y) = lC
  336.                 bDib(X + 2, Y) = lC
  337.             Next X
  338.         Next Y
  339.     Else
  340.         For X = 0 To xEnd Step 3
  341.             For Y = 0 To m_tBI.bmiHeader.biHeight - 1
  342.                 bDib(X, Y) = 0
  343.                 bDib(X + 1, Y) = Rnd * 255
  344.                 bDib(X + 2, Y) = Rnd * 255
  345.             Next Y
  346.         Next X
  347.     End If
  348.     
  349.     ' Clear the temporary array descriptor
  350.     ' (This does not appear to be necessary, but
  351.     ' for safety do it anyway)
  352.     CopyMemory ByVal VarPtrArray(bDib), 0&, 4
  353.     
  354. End Sub
  355.  
  356. Public Sub ClearUp()
  357.     If (m_hDC <> 0) Then
  358.         If (m_hDIb <> 0) Then
  359.             SelectObject m_hDC, m_hBmpOld
  360.             DeleteObject m_hDIb
  361.         End If
  362.         DeleteObject m_hDC
  363.     End If
  364.     m_hDC = 0: m_hDIb = 0: m_hBmpOld = 0: m_lPtr = 0
  365. End Sub
  366.  
  367. Public Function Resample( _
  368.         ByVal lNewHeight As Long, _
  369.         ByVal lNewWidth As Long _
  370.     ) As cDIBSection
  371. Dim cDib As cDIBSection
  372.     Set cDib = New cDIBSection
  373.     If cDib.Create(lNewWidth, lNewHeight) Then
  374.         If (lNewWidth <> m_tBI.bmiHeader.biWidth) Or (lNewHeight <> m_tBI.bmiHeader.biHeight) Then
  375.             ' Change in size, do resample:
  376.             ResampleDib cDib
  377.         Else
  378.             ' No size change so just return a copy:
  379.             cDib.LoadPictureBlt m_hDC
  380.         End If
  381.         Set Resample = cDib
  382.     End If
  383. End Function
  384.  
  385. Private Function ResampleDib(ByRef cDibTo As cDIBSection) As Boolean
  386. Dim bDibFrom() As Byte
  387. Dim bDibTo() As Byte
  388.  
  389. Dim tSAFrom As SAFEARRAY2D
  390. Dim tSATo As SAFEARRAY2D
  391.  
  392.     ' Get the bits in the from DIB section:
  393.     With tSAFrom
  394.         .cbElements = 1
  395.         .cDims = 2
  396.         .Bounds(0).lLbound = 0
  397.         .Bounds(0).cElements = m_tBI.bmiHeader.biHeight
  398.         .Bounds(1).lLbound = 0
  399.         .Bounds(1).cElements = BytesPerScanLine()
  400.         .pvData = m_lPtr
  401.     End With
  402.     CopyMemory ByVal VarPtrArray(bDibFrom()), VarPtr(tSAFrom), 4
  403.  
  404.     ' Get the bits in the to DIB section:
  405.     With tSATo
  406.         .cbElements = 1
  407.         .cDims = 2
  408.         .Bounds(0).lLbound = 0
  409.         .Bounds(0).cElements = cDibTo.Height
  410.         .Bounds(1).lLbound = 0
  411.         .Bounds(1).cElements = cDibTo.BytesPerScanLine()
  412.         .pvData = cDibTo.DIBSectionBitsPtr
  413.     End With
  414.     CopyMemory ByVal VarPtrArray(bDibTo()), VarPtr(tSATo), 4
  415.  
  416. Dim xScale As Single
  417. Dim yScale As Single
  418.  
  419. Dim X As Long, Y As Long, xEnd As Long, xOut As Long
  420.  
  421. Dim fX As Single, fY As Single
  422. Dim ifY As Long, ifX As Long
  423. Dim dX As Single, dy As Single
  424. Dim r As Long, r1 As Single, r2 As Single, r3 As Single, r4 As Single
  425. Dim g As Long, g1 As Single, g2 As Single, g3 As Single, g4 As Single
  426. Dim b As Long, b1 As Single, b2 As Single, b3 As Single, b4 As Single
  427. Dim ir1 As Long, ig1 As Long, ib1 As Long
  428. Dim ir2 As Long, ig2 As Long, ib2 As Long
  429.  
  430.     xScale = (Width - 1) / cDibTo.Width
  431.     yScale = (Height - 1) / cDibTo.Height
  432.     
  433.     xEnd = cDibTo.Width - 1
  434.         
  435.     For Y = 0 To cDibTo.Height - 1
  436.         
  437.         fY = Y * yScale
  438.         ifY = Int(fY)
  439.         dy = fY - ifY
  440.         
  441.         For X = 0 To xEnd
  442.             fX = X * xScale
  443.             ifX = Int(fX)
  444.             dX = fX - ifX
  445.             
  446.             ifX = ifX * 3
  447.             ' Interpolate using the four nearest pixels in the source
  448.             b1 = bDibFrom(ifX, ifY): g1 = bDibFrom(ifX + 1, ifY): r1 = bDibFrom(ifX + 2, ifY)
  449.             b2 = bDibFrom(ifX + 3, ifY): g2 = bDibFrom(ifX + 4, ifY): r2 = bDibFrom(ifX + 5, ifY)
  450.             b3 = bDibFrom(ifX, ifY + 1): g3 = bDibFrom(ifX + 1, ifY + 1): r3 = bDibFrom(ifX + 2, ifY + 1)
  451.             b4 = bDibFrom(ifX + 3, ifY + 1): g4 = bDibFrom(ifX + 4, ifY + 1): r4 = bDibFrom(ifX + 5, ifY + 1)
  452.             
  453.             ' Interplate in x direction:
  454.             ir1 = r1 * (1 - dy) + r3 * dy: ig1 = g1 * (1 - dy) + g3 * dy: ib1 = b1 * (1 - dy) + b3 * dy
  455.             ir2 = r2 * (1 - dy) + r4 * dy: ig2 = g2 * (1 - dy) + g4 * dy: ib2 = b2 * (1 - dy) + b4 * dy
  456.             ' Interpolate in y:
  457.             r = ir1 * (1 - dX) + ir2 * dX: g = ig1 * (1 - dX) + ig2 * dX: b = ib1 * (1 - dX) + ib2 * dX
  458.             
  459.             ' Set output:
  460.             If (r < 0) Then r = 0
  461.             If (r > 255) Then r = 255
  462.             If (g < 0) Then g = 0
  463.             If (g > 255) Then g = 255
  464.             If (b < 0) Then b = 0
  465.             If (b > 255) Then
  466.                 b = 255
  467.             End If
  468.             xOut = X * 3
  469.             bDibTo(xOut, Y) = b
  470.             bDibTo(xOut + 1, Y) = g
  471.             bDibTo(xOut + 2, Y) = r
  472.             
  473.         Next X
  474.         
  475.     Next Y
  476.  
  477.     ' Clear the temporary array descriptor
  478.     ' (This does not appear to be necessary, but
  479.     ' for safety do it anyway)
  480.     CopyMemory ByVal VarPtrArray(bDibFrom), 0&, 4
  481.     CopyMemory ByVal VarPtrArray(bDibTo), 0&, 4
  482.  
  483.  
  484. End Function
  485.  
  486. Private Sub Class_Terminate()
  487.     ClearUp
  488. End Sub
  489.  
  490.  
  491.