vbAccelerator - Contents of code file: cDIBSectionSave.clsVERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "cDIBSectionSave"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal
hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As
Long
Private Declare Function CreateDCAsNull Lib "gdi32" Alias "CreateDCA" (ByVal
lpDriverName As String, lpDeviceName As Any, lpOutput As Any, lpInitData As
Any) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As
Long
Private Type BITMAPINFOHEADER '40 bytes
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Type BITMAPINFO2
bmiHeader As BITMAPINFOHEADER
bmiColors(0 To 1) As RGBQUAD
End Type
Private Type BITMAPINFO16
bmiHeader As BITMAPINFOHEADER
bmiColors(0 To 15) As RGBQUAD
End Type
Private Type BITMAPINFO256
bmiHeader As BITMAPINFOHEADER
bmiColors(0 To 255) As RGBQUAD
End Type
Private Type BITMAP
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
Private Const BI_RGB = 0&
Private Const BI_RLE4 = 2&
Private Const BI_RLE8 = 1&
Private Const DIB_RGB_COLORS = 0 ' color table in RGBs
Private Declare Function CreateDIBSection2 Lib "gdi32" Alias "CreateDIBSection"
_
(ByVal hdc As Long, _
pBitmapInfo As BITMAPINFO2, _
ByVal un As Long, _
lplpVoid As Long, _
ByVal handle As Long, _
ByVal dw As Long) As Long
Private Declare Function CreateDIBSection16 Lib "gdi32" Alias
"CreateDIBSection" _
(ByVal hdc As Long, _
pBitmapInfo As BITMAPINFO16, _
ByVal un As Long, _
lplpVoid As Long, _
ByVal handle As Long, _
ByVal dw As Long) As Long
Private Declare Function CreateDIBSection256 Lib "gdi32" Alias
"CreateDIBSection" _
(ByVal hdc As Long, _
pBitmapInfo As BITMAPINFO256, _
ByVal un As Long, _
lplpVoid As Long, _
ByVal handle As Long, _
ByVal dw As Long) As Long
Private Const BITMAPTYPE As Integer = &H4D42
Private Type BITMAPFILEHEADER
bfType As Integer '- type ="BM" i.e &H4D42 - 2
bfSize As Long ' - size in bytes of file - 6
bfReserved1 As Integer ' - reserved, must be 0 - 8
bfReserved2 As Integer ' - reserved, must be 0 - 10
bfOffBits As Long ' offset from this structure to the bitmap bits - 14
End Type
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal
lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As
Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal
dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer
As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long,
lpOverlapped As Any) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long,
lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten
As Long, lpOverlapped As Any) As Long
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long,
ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal
dwMoveMethod As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As
Long
Private Const INVALID_HANDLE_VALUE = -1
Private Const CREATE_ALWAYS = 2
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const FILE_ATTRIBUTE_ARCHIVE = &H20
Private Const FILE_ATTRIBUTE_COMPRESSED = &H800
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10
Private Const FILE_ATTRIBUTE_HIDDEN = &H2
Private Const FILE_ATTRIBUTE_NORMAL = &H80
Private Const FILE_ATTRIBUTE_READONLY = &H1
Private Const FILE_ATTRIBUTE_SYSTEM = &H4
Private Const FILE_ATTRIBUTE_TEMPORARY = &H100
Private Const FILE_BEGIN = 0
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long,
ByVal dwBytes As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As
Long
Private Const GMEM_FIXED = &H0
Private Const GMEM_ZEROINIT = &H40
Private Const GPTR = (GMEM_FIXED Or GMEM_ZEROINIT)
Private Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100
Private Const FORMAT_MESSAGE_ARGUMENT_ARRAY = &H2000
Private Const FORMAT_MESSAGE_FROM_HMODULE = &H800
Private Const FORMAT_MESSAGE_FROM_STRING = &H400
Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Private Const FORMAT_MESSAGE_IGNORE_INSERTS = &H200
Private Const FORMAT_MESSAGE_MAX_WIDTH_MASK = &HFF
Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA"
(ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal
dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments
As Long) As Long
Private Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" (ByVal
hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal
hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As
Long, lpBI As Any, ByVal wUsage As Long) As Long
Private Declare Function CreateDIBitmap Lib "gdi32" (ByVal hdc As Long,
lpInfoHeader As BITMAPINFOHEADER, ByVal dwUsage As Long, lpInitBits As Any,
lpInitInfo As BITMAPINFO256, ByVal wUsage As Long) As Long
Public Sub Save8BitBitmap( _
ByVal sFileName As String, _
ByVal hBmp As Long, _
cP As cPalette, _
Optional ByVal RLEEncoded = False _
)
Dim tBI As BITMAPINFO256
Dim tBM As BITMAP
Dim hDCComp As Long
Dim hMem As Long
Dim lPtrBits As Long
' Set up BITMAPINFO
' Set up the header:
GetObjectAPI hBmp, LenB(tBM), tBM
With tBI.bmiHeader
.biSize = LenB(tBI.bmiHeader)
.biWidth = tBM.bmWidth
.biHeight = tBM.bmHeight
.biPlanes = 1
.biBitCount = 8
.biCompression = IIf(RLEEncoded, BI_RLE8, BI_RGB)
End With
' Set up the palette:
cP.ExtractToRGBQuadArray tBI.bmiColors
' Extract the DIBits
hDCComp = CreateDCAsNull("DISPLAY", ByVal 0&, ByVal 0&, ByVal 0&)
' Find out the size of the buffer:
GetDIBits hDCComp, hBmp, 0, tBI.bmiHeader.biHeight, ByVal 0&, _
tBI, DIB_RGB_COLORS
' Allocate the memory, and get the buffer
If (tBI.bmiHeader.biSizeImage > 0) Then
hMem = GlobalAlloc(GPTR, tBI.bmiHeader.biSizeImage)
lPtrBits = GlobalLock(hMem)
GetDIBits hDCComp, hBmp, 0, tBI.bmiHeader.biHeight, ByVal lPtrBits, _
tBI, DIB_RGB_COLORS
' Save the image:
SaveToBitmap8 tBI, lPtrBits, sFileName
' Clear up the bits
GlobalUnlock hMem
GlobalFree hMem
End If
' Clear up
DeleteDC hDCComp
End Sub
Public Sub Save24BitBitmap( _
ByVal sFileName As String, _
ByVal hBmp As Long _
)
Dim tBIH As BITMAPINFOHEADER
Dim tBM As BITMAP
Dim hDCComp As Long
Dim hMem As Long
Dim lPtrBits As Long
' Set up BITMAPINFO
' Set up the header:
GetObjectAPI hBmp, LenB(tBM), tBM
With tBIH
.biSize = LenB(tBIH)
.biWidth = tBM.bmWidth
.biHeight = tBM.bmHeight
.biPlanes = 1
.biBitCount = 24
.biSizeImage = BytesPerScanLine24(tBM.bmWidth) * tBM.bmHeight
End With
' Extract the DIBits
hDCComp = CreateDCAsNull("DISPLAY", ByVal 0&, ByVal 0&, ByVal 0&)
' Allocate the memory, and get the buffer
If (tBIH.biSizeImage > 0) Then
hMem = GlobalAlloc(GPTR, tBIH.biSizeImage)
lPtrBits = GlobalLock(hMem)
GetDIBits hDCComp, hBmp, 0, tBIH.biHeight, ByVal lPtrBits, _
tBIH, DIB_RGB_COLORS
' Save the image:
SaveToBitmap tBIH, lPtrBits, sFileName
' Clear up the bits
GlobalUnlock hMem
GlobalFree hMem
End If
' Clear up
DeleteDC hDCComp
End Sub
Private Function BytesPerScanLine24(ByVal lWidth As Long) As Long
BytesPerScanLine24 = (lWidth * 3 + 3) And &HFFFFFFFC
End Function
Private Function SaveToBitmap8(ByRef tBI As BITMAPINFO256, ByVal lPtrBits As
Long, ByVal sFileName As String)
Dim tBH As BITMAPFILEHEADER
Dim tRGBQ As RGBQUAD
Dim hFile As Long
Dim lBytesWritten As Long
Dim lSize As Long
Dim lR As Long
Dim bErr As Boolean
Dim hMem As Long, lPtr As Long
Dim lErr As Long
' Prepare the BITMAPFILEHEADER
With tBH
.bfType = BITMAPTYPE
.bfOffBits = 14 + Len(tBI)
.bfSize = .bfOffBits + tBI.bmiHeader.biSizeImage
End With
hFile = CreateFile(sFileName, _
GENERIC_READ Or GENERIC_WRITE, _
ByVal 0&, _
ByVal 0&, _
CREATE_ALWAYS, _
FILE_ATTRIBUTE_NORMAL, _
0)
lErr = Err.LastDllError
If (hFile = INVALID_HANDLE_VALUE) Then
' error
Err.Raise 17, App.EXEName & ".cDIBSection256", ApiError(lErr)
Else
' Writing the BITMAPFILEINFOHEADER is somewhat painful
' due to non-byte alignment of structure...
hMem = GlobalAlloc(GPTR, 14)
lPtr = GlobalLock(hMem)
CopyMemory ByVal lPtr, tBH.bfType, 2
CopyMemory ByVal lPtr + 2, tBH.bfSize, 4
CopyMemory ByVal lPtr + 6, 0&, 4
CopyMemory ByVal lPtr + 10, tBH.bfOffBits, 4
lSize = 14
lR = WriteFile(hFile, ByVal lPtr, lSize, lBytesWritten, ByVal 0&)
GlobalUnlock hMem
GlobalFree hMem
' Add the BITMAPINFOHEADER and colour palette:
bErr = FileErrHandler(lR, lSize, lBytesWritten)
If Not bErr Then
lSize = Len(tBI)
lR = WriteFile(hFile, tBI, lSize, lBytesWritten, ByVal 0&)
bErr = FileErrHandler(lR, lSize, lBytesWritten)
End If
If Not bErr Then
' Its easy to write the bitmap data, though...
lSize = tBI.bmiHeader.biSizeImage
lR = WriteFile(hFile, ByVal lPtrBits, lSize, lBytesWritten, ByVal 0&)
bErr = FileErrHandler(lR, lSize, lBytesWritten)
End If
CloseHandle hFile
SaveToBitmap8 = Not (bErr)
End If
End Function
Private Function SaveToBitmap4(ByRef tBI As BITMAPINFO16, ByVal lPtrBits As
Long, ByVal sFileName As String)
Dim tBH As BITMAPFILEHEADER
Dim tRGBQ As RGBQUAD
Dim hFile As Long
Dim lBytesWritten As Long
Dim lSize As Long
Dim lR As Long
Dim bErr As Boolean
Dim hMem As Long, lPtr As Long
Dim lErr As Long
' Prepare the BITMAPFILEHEADER
With tBH
.bfType = BITMAPTYPE
.bfOffBits = 14 + Len(tBI)
.bfSize = .bfOffBits + tBI.bmiHeader.biSizeImage
End With
hFile = CreateFile(sFileName, _
GENERIC_READ Or GENERIC_WRITE, _
ByVal 0&, _
ByVal 0&, _
CREATE_ALWAYS, _
FILE_ATTRIBUTE_NORMAL, _
0)
lErr = Err.LastDllError
If (hFile = INVALID_HANDLE_VALUE) Then
' error
Err.Raise 17, App.EXEName & ".cDIBSection256", ApiError(lErr)
Else
' Writing the BITMAPFILEINFOHEADER is somewhat painful
' due to non-byte alignment of structure...
hMem = GlobalAlloc(GPTR, 14)
lPtr = GlobalLock(hMem)
CopyMemory ByVal lPtr, tBH.bfType, 2
CopyMemory ByVal lPtr + 2, tBH.bfSize, 4
CopyMemory ByVal lPtr + 6, 0&, 4
CopyMemory ByVal lPtr + 10, tBH.bfOffBits, 4
lSize = 14
lR = WriteFile(hFile, ByVal lPtr, lSize, lBytesWritten, ByVal 0&)
GlobalUnlock hMem
GlobalFree hMem
' Add the BITMAPINFOHEADER and colour palette:
bErr = FileErrHandler(lR, lSize, lBytesWritten)
If Not bErr Then
lSize = Len(tBI)
lR = WriteFile(hFile, tBI, lSize, lBytesWritten, ByVal 0&)
bErr = FileErrHandler(lR, lSize, lBytesWritten)
End If
If Not bErr Then
' Its easy to write the bitmap data, though...
lSize = tBI.bmiHeader.biSizeImage
lR = WriteFile(hFile, ByVal lPtrBits, lSize, lBytesWritten, ByVal 0&)
bErr = FileErrHandler(lR, lSize, lBytesWritten)
End If
CloseHandle hFile
SaveToBitmap4 = Not (bErr)
End If
End Function
Private Function SaveToBitmap1(ByRef tBI As BITMAPINFO2, ByVal lPtrBits As
Long, ByVal sFileName As String)
Dim tBH As BITMAPFILEHEADER
Dim tRGBQ As RGBQUAD
Dim hFile As Long
Dim lBytesWritten As Long
Dim lSize As Long
Dim lR As Long
Dim bErr As Boolean
Dim hMem As Long, lPtr As Long
Dim lErr As Long
' Prepare the BITMAPFILEHEADER
With tBH
.bfType = BITMAPTYPE
.bfOffBits = 14 + Len(tBI)
.bfSize = .bfOffBits + tBI.bmiHeader.biSizeImage
End With
hFile = CreateFile(sFileName, _
GENERIC_READ Or GENERIC_WRITE, _
ByVal 0&, _
ByVal 0&, _
CREATE_ALWAYS, _
FILE_ATTRIBUTE_NORMAL, _
0)
lErr = Err.LastDllError
If (hFile = INVALID_HANDLE_VALUE) Then
' error
Err.Raise 17, App.EXEName & ".cDIBSection256", ApiError(lErr)
Else
' Writing the BITMAPFILEINFOHEADER is somewhat painful
' due to non-byte alignment of structure...
hMem = GlobalAlloc(GPTR, 14)
lPtr = GlobalLock(hMem)
CopyMemory ByVal lPtr, tBH.bfType, 2
CopyMemory ByVal lPtr + 2, tBH.bfSize, 4
CopyMemory ByVal lPtr + 6, 0&, 4
CopyMemory ByVal lPtr + 10, tBH.bfOffBits, 4
lSize = 14
lR = WriteFile(hFile, ByVal lPtr, lSize, lBytesWritten, ByVal 0&)
GlobalUnlock hMem
GlobalFree hMem
' Add the BITMAPINFOHEADER and colour palette:
bErr = FileErrHandler(lR, lSize, lBytesWritten)
If Not bErr Then
lSize = Len(tBI)
lR = WriteFile(hFile, tBI, lSize, lBytesWritten, ByVal 0&)
bErr = FileErrHandler(lR, lSize, lBytesWritten)
End If
If Not bErr Then
' Its easy to write the bitmap data, though...
lSize = tBI.bmiHeader.biSizeImage
lR = WriteFile(hFile, ByVal lPtrBits, lSize, lBytesWritten, ByVal 0&)
bErr = FileErrHandler(lR, lSize, lBytesWritten)
End If
CloseHandle hFile
SaveToBitmap1 = Not (bErr)
End If
End Function
Private Function SaveToBitmap(ByRef tBIH As BITMAPINFOHEADER, ByVal lPtrBits As
Long, ByVal sFileName As String) As Boolean
Dim tBH As BITMAPFILEHEADER
Dim tRGBQ As RGBQUAD
Dim hFile As Long
Dim lBytesWritten As Long
Dim lSize As Long
Dim lR As Long
Dim bErr As Boolean
Dim hMem As Long, lPtr As Long
Dim lErr As Long
' Prepare the BITMAPFILEHEADER
With tBH
.bfType = BITMAPTYPE
.bfOffBits = 14 + Len(tBIH)
.bfSize = .bfOffBits + tBIH.biSizeImage
End With
hFile = CreateFile(sFileName, _
GENERIC_READ Or GENERIC_WRITE, _
ByVal 0&, _
ByVal 0&, _
CREATE_ALWAYS, _
FILE_ATTRIBUTE_NORMAL, _
0)
lErr = Err.LastDllError
If (hFile = INVALID_HANDLE_VALUE) Then
' error
Err.Raise 17, App.EXEName & ".cDIBSection256", ApiError(lErr)
Else
' Writing the BITMAPFILEINFOHEADER is somewhat painful
' due to non-byte alignment of structure...
hMem = GlobalAlloc(GPTR, 14)
lPtr = GlobalLock(hMem)
CopyMemory ByVal lPtr, tBH.bfType, 2
CopyMemory ByVal lPtr + 2, tBH.bfSize, 4
CopyMemory ByVal lPtr + 6, 0&, 4
CopyMemory ByVal lPtr + 10, tBH.bfOffBits, 4
lSize = 14
lR = WriteFile(hFile, ByVal lPtr, lSize, lBytesWritten, ByVal 0&)
GlobalUnlock hMem
GlobalFree hMem
' Add the BITMAPINFOHEADER:
bErr = FileErrHandler(lR, lSize, lBytesWritten)
If Not bErr Then
lSize = Len(tBIH)
lR = WriteFile(hFile, tBIH, lSize, lBytesWritten, ByVal 0&)
bErr = FileErrHandler(lR, lSize, lBytesWritten)
End If
' There is no palette for a truecolour DIB
If Not bErr Then
' Its easy to write the bitmap data, though...
lSize = tBIH.biSizeImage
lR = WriteFile(hFile, ByVal lPtrBits, lSize, lBytesWritten, ByVal 0&)
bErr = FileErrHandler(lR, lSize, lBytesWritten)
End If
CloseHandle hFile
'SavePicture = Not (bErr)
End If
End Function
Private Function ApiError(ByVal e As Long) As String
Dim s As String, c As Long
s = String(256, 0)
c = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM Or _
FORMAT_MESSAGE_IGNORE_INSERTS, _
0, e, 0&, s, Len(s), ByVal 0)
If c Then ApiError = Left$(s, c)
End Function
Private Function FileErrHandler(ByVal lR As Long, ByVal lSize As Long, ByVal
lBytes As Long) As Boolean
If (lR = 0) Or Not (lSize = lBytes) Then
'Err.Raise
FileErrHandler = True
End If
End Function
|
|