[Visual Basic] 纯文本查看 复制代码VERSION 5.00
Begin VB.Form frmMain
Caption = "取得调色板"
ClientHeight = 6465
ClientLeft = 120
ClientTop = 450
ClientWidth = 16440
LinkTopic = "frmMain"
OLEDropMode = 1 'Manual
ScaleHeight = 431
ScaleMode = 3 'Pixel
ScaleWidth = 1096
StartUpPosition = 3 '窗口缺省
Begin VB.PictureBox picDither
Align = 3 'Align Left
BorderStyle = 0 'None
Height = 6465
Left = 0
ScaleHeight = 431
ScaleMode = 3 'Pixel
ScaleWidth = 457
TabIndex = 6
Top = 0
Visible = 0 'False
Width = 6855
Begin VB.HScrollBar HSDither
Height = 255
Left = 1440
Max = 0
TabIndex = 12
TabStop = 0 'False
Top = 3000
Width = 2415
End
Begin VB.PictureBox picColor4
AutoRedraw = -1 'True
BackColor = &H00000000&
BorderStyle = 0 'None
Height = 495
Left = 1800
ScaleHeight = 33
ScaleMode = 3 'Pixel
ScaleWidth = 33
TabIndex = 11
Top = 0
Visible = 0 'False
Width = 495
End
Begin VB.PictureBox picColor3
AutoRedraw = -1 'True
BackColor = &H00000000&
BorderStyle = 0 'None
Height = 495
Left = 1200
ScaleHeight = 33
ScaleMode = 3 'Pixel
ScaleWidth = 33
TabIndex = 10
Top = 0
Visible = 0 'False
Width = 495
End
Begin VB.PictureBox picColor2
AutoRedraw = -1 'True
BackColor = &H00000000&
BorderStyle = 0 'None
Height = 495
Left = 600
ScaleHeight = 33
ScaleMode = 3 'Pixel
ScaleWidth = 33
TabIndex = 9
Top = 0
Visible = 0 'False
Width = 495
End
Begin VB.PictureBox picColor1
AutoRedraw = -1 'True
BackColor = &H00000000&
BorderStyle = 0 'None
Height = 495
Left = 0
ScaleHeight = 33
ScaleMode = 3 'Pixel
ScaleWidth = 33
TabIndex = 8
Top = 0
Visible = 0 'False
Width = 495
End
Begin VB.PictureBox picResult
AutoRedraw = -1 'True
BackColor = &H00000000&
BorderStyle = 0 'None
Height = 495
Left = 2400
ScaleHeight = 33
ScaleMode = 3 'Pixel
ScaleWidth = 33
TabIndex = 7
Top = 0
Visible = 0 'False
Width = 495
End
End
Begin VB.PictureBox picRightPanel
Align = 4 'Align Right
BorderStyle = 0 'None
Height = 6465
Left = 15345
ScaleHeight = 431
ScaleMode = 3 'Pixel
ScaleWidth = 73
TabIndex = 0
Top = 0
Width = 1095
Begin VB.PictureBox picProgress
BackColor = &H8000000C&
Height = 255
Left = 0
ScaleHeight = 13
ScaleMode = 3 'Pixel
ScaleWidth = 69
TabIndex = 14
Top = 4320
Width = 1095
Begin VB.CommandButton cmdProgress
Enabled = 0 'False
Height = 195
Left = 0
Style = 1 'Graphical
TabIndex = 15
Top = 0
Width = 1035
End
End
Begin VB.CheckBox ChRandomPalette
Caption = "产生随机调色板"
Height = 615
Left = 0
Style = 1 'Graphical
TabIndex = 13
Top = 3600
Width = 1095
End
Begin VB.PictureBox picPal
AutoRedraw = -1 'True
BackColor = &H00000000&
BorderStyle = 0 'None
Height = 1095
Left = 0
ScaleHeight = 73
ScaleMode = 3 'Pixel
ScaleWidth = 73
TabIndex = 5
Top = 2400
Width = 1095
End
Begin VB.OptionButton OpDitherPic
Caption = "抖动图"
Enabled = 0 'False
Height = 495
Left = 0
Style = 1 'Graphical
TabIndex = 4
Top = 1920
Value = -1 'True
Width = 1095
End
Begin VB.OptionButton OpSrcPic
Caption = "原图"
Enabled = 0 'False
Height = 495
Left = 0
Style = 1 'Graphical
TabIndex = 3
Top = 1440
Width = 1095
End
Begin VB.CommandButton cmdDither
Caption = "抖动"
Enabled = 0 'False
Height = 615
Left = 0
TabIndex = 1
Top = 0
Width = 1095
End
End
Begin VB.PictureBox picSrcPic
AutoRedraw = -1 'True
AutoSize = -1 'True
BorderStyle = 0 'None
Height = 255
Left = 0
ScaleHeight = 255
ScaleWidth = 135
TabIndex = 2
Top = 0
Visible = 0 'False
Width = 135
End
End
Attribute VB_Name = "frmMain"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'==============================================================================
'作者:0xAA55
'论坛:http://www.0xaa55.com/
'版权所有 (C) 2013-2014 技术宅的结界
'请保留原作者信息,否则视为侵权。
'------------------------------------------------------------------------------
Option Explicit
Private Const COLORS_MAX As Long = 256
Private Const COLORS_BITS As Long = 8
Private Const DIST_MAX As Long = 200000
Private Type RGBQUAD
B As Byte
G As Byte
R As Byte
X As Byte
End Type
Private Type BITMAPINFO24
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 BITMAPINFOPAL
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
Palette(COLORS_MAX - 1) As RGBQUAD
End Type
Private Declare Function CreateOctreePaletteFromHBITMAP Lib "..\Octree.dll" (ByVal hDC&, ByVal hBitmap&, ByVal Width&, ByVal Height&, ByVal MaxColors&, ByVal ColorBits&, P As RGBQUAD) As Long
Private Declare Function GetBitmapPitch Lib "..\Octree.dll" (ByVal BitCount As Integer, ByVal Width As Long) As Long
Private Declare Function GetDIBits Lib "gdi32.dll" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO24, ByVal wUsage As Long) As Long
Private Declare Function SetDIBits Lib "gdi32.dll" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFOPAL, ByVal wUsage As Long) As Long
Private Const DIB_RGB_COLORS = 0 ' color table in RGBs
Private Const DIB_PAL_COLORS = 1 ' color table in palette indices
Dim BMIF24 As BITMAPINFO24
Dim BMIFPAL As BITMAPINFOPAL
Dim PW&, PH&
Dim LM() As Byte
Dim QuitLoop As Boolean
Dim SrcPixels() As Byte
Dim Values1() As Byte
Dim Values2() As Byte
Dim Values3() As Byte
Dim Values4() As Byte
Dim Vec1R() As Long, Vec1G() As Long, Vec1B() As Long
Dim Vec2R() As Long, Vec2G() As Long, Vec2B() As Long
Dim Vec3R() As Long, Vec3G() As Long, Vec3B() As Long
Dim Vec4R() As Long, Vec4G() As Long, Vec4B() As Long
Private Const MaxDist As Double = 64
Private Const MaxDistSq As Double = MaxDist * MaxDist
Private Const RefreshInterval As Single = 0.1
Dim ProgWidth As Single
Sub DrawProgress(ByVal Prog As Double)
cmdProgress.Left = (Prog - 1) * ProgWidth
picProgress.Refresh
End Sub
Private Sub cmdDither_Click()
Dim DestPixels() As Byte
Dim Pitch1 As Long, Pitch2 As Long
Dim X&, Y&
Dim I&, LStart1&
Dim L&, LStart2&
Dim K&, DistanceSq As Long, NewDistSq As Long
Dim RDiff As Long, GDiff As Long, BDiff As Long
Dim Tm!, NTm!
cmdDither.Enabled = False
picDither.Visible = True
picDither.Visible = True
Form_Resize
Pitch1 = GetBitmapPitch(24, PW)
Pitch2 = GetBitmapPitch(8, PW)
Erase Values1, Values2, Values3, Values4, SrcPixels
Erase Vec1R, Vec1G, Vec1B
Erase Vec2R, Vec2G, Vec2B
Erase Vec3R, Vec3G, Vec3B
Erase Vec4R, Vec4G, Vec4B
ReDim SrcPixels(Pitch1 * PH - 1)
ReDim DestPixels(Pitch2 * PH - 1)
ReDim Values1(UBound(DestPixels))
ReDim Values2(UBound(DestPixels))
ReDim Values3(UBound(DestPixels))
ReDim Values4(UBound(DestPixels))
ReDim Vec1R(UBound(DestPixels)), Vec1G(UBound(DestPixels)), Vec1B(UBound(DestPixels))
ReDim Vec2R(UBound(DestPixels)), Vec2G(UBound(DestPixels)), Vec2B(UBound(DestPixels))
ReDim Vec3R(UBound(DestPixels)), Vec3G(UBound(DestPixels)), Vec3B(UBound(DestPixels))
ReDim Vec4R(UBound(DestPixels)), Vec4G(UBound(DestPixels)), Vec4B(UBound(DestPixels))
GetDIBits picSrcPic.hDC, picSrcPic.Image.Handle, 0, PH, SrcPixels(0), BMIF24, DIB_RGB_COLORS
'==============================================================================
'步骤1:取得最相近的颜色
'------------------------------------------------------------------------------
LStart1 = 0
LStart2 = 0
picColor1.Visible = True
For Y = 0 To PH - 1
I = LStart1
L = LStart2
For X = 0 To PW - 1
DistanceSq = 255& * 255 * 3
For K = 0 To 255
RDiff = CLng(BMIFPAL.Palette(K).R) - SrcPixels(I + 2)
GDiff = CLng(BMIFPAL.Palette(K).G) - SrcPixels(I + 1)
BDiff = CLng(BMIFPAL.Palette(K).B) - SrcPixels(I + 0)
NewDistSq = RDiff * RDiff + GDiff * GDiff + BDiff * BDiff
If NewDistSq < DistanceSq And NewDistSq <= MaxDistSq Then
Vec1R(L) = RDiff
Vec1G(L) = GDiff
Vec1B(L) = BDiff
Values1(L) = K
DestPixels(L) = K
DistanceSq = NewDistSq
End If
Next
I = I + 3
L = L + 1
Next
NTm = Timer
If NTm - Tm >= RefreshInterval Then
Tm = NTm
SetDIBits picColor1.hDC, picColor1.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
picColor1.PaintPicture picSrcPic.Image, 0, 0, PW, PH - Y, 0, 0, PW, PH - Y
DrawProgress Y / (PH - 1)
picColor1.Refresh
DoEvents
If QuitLoop Then Exit For
End If
LStart1 = LStart1 + Pitch1
LStart2 = LStart2 + Pitch2
Next
SetDIBits picColor1.hDC, picColor1.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
DrawProgress 1
picColor1.Refresh
'==============================================================================
'步骤2:取得和上一步相反的颜色
'------------------------------------------------------------------------------
LStart1 = 0
LStart2 = 0
picColor2.Visible = True
For Y = 0 To PH - 1
I = LStart1
L = LStart2
For X = 0 To PW - 1
DistanceSq = 255& * 255 * 3
Values2(L) = Values1(L)
For K = 0 To 255
RDiff = CLng(BMIFPAL.Palette(K).R) - SrcPixels(I + 2)
GDiff = CLng(BMIFPAL.Palette(K).G) - SrcPixels(I + 1)
BDiff = CLng(BMIFPAL.Palette(K).B) - SrcPixels(I + 0)
If RDiff * Vec1R(L) + GDiff * Vec1G(L) + BDiff * Vec1B(L) < 0 Then
NewDistSq = RDiff * RDiff + GDiff * GDiff + BDiff * BDiff
If NewDistSq < DistanceSq And NewDistSq <= MaxDistSq Then
Vec2R(L) = RDiff
Vec2G(L) = GDiff
Vec2B(L) = BDiff
Values2(L) = K
DestPixels(L) = K
DistanceSq = NewDistSq
End If
End If
Next
I = I + 3
L = L + 1
Next
NTm = Timer
If NTm - Tm >= RefreshInterval Then
Tm = NTm
SetDIBits picColor2.hDC, picColor2.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
DrawProgress Y / (PH - 1)
picColor2.Refresh
DoEvents
If QuitLoop Then Exit For
End If
LStart1 = LStart1 + Pitch1
LStart2 = LStart2 + Pitch2
Next
SetDIBits picColor2.hDC, picColor2.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
DrawProgress 1
picColor2.Refresh
'==============================================================================
'步骤3:取得和上两步相反的颜色
'------------------------------------------------------------------------------
LStart1 = 0
LStart2 = 0
picColor3.Visible = True
For Y = 0 To PH - 1
I = LStart1
L = LStart2
For X = 0 To PW - 1
DistanceSq = 255& * 255 * 3
Values3(L) = Values2(L)
For K = 0 To 255
RDiff = CLng(BMIFPAL.Palette(K).R) - SrcPixels(I + 2)
GDiff = CLng(BMIFPAL.Palette(K).G) - SrcPixels(I + 1)
BDiff = CLng(BMIFPAL.Palette(K).B) - SrcPixels(I + 0)
If RDiff * Vec1R(L) + GDiff * Vec1G(L) + BDiff * Vec1B(L) < 0 And _
RDiff * Vec2R(L) + GDiff * Vec2G(L) + BDiff * Vec2B(L) < 0 Then
NewDistSq = RDiff * RDiff + GDiff * GDiff + BDiff * BDiff
If NewDistSq < DistanceSq And NewDistSq <= MaxDistSq Then
Vec3R(L) = RDiff
Vec3G(L) = GDiff
Vec3B(L) = BDiff
Values3(L) = K
DestPixels(L) = K
DistanceSq = NewDistSq
End If
End If
Next
I = I + 3
L = L + 1
Next
NTm = Timer
If NTm - Tm >= RefreshInterval Then
Tm = NTm
SetDIBits picColor3.hDC, picColor3.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
DrawProgress Y / (PH - 1)
picColor3.Refresh
DoEvents
If QuitLoop Then Exit For
End If
LStart1 = LStart1 + Pitch1
LStart2 = LStart2 + Pitch2
Next
SetDIBits picColor3.hDC, picColor3.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
DrawProgress 1
picColor3.Refresh
'==============================================================================
'步骤4:取得和上三步相反的颜色
'------------------------------------------------------------------------------
LStart1 = 0
LStart2 = 0
picColor4.Visible = True
For Y = 0 To PH - 1
I = LStart1
L = LStart2
For X = 0 To PW - 1
DistanceSq = 255& * 255 * 3
Values4(L) = Values3(L)
For K = 0 To 255
RDiff = CLng(BMIFPAL.Palette(K).R) - SrcPixels(I + 2)
GDiff = CLng(BMIFPAL.Palette(K).G) - SrcPixels(I + 1)
BDiff = CLng(BMIFPAL.Palette(K).B) - SrcPixels(I + 0)
If RDiff * Vec1R(L) + GDiff * Vec1G(L) + BDiff * Vec1B(L) < 0 And _
RDiff * Vec2R(L) + GDiff * Vec2G(L) + BDiff * Vec2B(L) < 0 And _
RDiff * Vec3R(L) + GDiff * Vec3G(L) + BDiff * Vec3B(L) < 0 Then
NewDistSq = RDiff * RDiff + GDiff * GDiff + BDiff * BDiff
If NewDistSq < DistanceSq And NewDistSq <= MaxDistSq Then
Vec4R(L) = RDiff
Vec4G(L) = GDiff
Vec4B(L) = BDiff
Values4(L) = K
DestPixels(L) = K
DistanceSq = NewDistSq
End If
End If
Next
I = I + 3
L = L + 1
Next
NTm = Timer
If NTm - Tm >= RefreshInterval Then
Tm = NTm
SetDIBits picColor4.hDC, picColor4.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
DrawProgress Y / (PH - 1)
picColor4.Refresh
DoEvents
If QuitLoop Then Exit For
End If
LStart1 = LStart1 + Pitch1
LStart2 = LStart2 + Pitch2
Next
SetDIBits picColor4.hDC, picColor4.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
DrawProgress 1
picColor4.Refresh
'==============================================================================
'步骤5:将上面四步取得的颜色进行抖动混合
'------------------------------------------------------------------------------
LStart1 = 0
LStart2 = 0
picResult.Visible = True
Dim DitherValue As Long
For Y = 0 To PH - 1
I = LStart1
L = LStart2
For X = 0 To PW - 1
DitherValue = LM((X And &HF) + (Y And &HF) * &H10)
If Values1(L) = Values2(L) And Values2(L) = Values3(L) And Values3(L) = Values4(L) Then '只有一个颜色
DestPixels(L) = Values1(L)
ElseIf Values1(L) <> Values2(L) And Values2(L) = Values3(L) And Values3(L) = Values4(L) Then '抖动颜色1、2
' Src
' /|~"-,_
' / | ~"-,_
' / | ~"-,_
' / | ~"-,_
' / | ~"-,_
'Values1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Values2
Dim Vec1To2R As Long, Vec1To2G As Long, Vec1To2B As Long
Dim Vec1To2Dist As Double, ProjLen As Double
Vec1To2R = Vec2R(L) - Vec1R(L)
Vec1To2G = Vec2G(L) - Vec1G(L)
Vec1To2B = Vec2B(L) - Vec1B(L)
Vec1To2Dist = Sqr(CDbl(Vec1To2R) * Vec1To2R + CDbl(Vec1To2G) * Vec1To2G + CDbl(Vec1To2B) * Vec1To2B)
ProjLen = (-Vec1R(L) * Vec1To2R - Vec1G(L) * Vec1To2G - Vec1B(L) * Vec1To2B) / Vec1To2Dist
If ProjLen * 255 / Vec1To2Dist <= DitherValue Then DestPixels(L) = Values1(L) Else DestPixels(L) = Values2(L)
ElseIf Values1(L) <> Values2(L) And Values2(L) <> Values3(L) And Values3(L) = Values4(L) Then '抖动颜色1、2、3
'P2,
'|\ ~"-,_
'| \ ~"-,_
'| P,__ ~"-,_
'| / ~~""--,,__ ~"-,_
'|L ~~""--===,_
'P1~~~~~~~~~~~~~~~~~~~~~~~~~~~P3
Dim Plane123A As Double, Plane123B As Double, Plane123C As Double, Plane123D As Double
Dim Plane123ABCLen As Double
Dim Vec2To3R As Long, Vec2To3G As Long, Vec2To3B As Long
Vec1To2R = Vec2R(L) - Vec1R(L)
Vec1To2G = Vec2G(L) - Vec1G(L)
Vec1To2B = Vec2B(L) - Vec1B(L)
Vec2To3R = Vec3R(L) - Vec2R(L)
Vec2To3G = Vec3G(L) - Vec2G(L)
Vec2To3B = Vec3B(L) - Vec2B(L)
Plane123A = Vec1To2G * Vec2To3B - Vec1To2B * Vec2To3G
Plane123B = Vec1To2B * Vec2To3R - Vec1To2R * Vec2To3B
Plane123C = Vec1To2R * Vec2To3G - Vec1To2G * Vec2To3R
Plane123D = -(Plane123A * BMIFPAL.Palette(Values1(L)).R + Plane123B * BMIFPAL.Palette(Values1(L)).G + Plane123C * BMIFPAL.Palette(Values1(L)).B)
Plane123ABCLen = Sqr(Plane123A * Plane123A + Plane123B * Plane123B + Plane123C * Plane123C)
Plane123A = Plane123A / Plane123ABCLen
Plane123B = Plane123B / Plane123ABCLen
Plane123C = Plane123C / Plane123ABCLen
Plane123D = Plane123D / Plane123ABCLen
Dim PlaneFace23A As Double, PlaneFace23B As Double, PlaneFace23C As Double, PlaneFace23D As Double
Dim PlaneFace23ABCLen As Double
PlaneFace23A = Vec1G(L) * Plane123C - Vec1B(L) * Plane123B
PlaneFace23B = Vec1B(L) * Plane123A - Vec1R(L) * Plane123C
PlaneFace23C = Vec1R(L) * Plane123B - Vec1G(L) * Plane123A
PlaneFace23D = -(PlaneFace23A * SrcPixels(I + 2) + PlaneFace23B * SrcPixels(I + 1) + PlaneFace23C * SrcPixels(I + 0))
PlaneFace23ABCLen = Sqr(PlaneFace23A * PlaneFace23A + PlaneFace23B * PlaneFace23B + PlaneFace23C * PlaneFace23C)
PlaneFace23A = PlaneFace23A / PlaneFace23ABCLen
PlaneFace23B = PlaneFace23B / PlaneFace23ABCLen
PlaneFace23C = PlaneFace23C / PlaneFace23ABCLen
PlaneFace23D = PlaneFace23D / PlaneFace23ABCLen
Dim P2ToPlaneDist As Double, P3ToPlaneDist As Double, PlaneCutPosition As Double
P2ToPlaneDist = Abs(BMIFPAL.Palette(Values2(L)).R * PlaneFace23A + BMIFPAL.Palette(Values2(L)).G * PlaneFace23B + BMIFPAL.Palette(Values2(L)).B * PlaneFace23C + PlaneFace23D)
P3ToPlaneDist = Abs(BMIFPAL.Palette(Values3(L)).R * PlaneFace23A + BMIFPAL.Palette(Values3(L)).G * PlaneFace23B + BMIFPAL.Palette(Values3(L)).B * PlaneFace23C + PlaneFace23D)
PlaneCutPosition = P2ToPlaneDist / (P2ToPlaneDist + P3ToPlaneDist)
If PlaneCutPosition * 255 <= DitherValue Then DestPixels(L) = Values2(L) Else DestPixels(L) = Values3(L)
Dim PointOnPlaneAnd2To3VecR As Double, PointOnPlaneAnd2To3VecG As Double, PointOnPlaneAnd2To3VecB As Double
PointOnPlaneAnd2To3VecR = CDbl(BMIFPAL.Palette(Values2(L)).R) + Vec2To3R * PlaneCutPosition - SrcPixels(I + 2)
PointOnPlaneAnd2To3VecG = CDbl(BMIFPAL.Palette(Values2(L)).G) + Vec2To3G * PlaneCutPosition - SrcPixels(I + 1)
PointOnPlaneAnd2To3VecB = CDbl(BMIFPAL.Palette(Values2(L)).B) + Vec2To3B * PlaneCutPosition - SrcPixels(I + 0)
Dim VecToThatPointR As Double, VecToThatPointG As Double, VecToThatPointB As Double, VecToThatPointLen As Double
VecToThatPointR = PointOnPlaneAnd2To3VecR - Vec1R(L)
VecToThatPointG = PointOnPlaneAnd2To3VecG - Vec1G(L)
VecToThatPointB = PointOnPlaneAnd2To3VecB - Vec1B(L)
VecToThatPointLen = Sqr(VecToThatPointR * VecToThatPointR + VecToThatPointG * VecToThatPointG + VecToThatPointB * VecToThatPointB)
VecToThatPointR = VecToThatPointR / VecToThatPointLen
VecToThatPointG = VecToThatPointG / VecToThatPointLen
VecToThatPointB = VecToThatPointB / VecToThatPointLen
ProjLen = (-Vec1R(L) * VecToThatPointR - Vec1G(L) * VecToThatPointG - Vec1B(L) * VecToThatPointB) / VecToThatPointLen
If ProjLen * 255 <= DitherValue Then DestPixels(L) = Values1(L)
Else '抖动颜色1、2、3、4
Dim Plane12PA As Double, Plane12PB As Double, Plane12PC As Double, Plane12PD As Double, Plane12PABCLen As Double
Dim Plane34PA As Double, Plane34PB As Double, Plane34PC As Double, Plane34PD As Double, Plane34PABCLen As Double
Plane12PA = Vec1G(L) * Vec2B(L) - Vec1B(L) * Vec2G(L)
Plane12PB = Vec1B(L) * Vec2R(L) - Vec1R(L) * Vec2B(L)
Plane12PC = Vec1R(L) * Vec2G(L) - Vec1G(L) * Vec2R(L)
Plane34PA = Vec3G(L) * Vec4B(L) - Vec3B(L) * Vec4G(L)
Plane34PB = Vec3B(L) * Vec4R(L) - Vec3R(L) * Vec4B(L)
Plane34PC = Vec3R(L) * Vec4G(L) - Vec3G(L) * Vec4R(L)
Plane12PD = -(Plane12PA * SrcPixels(I + 2) + Plane12PB * SrcPixels(I + 1) + Plane12PC * SrcPixels(I + 0))
Plane34PD = -(Plane34PA * SrcPixels(I + 2) + Plane34PB * SrcPixels(I + 1) + Plane34PC * SrcPixels(I + 0))
Plane12PABCLen = Sqr(Plane12PA * Plane12PA + Plane12PB * Plane12PB + Plane12PC * Plane12PC)
Plane34PABCLen = Sqr(Plane34PA * Plane34PA + Plane34PB * Plane34PB + Plane34PC * Plane34PC)
Plane12PA = Plane12PA / Plane12PABCLen
Plane12PB = Plane12PB / Plane12PABCLen
Plane12PC = Plane12PC / Plane12PABCLen
Plane12PD = Plane12PD / Plane12PABCLen
Plane34PA = Plane34PA / Plane34PABCLen
Plane34PB = Plane34PB / Plane34PABCLen
Plane34PC = Plane34PC / Plane34PABCLen
Plane34PD = Plane34PD / Plane34PABCLen
Dim Distance1ToP34 As Double, Distance2ToP34 As Double
Dim Distance3ToP12 As Double, Distance4ToP12 As Double
Distance1ToP34 = Abs(Vec1R(L) * Plane34PA + Vec1G(L) * Plane34PB + Vec1B(L) * Plane34PC + Plane34PD)
Distance2ToP34 = Abs(Vec2R(L) * Plane34PA + Vec2G(L) * Plane34PB + Vec2B(L) * Plane34PC + Plane34PD)
Distance3ToP12 = Abs(Vec3R(L) * Plane12PA + Vec3G(L) * Plane12PB + Vec3B(L) * Plane12PC + Plane12PD)
Distance4ToP12 = Abs(Vec4R(L) * Plane12PA + Vec4G(L) * Plane12PB + Vec4B(L) * Plane12PC + Plane12PD)
Dim P12Cut34 As Double, P34Cut12 As Double
P12Cut34 = Distance3ToP12 + (Distance3ToP12 + Distance4ToP12)
P34Cut12 = Distance1ToP34 + (Distance1ToP34 + Distance2ToP34)
Dim Value12 As Byte, Value34 As Byte
If P12Cut34 * 255 <= DitherValue Then Value34 = Values3(L) Else Value34 = Values4(L)
If P34Cut12 * 255 <= DitherValue Then Value12 = Values1(L) Else Value12 = Values2(L)
Vec1To2R = Vec2R(L) - Vec1R(L)
Vec1To2G = Vec2G(L) - Vec1G(L)
Vec1To2B = Vec2B(L) - Vec1B(L)
Dim Vec3To4R As Long, Vec3To4G As Long, Vec3To4B As Long
Vec3To4R = Vec4R(L) - Vec3R(L)
Vec3To4G = Vec4G(L) - Vec3G(L)
Vec3To4B = Vec4B(L) - Vec3B(L)
Dim CutPoint1R As Double, CutPoint1G As Double, CutPoint1B As Double
Dim CutPoint2R As Double, CutPoint2G As Double, CutPoint2B As Double
CutPoint1R = Vec1R(L) + Vec1To2R * P34Cut12
CutPoint1G = Vec1G(L) + Vec1To2G * P34Cut12
CutPoint1B = Vec1B(L) + Vec1To2B * P34Cut12
CutPoint2R = Vec3R(L) + Vec3To4R * P12Cut34
CutPoint2G = Vec3G(L) + Vec3To4G * P12Cut34
CutPoint2B = Vec3B(L) + Vec3To4B * P12Cut34
Dim Dist12 As Double, Dist34 As Double
Dist12 = Sqr(CutPoint1R * CutPoint1R + CutPoint1G * CutPoint1G + CutPoint1B * CutPoint1B)
Dist34 = Sqr(CutPoint2R * CutPoint2R + CutPoint2G * CutPoint2G + CutPoint2B * CutPoint2B)
If Dist12 * 255 / (Dist12 + Dist34) <= DitherValue Then DestPixels(L) = Value12 Else DestPixels(L) = Value34
End If
I = I + 3
L = L + 1
Next
NTm = Timer
If NTm - Tm >= RefreshInterval Then
Tm = NTm
SetDIBits picResult.hDC, picResult.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
DrawProgress Y / (PH - 1)
picResult.Refresh
DoEvents
If QuitLoop Then Exit For
End If
LStart1 = LStart1 + Pitch1
LStart2 = LStart2 + Pitch2
Next
SetDIBits picResult.hDC, picResult.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
DrawProgress 1
picResult.Refresh
cmdDither.Enabled = False
OpSrcPic.Enabled = True
OpDitherPic.Enabled = True
OpDitherPic.Value = True
End Sub
Private Sub Form_Load()
With BMIF24
.biSize = 40
.biPlanes = 1
.biBitCount = 24
End With
With BMIFPAL
.biSize = 40
.biPlanes = 1
.biBitCount = COLORS_BITS
.biClrUsed = COLORS_MAX
.biClrImportant = COLORS_MAX
End With
LM = LoadResData(101, "LIGHTMATRIX")
Randomize Timer
ProgWidth = picProgress.ScaleWidth
End Sub
Function Lerp(ByVal V1 As Long, ByVal V2 As Long, ByVal Val_0_255 As Long) As Long
Lerp = V1 + (V2 - V1) * Val_0_255 \ 255
End Function
Private Sub Form_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)
On Local Error GoTo eHandlr
Picture = LoadPicture(Data.Files(1))
PW = ScaleX(Picture.Width, vbHimetric, vbPixels)
PH = ScaleY(Picture.Height, vbHimetric, vbPixels)
picSrcPic.Move 0, 0, PW, PH
picSrcPic.PaintPicture Picture, 0, 0
picColor1.Cls
picColor2.Cls
picColor3.Cls
picColor4.Cls
picResult.Cls
picColor1.Visible = False
picColor2.Visible = False
picColor3.Visible = False
picColor4.Visible = False
picResult.Visible = False
picColor1.Move PW * 0, 0, PW, PH
picColor2.Move PW * 1, 0, PW, PH
picColor3.Move PW * 2, 0, PW, PH
picColor4.Move PW * 3, 0, PW, PH
picResult.Move PW * 4, 0, PW, PH
picDither_Resize
HSDither_Change
BMIF24.biWidth = PW
BMIF24.biHeight = PH
BMIFPAL.biWidth = PW
BMIFPAL.biHeight = PH
DrawProgress 0
If ChRandomPalette.Value Then
Dim I&
For I = 0 To UBound(BMIFPAL.Palette)
BMIFPAL.Palette(I).R = Rnd * 255
BMIFPAL.Palette(I).G = Rnd * 255
BMIFPAL.Palette(I).B = Rnd * 255
Next
Else
If CreateOctreePaletteFromHBITMAP(hDC, Picture.Handle, PW, PH, COLORS_MAX, COLORS_BITS, BMIFPAL.Palette(0)) = 0 Then
MsgBox "生成调色板失败。", vbExclamation
End If
End If
DrawPal
cmdDither.Enabled = True
OpSrcPic.Enabled = False
OpDitherPic.Enabled = False
OpSrcPic.Value = True
Exit Sub
eHandlr:
MsgBox Err.Description, vbExclamation, "出错"
End Sub
Sub DrawPal()
Dim X&, Y&
Dim DrX&, DrY&
Dim I&
For Y = 0 To 15
DrX = 0
For X = 0 To 15
picPal.Line (DrX, DrY)-(DrX + 4, DrY + 4), RGB(BMIFPAL.Palette(I).R, BMIFPAL.Palette(I).G, BMIFPAL.Palette(I).B), BF
I = I + 1
If I >= COLORS_MAX Then Exit Sub
DrX = DrX + 5
Next
DrY = DrY + 5
Next
End Sub
Private Sub Form_Resize()
On Error Resume Next
picDither.Width = picRightPanel.Left
End Sub
Private Sub Form_Unload(Cancel As Integer)
QuitLoop = True
End
End Sub
Private Sub HSDither_Change()
On Error Resume Next
Dim LeftBegin As Long
LeftBegin = -HSDither.Value
picColor1.Left = LeftBegin + PW * 0
picColor2.Left = LeftBegin + PW * 1
picColor3.Left = LeftBegin + PW * 2
picColor4.Left = LeftBegin + PW * 3
picResult.Left = LeftBegin + PW * 4
End Sub
Private Sub HSDither_Scroll()
HSDither_Change
End Sub
Private Sub OpDitherPic_Click()
picSrcPic.Visible = False
picDither.Visible = True
End Sub
Private Sub OpSrcPic_Click()
picSrcPic.Visible = True
picDither.Visible = False
End Sub
Private Sub picDither_Resize()
On Error Resume Next
Dim PP1W As Long, PP1H As Long, HSMax As Long
PP1W = picDither.ScaleWidth
PP1H = picDither.ScaleHeight
HSDither.Move 0, PP1H - 17, PP1W, 17
HSMax = PW * 5 - PP1W
If HSMax > 0 Then
HSDither.Max = HSMax
HSDither.LargeChange = PP1W
HSDither.Visible = True
Else
HSDither.Value = 0
HSDither.Visible = False
End If
End Sub