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