www.pudn.com > imagescale---raw.zip > BasDIB.bas
Attribute VB_Name = "BasDIB"
Option Explicit
Public Const CW_USEDEFAULT As Long = &H80000000
'## 位图创建 ###################################
'== Fun ========================================
'CreateDIBSection 创建一个DIBSection。这是一个GDI对象,可象一幅与设备有关位图那样使用。但是,它在内部作为一幅与设备无关位图保存。返回值:Long,执行成功返回DIBSection位图的句柄,零表示失败。会设置GetLastError
'LoadImage 载入一个位图、图标或指针
Public Declare Function CreateDIBSection Lib "gdi32" (ByVal hDC As Long, pBitmapInfo As Any, ByVal un As Long, lplpVoid As Long, ByVal handle As Long, ByVal dw As Long) As Long
Public 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
'== Const ======================================
Public Const DIB_RGB_COLORS = 0 'BITMAPINFO包含了一个颜色表,其中保存有32位颜色(RGBQUAD)
Public Const DIB_PAL_COLORS = 1 'BITMAPINFO包含了一个16位调色板索引的数组
Public Const IMAGE_BITMAP As Long = 0 '
Public Const IMAGE_ICON As Long = 1 '
Public Const IMAGE_CURSOR As Long = 2 '
Public Const IMAGE_ENHMETAFILE As Long = 3 '
Public Const LR_DEFAULTCOLOR As Long = &H0 '以常规方式载入图象
Public Const LR_MONOCHROME As Long = &H1 '将图象转换成单色
Public Const LR_COLOR As Long = &H2 '
Public Const LR_COPYRETURNORG As Long = &H4 'Creates an exact copy of the image, ignoring the cxDesired and cyDesired parameters.
Public Const LR_COPYDELETEORG As Long = &H8 'Deletes the original image after creating the copy.
Public Const LR_LOADFROMFILE As Long = &H10 '如hInst为零,lpsz就代表要载入适当类型的一个文件的名字,仅适用于Win95
Public Const LR_LOADTRANSPARENT As Long = &H20 '与图象中第一个像素相符的所有像素都由系统替换
Public Const LR_DEFAULTSIZE As Long = &H40 '不对图象进行缩放处理。忽略n1和n2的设置
Public Const LR_VGACOLOR As Long = &H80 '使用真彩色?Uses true VGA colors.
Public Const LR_LOADMAP3DCOLORS As Long = &H1000 '将图象中的深灰、灰、以及浅灰像素都替换成COLOR_3DSHADOW,COLOR_3DFACE以及COLOR_3DLIGHT的当前设置
Public Const LR_CREATEDIBSECTION As Long = &H2000 '如果指定了IMAGE_BITMAP,就返回DIBSection的句柄,而不是位图的句柄
Public Const LR_COPYFROMRESOURCE As Long = &H4000 'Tries to reload an icon or cursor resource from the original resource file rather than simply copying the current image. This is useful for creating a different-sized copy when the resource file contains multiple sizes of the resource. Without this flag, CopyImage stretches the original image to the new size. If this flag is set, CopyImage uses the size in the resource file closest to the desired size.
Public Const LR_SHARED As Long = &H8000 '将图象作为一个共享资源载入。在NT 4.0中装载固有资源时要用到这个设置
'## 位图属性 ###################################
'== Fun ========================================
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 Any, ByVal wUsage As Long) As Long
Public Declare Function StretchDIBits 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 wSrcWidth As Long, ByVal wSrcHeight As Long, lpBits As Any, lpBitsInfo As Any, ByVal wUsage As Long, ByVal dwRop As Long) As Long
Public Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
Public Declare Function GetDIBColorTable Lib "gdi32" (ByVal hDC As Long, ByVal un1 As Long, ByVal un2 As Long, pRGBQuad As RGBQuad) As Long
Public Declare Function SetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
Public Declare Function SetDIBColorTable Lib "gdi32" (ByVal hDC As Long, ByVal un1 As Long, ByVal un2 As Long, pcRGBQuad As RGBQuad) As Long
'## Other ######################################
Public Type BITMAPFILEHEADER
bfType(1 To 2) As Byte
bfSize As Long
bfReserved1 As Integer
bfReserved2 As Integer
bfOffBits As Long
End Type
Public Type BitMapInfoHeader
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
Public Const BI_RGB As Long = 0&
Public Const BI_RLE8 As Long = 1&
Public Const BI_RLE4 As Long = 2&
Public Const BI_BitFields As Long = 3&
Public Const BI_JPEG As Long = 4&
Public Const BI_PNG As Long = 5&
Public Type RGBQuad
rgbBlue As Byte
rgbGreen As Byte
rgbRed As Byte
rgbReserved As Byte
End Type
Public Type BitMapInfo
bmiHeader As BitMapInfoHeader
bmiColors(0 To &HFF) As RGBQuad
End Type
'##################################################
Public Enum ScaleModeConst
SMC_Min = 0
SMC_Nearest = 0 '最邻近插值
SMC_StretchBlt = 1 'StretchBlt
SMC_BiliNear = 2 '双线性内插值
SMC_ThreeOrder = 3 '三次卷积法
SMC_Max = 3
End Enum
Public Function GetWidthBytes(ByVal Width As Long, ByVal ColorBits As Long) As Long
If Width <= 0 Then
GetWidthBytes = 0
Exit Function
End If
Select Case ColorBits
Case 1, 4, 8, 16, 24, 32
Dim TempNum As Long
If ColorBits < 8 Then
TempNum = (Width * ColorBits + 7) \ 8
Else
TempNum = Width * (ColorBits \ 8)
End If
GetWidthBytes = (TempNum + 3) And &H7FFFFFFC
Case Else
GetWidthBytes = 0
End Select
End Function
Public Function DIBLoadMap(ByRef dDIB As ClsDIB, FileName As String, Optional ByVal AutoSize As Boolean = True, Optional ByVal CBit As Long = 24) As Boolean
Dim hMap As Long
Dim hDC As Long
Dim hOldMap As Long
Dim TempPic As IPictureDisp
Dim BM As BitMap
If dDIB Is Nothing Then Set dDIB = New ClsDIB
If dDIB.hDC = 0 Then AutoSize = True
If AutoSize Then
If CBit = 16 Or CBit = 24 Or CBit = 32 Then
Else
Exit Function
End If
End If
'Debug.Print AutoSize
hMap = LoadImage(0, FileName, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE Or LR_CREATEDIBSECTION)
If hMap Then
'
Else
On Error Resume Next
Set TempPic = LoadPicture(FileName)
On Error GoTo 0
If TempPic Is Nothing Then
Else
If TempPic.Type = vbPicTypeBitmap Then
hMap = TempPic.handle
Else
Set TempPic = Nothing
End If
End If
End If
If hMap Then
hDC = CreateCompatibleDC(0)
If hDC = 0 Then GoTo FreeMe
GetObjectAPI hMap, Len(BM), BM
If AutoSize Then
If dDIB.Create(BM.bmWidth, BM.bmHeight, CBit, False) Then
Else
GoTo FreeMe
End If
End If
hOldMap = SelectObject(hDC, hMap)
SetStretchBltMode dDIB.hDC, STRETCH_HALFTONE
StretchBlt dDIB.hDC, 0, 0, dDIB.Width, dDIB.Height, hDC, 0, 0, BM.bmWidth, BM.bmHeight, vbSrcCopy
Call SelectObject(hDC, hOldMap)
DIBLoadMap = True
End If
FreeMe:
If hDC Then DeleteDC hDC
If TempPic Is Nothing Then DeleteObject hMap
Set TempPic = Nothing
End Function
Public Function ScaleModeName(ByVal ScaleMode As ScaleModeConst) As String
Dim s As String
Select Case ScaleMode
Case ScaleModeConst.SMC_Nearest
s = "最邻近插值"
Case ScaleModeConst.SMC_StretchBlt
s = "StretchBlt"
Case ScaleModeConst.SMC_BiliNear
s = "双线性内插值"
Case ScaleModeConst.SMC_ThreeOrder
s = "三次卷积法"
End Select
ScaleModeName = s
End Function
Private Function Sinxx(ByVal X As Single) As Single
X = Abs(X)
If X < 1 Then
Sinxx = 1 - 2 * X * X + X * X * X
ElseIf X < 2 Then
Sinxx = 4 - 8 * X + 5 * X * X - X * X * X
Else
Sinxx = 0
End If
End Function
Public Function DIBScale(ByVal ScaleMode As ScaleModeConst, _
ByVal dDIB As ClsDIB, ByVal sDIB As ClsDIB, _
ByVal Width As Long, ByVal Height As Long) As Boolean
If sDIB Is Nothing Then Exit Function
If sDIB.DataPtr = 0 Then Exit Function
If sDIB.ColorBit <> 24 Then Exit Function
If Width < 2 Then Exit Function
If Height < 2 Then Exit Function
If ScaleMode < SMC_Min Or ScaleMode > SMC_Max Then Exit Function
If dDIB Is Nothing Then Set dDIB = New ClsDIB
If dDIB.Create(Width, Height, 24, False) = False Then Exit Function
If Width = sDIB.Width And Height = sDIB.Height Then
CopyMemory ByVal dDIB.DataPtr, ByVal sDIB.DataPtr, sDIB.DataSize
DIBScale = True
Exit Function
End If
Dim pMapData() As Byte
Dim pMapDataInfo As SAFEARRAY1
pMapDataInfo.cDims = 1
pMapDataInfo.fFeatures = 0
pMapDataInfo.cbElements = 1
pMapDataInfo.cLocks = 0
pMapDataInfo.pvData = 0
pMapDataInfo.CE0 = 12
pMapDataInfo.LB0 = 0
pLongAllPtr(0) = VarPtrArray(pMapData)
pLongAll(0) = VarPtr(pMapDataInfo)
Dim sMaxX As Long, sMaxY As Long
Dim dMaxX As Long, dMaxY As Long
sMaxX = sDIB.Width - 1
sMaxY = sDIB.Height - 1
dMaxX = dDIB.Width - 1
dMaxY = dDIB.Height - 1
Dim sPtr As Long, dPtr As Long
Dim sLineBytes As Long, dLineBytes As Long
sPtr = sDIB.DataPtr
dPtr = dDIB.DataPtr
sLineBytes = sDIB.WidthBytes
dLineBytes = dDIB.WidthBytes
Dim sPixelAdd As Long, sLineAdd As Long
Dim dPixelAdd As Long, dLineAdd As Long
sPixelAdd = 3
sLineAdd = sLineBytes - sDIB.Width * sPixelAdd
dPixelAdd = 3
dLineAdd = dLineBytes - dDIB.Width * dPixelAdd
Dim X As Single, Y As Single
Dim nX As Long, nY As Long
Dim u As Single, v As Single
Dim u_ As Single, v_ As Single
Dim LinenX() As Long
Dim Lineu() As Single
Dim I As Long, J As Long
Dim fI As Long, fJ As Long
Dim LinePtr(0 To 3) As Long
Dim CurPtr As Long, CurIdx As Long
Dim OldX As Long, OldY As Long
Dim TempLng As Long
Select Case ScaleMode
Case ScaleModeConst.SMC_Nearest
ReDim LinenX(0 To dMaxX)
For I = 0 To dMaxX
LinenX(I) = I * sMaxX \ dMaxX
Next I
OldY = -2
p3Byte0Ptr(0) = dPtr
For I = 0 To dMaxY
'Y = I * sMaxY / dMaxY
'nY = Int(Y + FloatMinNum)
nY = I * sMaxY \ dMaxY
If nY = OldY Then
CopyMemory ByVal p3Byte0Ptr(0), ByVal p3Byte0Ptr(0) - dLineBytes, dLineBytes
p3Byte0Ptr(0) = p3Byte0Ptr(0) + dLineBytes
Else
OldY = nY
p3Byte1Ptr(0) = sPtr + nY * sLineBytes
OldX = 0
For J = 0 To dMaxX
'nX = J * sMaxX \ dMaxX
nX = LinenX(J)
If nX > OldX Then
p3Byte1Ptr(0) = p3Byte1Ptr(0) + (nX - OldX) * sPixelAdd
OldX = nX
End If
p3Byte0(0) = p3Byte1(0)
p3Byte0(1) = p3Byte1(1)
p3Byte0(2) = p3Byte1(2)
p3Byte0Ptr(0) = p3Byte0Ptr(0) + dPixelAdd
Next J
p3Byte0Ptr(0) = p3Byte0Ptr(0) + dLineAdd
End If
Next I
Case ScaleModeConst.SMC_StretchBlt
SetStretchBltMode dDIB.hDC, STRETCH_HALFTONE
StretchBlt dDIB.hDC, 0, 0, dDIB.Width, dDIB.Height, sDIB.hDC, 0, 0, sDIB.Width, sDIB.Height, vbSrcCopy
Case ScaleModeConst.SMC_BiliNear
Dim MapData(0 To 1, 0 To 1, 0 To 2) As Long
Dim Lineu_() As Single
ReDim LinenX(0 To dMaxX)
ReDim Lineu(0 To dMaxX)
ReDim Lineu_(0 To dMaxX)
For I = 0 To dMaxX
X = I * sMaxX / dMaxX
nX = Int(X)
LinenX(I) = nX
u = X - nX
Lineu(I) = u
Lineu_(I) = 1 - u
Next I
OldX = -1
p3Byte0Ptr(0) = dPtr
For I = 0 To dMaxY
Y = I * sMaxY / dMaxY
nY = Int(Y)
v = Y - nY
v_ = 1 - v
LinePtr(0) = sPtr + nY * sLineBytes
If I = dMaxY Then
LinePtr(1) = LinePtr(0)
Else
LinePtr(1) = LinePtr(0) + sLineBytes
End If
For J = 0 To dMaxX
'X = J * sMaxX / dMaxX
'nX = Int(X)
'u = X - nX
nX = LinenX(J)
u = Lineu(J)
'u_ = 1 - u
u_ = Lineu_(J)
If OldX <> nX Then
CurPtr = nX * sPixelAdd
'For fI = 0 To 1
' pMapDataInfo.pvData = LinePtr(fI) + CurPtr
' 'CurIdx = 0
' 'For fJ = 0 To 1
' ' MapData(fJ, fI, 0) = pMapData(CurIdx)
' ' MapData(fJ, fI, 1) = pMapData(CurIdx + 1)
' ' MapData(fJ, fI, 2) = pMapData(CurIdx + 2)
' ' CurIdx = CurIdx + sPixelAdd
' 'Next fJ
' MapData(0, fI, 0) = pMapData(0)
' MapData(0, fI, 1) = pMapData(1)
' MapData(0, fI, 2) = pMapData(2)
' MapData(1, fI, 0) = pMapData(3)
' MapData(1, fI, 1) = pMapData(4)
' MapData(1, fI, 2) = pMapData(5)
'Next fI
If nX < sMaxX Then
pMapDataInfo.pvData = LinePtr(0) + CurPtr
MapData(0, 0, 0) = pMapData(0)
MapData(0, 0, 1) = pMapData(1)
MapData(0, 0, 2) = pMapData(2)
MapData(1, 0, 0) = pMapData(3)
MapData(1, 0, 1) = pMapData(4)
MapData(1, 0, 2) = pMapData(5)
pMapDataInfo.pvData = LinePtr(1) + CurPtr
MapData(0, 1, 0) = pMapData(0)
MapData(0, 1, 1) = pMapData(1)
MapData(0, 1, 2) = pMapData(2)
MapData(1, 1, 0) = pMapData(3)
MapData(1, 1, 1) = pMapData(4)
MapData(1, 1, 2) = pMapData(5)
Else
pMapDataInfo.pvData = LinePtr(0) + CurPtr
MapData(0, 0, 0) = pMapData(0)
MapData(0, 0, 1) = pMapData(1)
MapData(0, 0, 2) = pMapData(2)
MapData(1, 0, 0) = pMapData(0)
MapData(1, 0, 1) = pMapData(1)
MapData(1, 0, 2) = pMapData(2)
pMapDataInfo.pvData = LinePtr(1) + CurPtr
MapData(0, 1, 0) = pMapData(0)
MapData(0, 1, 1) = pMapData(1)
MapData(0, 1, 2) = pMapData(2)
MapData(1, 1, 0) = pMapData(0)
MapData(1, 1, 1) = pMapData(1)
MapData(1, 1, 2) = pMapData(2)
End If
OldX = nX
End If
'For fI = 0 To 2
' p3Byte0(fI) = (MapData(0, 0, fI) * u_ + MapData(0, 1, fI) * u) * v_ + (MapData(1, 0, fI) * u_ + MapData(1, 1, fI) * u) * v
'Next fI
p3Byte0(0) = (MapData(0, 0, 0) * u_ + MapData(1, 0, 0) * u) * v_ + (MapData(0, 1, 0) * u_ + MapData(1, 1, 0) * u) * v
p3Byte0(1) = (MapData(0, 0, 1) * u_ + MapData(1, 0, 1) * u) * v_ + (MapData(0, 1, 1) * u_ + MapData(1, 1, 1) * u) * v
p3Byte0(2) = (MapData(0, 0, 2) * u_ + MapData(1, 0, 2) * u) * v_ + (MapData(0, 1, 2) * u_ + MapData(1, 1, 2) * u) * v
p3Byte0Ptr(0) = p3Byte0Ptr(0) + dPixelAdd
Next J
p3Byte0Ptr(0) = p3Byte0Ptr(0) + dLineAdd
Next I
Case ScaleModeConst.SMC_ThreeOrder
Dim MatrixA(0 To 3) As Single
Dim MatrixB(0 To 3, 0 To 3, 0 To 2) As Byte
Dim MatrixC(0 To 3) As Single
Dim MatrixT(0 To 3, 0 To 2) As Single
Dim TempSng As Single
'Dim xAdd(0 To 3) As Long
Dim yAdd(0 To 3) As Long
ReDim LinenX(0 To dMaxX)
ReDim Lineu(0 To dMaxX)
For I = 0 To dMaxX
X = I * sMaxX / dMaxX
nX = Int(X)
LinenX(I) = nX
Lineu(I) = X - nX
Next I
Dim ThisLinePixelAdd(0 To 3) As Long
Dim LinePixelAdd() As Long
ReDim LinePixelAdd(-1 To sMaxX + 2)
For I = 0 To sMaxX
LinePixelAdd(I) = I * sPixelAdd
Next I
LinePixelAdd(-1) = 0
LinePixelAdd(sMaxX + 1) = LinePixelAdd(sMaxX)
LinePixelAdd(sMaxX + 2) = LinePixelAdd(sMaxX)
OldX = -1
p3Byte0Ptr(0) = dPtr
For I = 0 To dMaxY
Y = I * sMaxY / dMaxY
nY = Int(Y)
v = Y - nY
'For fI = 0 To 3
' MatrixA(fI) = Sinxx(fI - 1 - v)
'Next fI
TempSng = 1 + v
MatrixA(0) = 4 - 8 * TempSng + 5 * TempSng * TempSng - TempSng * TempSng * TempSng
MatrixA(1) = 1 - 2 * v * v + v * v * v
TempSng = 1 - v
MatrixA(2) = 1 - 2 * TempSng * TempSng + TempSng * TempSng * TempSng
TempSng = 2 - v
MatrixA(3) = 4 - 8 * TempSng + 5 * TempSng * TempSng - TempSng * TempSng * TempSng
yAdd(0) = IIf(nY > 0, -1, 0)
yAdd(1) = 0
If nY < sMaxY - 1 Then
yAdd(2) = 1
yAdd(3) = 2
ElseIf nY < sMaxY Then
yAdd(2) = 1
yAdd(3) = 1
Else
yAdd(2) = 0
yAdd(3) = 0
End If
For fI = 0 To 3
LinePtr(fI) = sPtr + (nY + yAdd(fI)) * sLineBytes
Next fI
For J = 0 To dMaxX
'X = J * sMaxX / dMaxX
'nX = Int(X)
'u = X - nX
nX = LinenX(J)
u = Lineu(J)
'For fI = 0 To 3
' MatrixC(fI) = Sinxx(fI - 1 - u)
'Next fI
TempSng = 1 + u
MatrixC(0) = 4 - 8 * TempSng + 5 * TempSng * TempSng - TempSng * TempSng * TempSng
MatrixC(1) = 1 - 2 * u * u + u * u * u
TempSng = 1 - u
MatrixC(2) = 1 - 2 * TempSng * TempSng + TempSng * TempSng * TempSng
TempSng = 2 - u
MatrixC(3) = 4 - 8 * TempSng + 5 * TempSng * TempSng - TempSng * TempSng * TempSng
If nX <> OldX Then
CurIdx = nX
ThisLinePixelAdd(0) = LinePixelAdd(CurIdx) - LinePixelAdd(CurIdx - 1)
CurIdx = CurIdx + 1
ThisLinePixelAdd(1) = LinePixelAdd(CurIdx) - LinePixelAdd(CurIdx - 1)
CurIdx = CurIdx + 1
ThisLinePixelAdd(2) = LinePixelAdd(CurIdx) - LinePixelAdd(CurIdx - 1)
CurPtr = LinePixelAdd(nX - 1)
For fI = 0 To 3
pMapDataInfo.pvData = LinePtr(fI) + CurPtr
For fJ = 0 To 3
MatrixB(fJ, fI, 0) = pMapData(0)
MatrixB(fJ, fI, 1) = pMapData(1)
MatrixB(fJ, fI, 2) = pMapData(2)
pMapDataInfo.pvData = pMapDataInfo.pvData + ThisLinePixelAdd(fJ)
Next fJ
Next fI
For fI = 0 To 2
MatrixT(0, fI) = MatrixA(0) * MatrixB(0, 0, fI) + MatrixA(1) * MatrixB(0, 1, fI) + MatrixA(2) * MatrixB(0, 2, fI) + MatrixA(3) * MatrixB(0, 3, fI)
MatrixT(1, fI) = MatrixA(0) * MatrixB(1, 0, fI) + MatrixA(1) * MatrixB(1, 1, fI) + MatrixA(2) * MatrixB(1, 2, fI) + MatrixA(3) * MatrixB(1, 3, fI)
MatrixT(2, fI) = MatrixA(0) * MatrixB(2, 0, fI) + MatrixA(1) * MatrixB(2, 1, fI) + MatrixA(2) * MatrixB(2, 2, fI) + MatrixA(3) * MatrixB(2, 3, fI)
MatrixT(3, fI) = MatrixA(0) * MatrixB(3, 0, fI) + MatrixA(1) * MatrixB(3, 1, fI) + MatrixA(2) * MatrixB(3, 2, fI) + MatrixA(3) * MatrixB(3, 3, fI)
Next fI
OldX = nX
End If
For fI = 0 To 2
TempLng = MatrixT(0, fI) * MatrixC(0) + MatrixT(1, fI) * MatrixC(1) + MatrixT(2, fI) * MatrixC(2) + MatrixT(3, fI) * MatrixC(3)
If TempLng >= 0 And TempLng <= &HFF Then
p3Byte0(fI) = TempLng
ElseIf TempLng < 0 Then
p3Byte0(fI) = 0
Else
p3Byte0(fI) = &HFF
End If
Next fI
p3Byte0Ptr(0) = p3Byte0Ptr(0) + dPixelAdd
Next J
p3Byte0Ptr(0) = p3Byte0Ptr(0) + dLineAdd
Next I
End Select
pLongAllPtr(0) = VarPtrArray(pMapData)
pLongAll(0) = 0
DIBScale = True
End Function