找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 12968|回复: 6

【图像】抖动算法实现真彩色图片高细节256色降级处理【旧帖,效果不好,勿用】

[复制链接]

1109

主题

1649

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24180 个
贡献
46222 次
宅之契约
0 份
在线时间
2294 小时
注册时间
2014-1-26
发表于 2014-6-20 20:42:57 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
这里所说的高细节并不是我们所说的HDR,也不是用浮点数进行纹理存储……而是在尽可能保证图片不变得“难看”的情况下把图片降级为256色(尤其是对于存储GIF图片非常具有利用价值)。
对于256色的图片都有一个调色板 Palette(或颜色表 Color Table)。这个颜色表是如何得到的呢?有很多种方法:
1、用随机数,取得256种颜色的RGB,组成调色板。
2、使用固定的调色板
3、用八叉树算法计算调色板。

其中方法1要看人品。。。人品好的话颜色刚好适合这个图像,人品不好的话就呵呵了。
方法2的调色板意在把24位真彩色的所有颜色中,均匀取出256种颜色。虽然色域很广,但是每种颜色的细节都不高。
方法3能取得接近完美的调色板。但是这个算法比较费内存。特别是图像特别大的时候。

方法3的实现方法,请看我的这个帖子:【C】八叉树算法:BMP颜色降级生成调色板的算法

接下来言归正传:抖动算法的实现原理。
假设我只有黑色和白色两种颜色,然后我要实现如下图的效果,应该怎么让画面更真实?
hentai.jpg

很简单,我们只需要把黑白的像素点排列一下。我想大家用过碳素笔都知道碳素笔这东西只能画出纯色的线,而不能像铅笔一样画出深浅不同的线条。但是仍然有一种艺术叫“线描”,就是用碳素笔画交叉线实现灰度的效果。那么我们也使用类似的方法,通过排列黑白两色的像素实现灰度的效果。因此处理后的图像效果如下:
hentai.gif

至于这个黑白两色的像素怎么排列呢?这里就要讲到最基础的抖动算法:黑白两色的抖动算法。
我们可以看到这些像素的排列很有规律。那么这个规律到底是什么规律呢?我们其实是把一张“亮度矩阵”平铺到图像上,然后通过判断图像中的像素的值是否大于亮度矩阵图的像素的值来判断是白色还是黑色。亮度矩阵是什么样的呢?请看下图,是亮度矩阵的放大图。
lm.gif

然后我们把亮度矩阵图平铺到原图上,根据比较原图和亮度矩阵图的对应像素的结果,得到最终的颜色。
Dither.gif

有关彩色图像的抖动算法,我自己提出的这个是根据空间四边形向量逼近指定颜色,用抖动矩阵来选取颜色的算法。亲测效果不好用,请大家不要用。
我来讲讲我的算法。这个是我自己想出来的算法,我并没有参考任何的相关资料。
我的想法是这样的:
假设给定任意颜色(R,G,B),让我从一个调色板里面取得一个合适的颜色来替代这个颜色,从而实现位图从24位真彩色降级为8位索引颜色。那么第一步就是从调色板里面找出最接近的颜色。
我们把颜色信息(R,G,B)当做一个三维空间的坐标,它的取值范围从(0,0,0)到(255,255,255),然后我们就可以利用三维空间中计算两点距离的公式找出最相近的颜色了。
我们拿Win7自带的企鹅壁纸做测试。首先看原图:
Penguins.jpg
然后我们通过取得它的最相近颜色,先初步把它降级为256色。
Penguins1.gif
以此为基础,接下来我要讲我的算法原理了。

首先,我们要从256个调色板颜色中,找出4个能包住原始颜色的颜色。所谓的“包住原始颜色”指的是把原始颜色(R,G,B)看做一个三维空间的坐标。然后我们也把调色板中所有的颜色的RGB值看成坐标。那么这样的话,256个调色板项,相当于空间中的256个点。我们再从这些颜色中找到4个点组成一个三棱锥,让原始颜色在三棱锥内部。之后我们就可以通过把抖动算法当成线性插值从而在4个颜色中选出最合适的颜色。
ColorSpace.GIF
那么这4个颜色肯定首选距离原始颜色最接近的颜色。我的算法是,先找出距离原始颜色最近的颜色,然后取得“对面的”最接近的颜色。这个“对面的”我不好解释,不过我可以用另外一种方法解释,就是取得的这个点,和刚才的两个点,能组成一个钝角三角形,然后原始颜色的位置就在这个三角形的钝角上。
这一步下来,我们取得的颜色值就不像上面图那么像了。
2.gif
然后找出第三个点。第三个点的要求是必须能和前两个点组合的三角形上能找到原始颜色的点到这个三角形的投影,同时也是所有的这些个点中距离原始颜色最近的点。
3.gif
最后就是第四个点。这个点是最后一步取得的点。这个点和前面三个点组成一个四面体,这个四面体能包住这个原始颜色的点。
当这个四面体建立后,我们最后要做的就是插值。第一个点、第二个点和原始颜色的点组成一个平面,然后第三个点、第四个点和原始颜色的点组成一个平面,分别计算第一个点、第二个点到第二个平面的距离,然后分别计算第三个点、第四个点到第一个平面的距离,这样就能做好颜色1、2的插值和颜色3、4的插值。做好以后再做最终的插值。计算距离即可。
而这里所说的插值,其实是通过亮度矩阵判断点的颜色值,进行抖动。
5.gif
看起来很不错,不过这个算法有个缺点,第三、第四步很容易因为找到的点颜色差别太离谱而出现严重的失真情况。就像下图这样:
原图是下面这幅图(随便找的)
16C.png
处理后,可以看到第三步、第四步取得了过于离谱的颜色:
20140620203115.png
那么我的解决办法,是通过筛选,把距离过远的颜色筛除。经过这个优化以后就是如下的效果了:
20140620203519.png
这样第三步、第四步取得的奇怪颜色就被筛掉了。效果好多了!

为了便于大家理解,我决定把VB写的这个源码公开给大家看。
  1. VERSION 5.00
  2. Begin VB.Form frmMain
  3.    Caption         =   "取得调色板"
  4.    ClientHeight    =   6465
  5.    ClientLeft      =   120
  6.    ClientTop       =   450
  7.    ClientWidth     =   16440
  8.    LinkTopic       =   "frmMain"
  9.    OLEDropMode     =   1  'Manual
  10.    ScaleHeight     =   431
  11.    ScaleMode       =   3  'Pixel
  12.    ScaleWidth      =   1096
  13.    StartUpPosition =   3  '窗口缺省
  14.    Begin VB.PictureBox picDither
  15.       Align           =   3  'Align Left
  16.       BorderStyle     =   0  'None
  17.       Height          =   6465
  18.       Left            =   0
  19.       ScaleHeight     =   431
  20.       ScaleMode       =   3  'Pixel
  21.       ScaleWidth      =   457
  22.       TabIndex        =   6
  23.       Top             =   0
  24.       Visible         =   0   'False
  25.       Width           =   6855
  26.       Begin VB.HScrollBar HSDither
  27.          Height          =   255
  28.          Left            =   1440
  29.          Max             =   0
  30.          TabIndex        =   12
  31.          TabStop         =   0   'False
  32.          Top             =   3000
  33.          Width           =   2415
  34.       End
  35.       Begin VB.PictureBox picColor4
  36.          AutoRedraw      =   -1  'True
  37.          BackColor       =   &H00000000&
  38.          BorderStyle     =   0  'None
  39.          Height          =   495
  40.          Left            =   1800
  41.          ScaleHeight     =   33
  42.          ScaleMode       =   3  'Pixel
  43.          ScaleWidth      =   33
  44.          TabIndex        =   11
  45.          Top             =   0
  46.          Visible         =   0   'False
  47.          Width           =   495
  48.       End
  49.       Begin VB.PictureBox picColor3
  50.          AutoRedraw      =   -1  'True
  51.          BackColor       =   &H00000000&
  52.          BorderStyle     =   0  'None
  53.          Height          =   495
  54.          Left            =   1200
  55.          ScaleHeight     =   33
  56.          ScaleMode       =   3  'Pixel
  57.          ScaleWidth      =   33
  58.          TabIndex        =   10
  59.          Top             =   0
  60.          Visible         =   0   'False
  61.          Width           =   495
  62.       End
  63.       Begin VB.PictureBox picColor2
  64.          AutoRedraw      =   -1  'True
  65.          BackColor       =   &H00000000&
  66.          BorderStyle     =   0  'None
  67.          Height          =   495
  68.          Left            =   600
  69.          ScaleHeight     =   33
  70.          ScaleMode       =   3  'Pixel
  71.          ScaleWidth      =   33
  72.          TabIndex        =   9
  73.          Top             =   0
  74.          Visible         =   0   'False
  75.          Width           =   495
  76.       End
  77.       Begin VB.PictureBox picColor1
  78.          AutoRedraw      =   -1  'True
  79.          BackColor       =   &H00000000&
  80.          BorderStyle     =   0  'None
  81.          Height          =   495
  82.          Left            =   0
  83.          ScaleHeight     =   33
  84.          ScaleMode       =   3  'Pixel
  85.          ScaleWidth      =   33
  86.          TabIndex        =   8
  87.          Top             =   0
  88.          Visible         =   0   'False
  89.          Width           =   495
  90.       End
  91.       Begin VB.PictureBox picResult
  92.          AutoRedraw      =   -1  'True
  93.          BackColor       =   &H00000000&
  94.          BorderStyle     =   0  'None
  95.          Height          =   495
  96.          Left            =   2400
  97.          ScaleHeight     =   33
  98.          ScaleMode       =   3  'Pixel
  99.          ScaleWidth      =   33
  100.          TabIndex        =   7
  101.          Top             =   0
  102.          Visible         =   0   'False
  103.          Width           =   495
  104.       End
  105.    End
  106.    Begin VB.PictureBox picRightPanel
  107.       Align           =   4  'Align Right
  108.       BorderStyle     =   0  'None
  109.       Height          =   6465
  110.       Left            =   15345
  111.       ScaleHeight     =   431
  112.       ScaleMode       =   3  'Pixel
  113.       ScaleWidth      =   73
  114.       TabIndex        =   0
  115.       Top             =   0
  116.       Width           =   1095
  117.       Begin VB.PictureBox picProgress
  118.          BackColor       =   &H8000000C&
  119.          Height          =   255
  120.          Left            =   0
  121.          ScaleHeight     =   13
  122.          ScaleMode       =   3  'Pixel
  123.          ScaleWidth      =   69
  124.          TabIndex        =   14
  125.          Top             =   4320
  126.          Width           =   1095
  127.          Begin VB.CommandButton cmdProgress
  128.             Enabled         =   0   'False
  129.             Height          =   195
  130.             Left            =   0
  131.             Style           =   1  'Graphical
  132.             TabIndex        =   15
  133.             Top             =   0
  134.             Width           =   1035
  135.          End
  136.       End
  137.       Begin VB.CheckBox ChRandomPalette
  138.          Caption         =   "产生随机调色板"
  139.          Height          =   615
  140.          Left            =   0
  141.          Style           =   1  'Graphical
  142.          TabIndex        =   13
  143.          Top             =   3600
  144.          Width           =   1095
  145.       End
  146.       Begin VB.PictureBox picPal
  147.          AutoRedraw      =   -1  'True
  148.          BackColor       =   &H00000000&
  149.          BorderStyle     =   0  'None
  150.          Height          =   1095
  151.          Left            =   0
  152.          ScaleHeight     =   73
  153.          ScaleMode       =   3  'Pixel
  154.          ScaleWidth      =   73
  155.          TabIndex        =   5
  156.          Top             =   2400
  157.          Width           =   1095
  158.       End
  159.       Begin VB.OptionButton OpDitherPic
  160.          Caption         =   "抖动图"
  161.          Enabled         =   0   'False
  162.          Height          =   495
  163.          Left            =   0
  164.          Style           =   1  'Graphical
  165.          TabIndex        =   4
  166.          Top             =   1920
  167.          Value           =   -1  'True
  168.          Width           =   1095
  169.       End
  170.       Begin VB.OptionButton OpSrcPic
  171.          Caption         =   "原图"
  172.          Enabled         =   0   'False
  173.          Height          =   495
  174.          Left            =   0
  175.          Style           =   1  'Graphical
  176.          TabIndex        =   3
  177.          Top             =   1440
  178.          Width           =   1095
  179.       End
  180.       Begin VB.CommandButton cmdDither
  181.          Caption         =   "抖动"
  182.          Enabled         =   0   'False
  183.          Height          =   615
  184.          Left            =   0
  185.          TabIndex        =   1
  186.          Top             =   0
  187.          Width           =   1095
  188.       End
  189.    End
  190.    Begin VB.PictureBox picSrcPic
  191.       AutoRedraw      =   -1  'True
  192.       AutoSize        =   -1  'True
  193.       BorderStyle     =   0  'None
  194.       Height          =   255
  195.       Left            =   0
  196.       ScaleHeight     =   255
  197.       ScaleWidth      =   135
  198.       TabIndex        =   2
  199.       Top             =   0
  200.       Visible         =   0   'False
  201.       Width           =   135
  202.    End
  203. End
  204. Attribute VB_Name = "frmMain"
  205. Attribute VB_GlobalNameSpace = False
  206. Attribute VB_Creatable = False
  207. Attribute VB_PredeclaredId = True
  208. Attribute VB_Exposed = False
  209. '==============================================================================
  210. '作者:0xAA55
  211. '论坛:http://www.0xaa55.com/
  212. '版权所有 (C) 2013-2014 技术宅的结界
  213. '请保留原作者信息,否则视为侵权。
  214. '------------------------------------------------------------------------------

  215. Option Explicit

  216. Private Const COLORS_MAX As Long = 256
  217. Private Const COLORS_BITS As Long = 8
  218. Private Const DIST_MAX As Long = 200000

  219. Private Type RGBQUAD
  220.     B As Byte
  221.     G As Byte
  222.     R As Byte
  223.     X As Byte
  224. End Type

  225. Private Type BITMAPINFO24
  226.     biSize As Long
  227.     biWidth As Long
  228.     biHeight As Long
  229.     biPlanes As Integer
  230.     biBitCount As Integer
  231.     biCompression As Long
  232.     biSizeImage As Long
  233.     biXPelsPerMeter As Long
  234.     biYPelsPerMeter As Long
  235.     biClrUsed As Long
  236.     biClrImportant As Long
  237. End Type

  238. Private Type BITMAPINFOPAL
  239.     biSize As Long
  240.     biWidth As Long
  241.     biHeight As Long
  242.     biPlanes As Integer
  243.     biBitCount As Integer
  244.     biCompression As Long
  245.     biSizeImage As Long
  246.     biXPelsPerMeter As Long
  247.     biYPelsPerMeter As Long
  248.     biClrUsed As Long
  249.     biClrImportant As Long
  250.     Palette(COLORS_MAX - 1) As RGBQUAD
  251. End Type

  252. Private Declare Function CreateOctreePaletteFromHBITMAP Lib "..\Octree.dll" (ByVal hDC&, ByVal hBitmap&, ByVal Width&, ByVal Height&, ByVal MaxColors&, ByVal ColorBits&, P As RGBQUAD) As Long
  253. Private Declare Function GetBitmapPitch Lib "..\Octree.dll" (ByVal BitCount As Integer, ByVal Width As Long) As Long
  254. 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
  255. 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
  256. Private Const DIB_RGB_COLORS = 0 '  color table in RGBs
  257. Private Const DIB_PAL_COLORS = 1 '  color table in palette indices

  258. Dim BMIF24 As BITMAPINFO24
  259. Dim BMIFPAL As BITMAPINFOPAL
  260. Dim PW&, PH&
  261. Dim LM() As Byte

  262. Dim QuitLoop As Boolean

  263. Dim SrcPixels() As Byte

  264. Dim Values1() As Byte
  265. Dim Values2() As Byte
  266. Dim Values3() As Byte
  267. Dim Values4() As Byte
  268. Dim Vec1R() As Long, Vec1G() As Long, Vec1B() As Long
  269. Dim Vec2R() As Long, Vec2G() As Long, Vec2B() As Long
  270. Dim Vec3R() As Long, Vec3G() As Long, Vec3B() As Long
  271. Dim Vec4R() As Long, Vec4G() As Long, Vec4B() As Long

  272. Private Const MaxDist As Double = 64
  273. Private Const MaxDistSq As Double = MaxDist * MaxDist

  274. Private Const RefreshInterval As Single = 0.1
  275. Dim ProgWidth As Single

  276. Sub DrawProgress(ByVal Prog As Double)
  277. cmdProgress.Left = (Prog - 1) * ProgWidth
  278. picProgress.Refresh
  279. End Sub

  280. Private Sub cmdDither_Click()
  281. Dim DestPixels() As Byte
  282. Dim Pitch1 As Long, Pitch2 As Long
  283. Dim X&, Y&
  284. Dim I&, LStart1&
  285. Dim L&, LStart2&
  286. Dim K&, DistanceSq As Long, NewDistSq As Long
  287. Dim RDiff As Long, GDiff As Long, BDiff As Long

  288. Dim Tm!, NTm!

  289. cmdDither.Enabled = False
  290. picDither.Visible = True
  291. picDither.Visible = True
  292. Form_Resize

  293. Pitch1 = GetBitmapPitch(24, PW)
  294. Pitch2 = GetBitmapPitch(8, PW)

  295. Erase Values1, Values2, Values3, Values4, SrcPixels
  296. Erase Vec1R, Vec1G, Vec1B
  297. Erase Vec2R, Vec2G, Vec2B
  298. Erase Vec3R, Vec3G, Vec3B
  299. Erase Vec4R, Vec4G, Vec4B
  300. ReDim SrcPixels(Pitch1 * PH - 1)
  301. ReDim DestPixels(Pitch2 * PH - 1)
  302. ReDim Values1(UBound(DestPixels))
  303. ReDim Values2(UBound(DestPixels))
  304. ReDim Values3(UBound(DestPixels))
  305. ReDim Values4(UBound(DestPixels))
  306. ReDim Vec1R(UBound(DestPixels)), Vec1G(UBound(DestPixels)), Vec1B(UBound(DestPixels))
  307. ReDim Vec2R(UBound(DestPixels)), Vec2G(UBound(DestPixels)), Vec2B(UBound(DestPixels))
  308. ReDim Vec3R(UBound(DestPixels)), Vec3G(UBound(DestPixels)), Vec3B(UBound(DestPixels))
  309. ReDim Vec4R(UBound(DestPixels)), Vec4G(UBound(DestPixels)), Vec4B(UBound(DestPixels))

  310. GetDIBits picSrcPic.hDC, picSrcPic.Image.Handle, 0, PH, SrcPixels(0), BMIF24, DIB_RGB_COLORS

  311. '==============================================================================
  312. '步骤1:取得最相近的颜色
  313. '------------------------------------------------------------------------------
  314. LStart1 = 0
  315. LStart2 = 0
  316. picColor1.Visible = True
  317. For Y = 0 To PH - 1
  318.     I = LStart1
  319.     L = LStart2
  320.     For X = 0 To PW - 1
  321.         DistanceSq = 255& * 255 * 3
  322.         For K = 0 To 255
  323.             RDiff = CLng(BMIFPAL.Palette(K).R) - SrcPixels(I + 2)
  324.             GDiff = CLng(BMIFPAL.Palette(K).G) - SrcPixels(I + 1)
  325.             BDiff = CLng(BMIFPAL.Palette(K).B) - SrcPixels(I + 0)
  326.             NewDistSq = RDiff * RDiff + GDiff * GDiff + BDiff * BDiff
  327.             If NewDistSq < DistanceSq And NewDistSq <= MaxDistSq Then
  328.                 Vec1R(L) = RDiff
  329.                 Vec1G(L) = GDiff
  330.                 Vec1B(L) = BDiff
  331.                 Values1(L) = K
  332.                 DestPixels(L) = K
  333.                 DistanceSq = NewDistSq
  334.             End If
  335.         Next
  336.         I = I + 3
  337.         L = L + 1
  338.     Next
  339.     NTm = Timer
  340.     If NTm - Tm >= RefreshInterval Then
  341.         Tm = NTm
  342.         SetDIBits picColor1.hDC, picColor1.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
  343.         picColor1.PaintPicture picSrcPic.Image, 0, 0, PW, PH - Y, 0, 0, PW, PH - Y
  344.         DrawProgress Y / (PH - 1)
  345.         picColor1.Refresh
  346.         DoEvents
  347.         If QuitLoop Then Exit For
  348.     End If
  349.     LStart1 = LStart1 + Pitch1
  350.     LStart2 = LStart2 + Pitch2
  351. Next
  352. SetDIBits picColor1.hDC, picColor1.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
  353. DrawProgress 1
  354. picColor1.Refresh

  355. '==============================================================================
  356. '步骤2:取得和上一步相反的颜色
  357. '------------------------------------------------------------------------------
  358. LStart1 = 0
  359. LStart2 = 0
  360. picColor2.Visible = True
  361. For Y = 0 To PH - 1
  362.     I = LStart1
  363.     L = LStart2
  364.     For X = 0 To PW - 1
  365.         DistanceSq = 255& * 255 * 3
  366.         Values2(L) = Values1(L)
  367.         For K = 0 To 255
  368.             RDiff = CLng(BMIFPAL.Palette(K).R) - SrcPixels(I + 2)
  369.             GDiff = CLng(BMIFPAL.Palette(K).G) - SrcPixels(I + 1)
  370.             BDiff = CLng(BMIFPAL.Palette(K).B) - SrcPixels(I + 0)
  371.             If RDiff * Vec1R(L) + GDiff * Vec1G(L) + BDiff * Vec1B(L) < 0 Then
  372.                 NewDistSq = RDiff * RDiff + GDiff * GDiff + BDiff * BDiff
  373.                 If NewDistSq < DistanceSq And NewDistSq <= MaxDistSq Then
  374.                     Vec2R(L) = RDiff
  375.                     Vec2G(L) = GDiff
  376.                     Vec2B(L) = BDiff
  377.                     Values2(L) = K
  378.                     DestPixels(L) = K
  379.                     DistanceSq = NewDistSq
  380.                 End If
  381.             End If
  382.         Next
  383.         I = I + 3
  384.         L = L + 1
  385.     Next
  386.     NTm = Timer
  387.     If NTm - Tm >= RefreshInterval Then
  388.         Tm = NTm
  389.         SetDIBits picColor2.hDC, picColor2.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
  390.         DrawProgress Y / (PH - 1)
  391.         picColor2.Refresh
  392.         DoEvents
  393.         If QuitLoop Then Exit For
  394.     End If
  395.     LStart1 = LStart1 + Pitch1
  396.     LStart2 = LStart2 + Pitch2
  397. Next
  398. SetDIBits picColor2.hDC, picColor2.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
  399. DrawProgress 1
  400. picColor2.Refresh

  401. '==============================================================================
  402. '步骤3:取得和上两步相反的颜色
  403. '------------------------------------------------------------------------------
  404. LStart1 = 0
  405. LStart2 = 0
  406. picColor3.Visible = True
  407. For Y = 0 To PH - 1
  408.     I = LStart1
  409.     L = LStart2
  410.     For X = 0 To PW - 1
  411.         DistanceSq = 255& * 255 * 3
  412.         Values3(L) = Values2(L)
  413.         For K = 0 To 255
  414.             RDiff = CLng(BMIFPAL.Palette(K).R) - SrcPixels(I + 2)
  415.             GDiff = CLng(BMIFPAL.Palette(K).G) - SrcPixels(I + 1)
  416.             BDiff = CLng(BMIFPAL.Palette(K).B) - SrcPixels(I + 0)
  417.             If RDiff * Vec1R(L) + GDiff * Vec1G(L) + BDiff * Vec1B(L) < 0 And _
  418.                RDiff * Vec2R(L) + GDiff * Vec2G(L) + BDiff * Vec2B(L) < 0 Then
  419.                 NewDistSq = RDiff * RDiff + GDiff * GDiff + BDiff * BDiff
  420.                 If NewDistSq < DistanceSq And NewDistSq <= MaxDistSq Then
  421.                     Vec3R(L) = RDiff
  422.                     Vec3G(L) = GDiff
  423.                     Vec3B(L) = BDiff
  424.                     Values3(L) = K
  425.                     DestPixels(L) = K
  426.                     DistanceSq = NewDistSq
  427.                 End If
  428.             End If
  429.         Next
  430.         I = I + 3
  431.         L = L + 1
  432.     Next
  433.     NTm = Timer
  434.     If NTm - Tm >= RefreshInterval Then
  435.         Tm = NTm
  436.         SetDIBits picColor3.hDC, picColor3.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
  437.         DrawProgress Y / (PH - 1)
  438.         picColor3.Refresh
  439.         DoEvents
  440.         If QuitLoop Then Exit For
  441.     End If
  442.     LStart1 = LStart1 + Pitch1
  443.     LStart2 = LStart2 + Pitch2
  444. Next
  445. SetDIBits picColor3.hDC, picColor3.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
  446. DrawProgress 1
  447. picColor3.Refresh

  448. '==============================================================================
  449. '步骤4:取得和上三步相反的颜色
  450. '------------------------------------------------------------------------------
  451. LStart1 = 0
  452. LStart2 = 0
  453. picColor4.Visible = True
  454. For Y = 0 To PH - 1
  455.     I = LStart1
  456.     L = LStart2
  457.     For X = 0 To PW - 1
  458.         DistanceSq = 255& * 255 * 3
  459.         Values4(L) = Values3(L)
  460.         For K = 0 To 255
  461.             RDiff = CLng(BMIFPAL.Palette(K).R) - SrcPixels(I + 2)
  462.             GDiff = CLng(BMIFPAL.Palette(K).G) - SrcPixels(I + 1)
  463.             BDiff = CLng(BMIFPAL.Palette(K).B) - SrcPixels(I + 0)
  464.             If RDiff * Vec1R(L) + GDiff * Vec1G(L) + BDiff * Vec1B(L) < 0 And _
  465.                RDiff * Vec2R(L) + GDiff * Vec2G(L) + BDiff * Vec2B(L) < 0 And _
  466.                RDiff * Vec3R(L) + GDiff * Vec3G(L) + BDiff * Vec3B(L) < 0 Then
  467.                 NewDistSq = RDiff * RDiff + GDiff * GDiff + BDiff * BDiff
  468.                 If NewDistSq < DistanceSq And NewDistSq <= MaxDistSq Then
  469.                     Vec4R(L) = RDiff
  470.                     Vec4G(L) = GDiff
  471.                     Vec4B(L) = BDiff
  472.                     Values4(L) = K
  473.                     DestPixels(L) = K
  474.                     DistanceSq = NewDistSq
  475.                 End If
  476.             End If
  477.         Next
  478.         I = I + 3
  479.         L = L + 1
  480.     Next
  481.     NTm = Timer
  482.     If NTm - Tm >= RefreshInterval Then
  483.         Tm = NTm
  484.         SetDIBits picColor4.hDC, picColor4.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
  485.         DrawProgress Y / (PH - 1)
  486.         picColor4.Refresh
  487.         DoEvents
  488.         If QuitLoop Then Exit For
  489.     End If
  490.     LStart1 = LStart1 + Pitch1
  491.     LStart2 = LStart2 + Pitch2
  492. Next
  493. SetDIBits picColor4.hDC, picColor4.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
  494. DrawProgress 1
  495. picColor4.Refresh

  496. '==============================================================================
  497. '步骤5:将上面四步取得的颜色进行抖动混合
  498. '------------------------------------------------------------------------------
  499. LStart1 = 0
  500. LStart2 = 0
  501. picResult.Visible = True
  502. Dim DitherValue As Long
  503. For Y = 0 To PH - 1
  504.     I = LStart1
  505.     L = LStart2
  506.     For X = 0 To PW - 1
  507.         DitherValue = LM((X And &HF) + (Y And &HF) * &H10)
  508.         If Values1(L) = Values2(L) And Values2(L) = Values3(L) And Values3(L) = Values4(L) Then '只有一个颜色
  509.             DestPixels(L) = Values1(L)
  510.         ElseIf Values1(L) <> Values2(L) And Values2(L) = Values3(L) And Values3(L) = Values4(L) Then '抖动颜色1、2
  511.             
  512.             '          Src
  513.             '           /|~"-,_
  514.             '          / |     ~"-,_
  515.             '         /  |          ~"-,_
  516.             '        /   |               ~"-,_
  517.             '       /    |                    ~"-,_
  518.             'Values1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Values2
  519.             
  520.             Dim Vec1To2R As Long, Vec1To2G As Long, Vec1To2B As Long
  521.             Dim Vec1To2Dist As Double, ProjLen As Double
  522.             Vec1To2R = Vec2R(L) - Vec1R(L)
  523.             Vec1To2G = Vec2G(L) - Vec1G(L)
  524.             Vec1To2B = Vec2B(L) - Vec1B(L)
  525.             Vec1To2Dist = Sqr(CDbl(Vec1To2R) * Vec1To2R + CDbl(Vec1To2G) * Vec1To2G + CDbl(Vec1To2B) * Vec1To2B)
  526.             ProjLen = (-Vec1R(L) * Vec1To2R - Vec1G(L) * Vec1To2G - Vec1B(L) * Vec1To2B) / Vec1To2Dist
  527.             If ProjLen * 255 / Vec1To2Dist <= DitherValue Then DestPixels(L) = Values1(L) Else DestPixels(L) = Values2(L)
  528.         ElseIf Values1(L) <> Values2(L) And Values2(L) <> Values3(L) And Values3(L) = Values4(L) Then '抖动颜色1、2、3
  529.             
  530.             'P2,
  531.             '|\ ~"-,_
  532.             '| \     ~"-,_
  533.             '|  P,__      ~"-,_
  534.             '| /    ~~""--,,__ ~"-,_
  535.             '|L               ~~""--===,_
  536.             'P1~~~~~~~~~~~~~~~~~~~~~~~~~~~P3
  537.             
  538.             Dim Plane123A As Double, Plane123B As Double, Plane123C As Double, Plane123D As Double
  539.             Dim Plane123ABCLen As Double
  540.             Dim Vec2To3R As Long, Vec2To3G As Long, Vec2To3B As Long
  541.             Vec1To2R = Vec2R(L) - Vec1R(L)
  542.             Vec1To2G = Vec2G(L) - Vec1G(L)
  543.             Vec1To2B = Vec2B(L) - Vec1B(L)
  544.             Vec2To3R = Vec3R(L) - Vec2R(L)
  545.             Vec2To3G = Vec3G(L) - Vec2G(L)
  546.             Vec2To3B = Vec3B(L) - Vec2B(L)
  547.             
  548.             Plane123A = Vec1To2G * Vec2To3B - Vec1To2B * Vec2To3G
  549.             Plane123B = Vec1To2B * Vec2To3R - Vec1To2R * Vec2To3B
  550.             Plane123C = Vec1To2R * Vec2To3G - Vec1To2G * Vec2To3R
  551.             Plane123D = -(Plane123A * BMIFPAL.Palette(Values1(L)).R + Plane123B * BMIFPAL.Palette(Values1(L)).G + Plane123C * BMIFPAL.Palette(Values1(L)).B)
  552.             
  553.             Plane123ABCLen = Sqr(Plane123A * Plane123A + Plane123B * Plane123B + Plane123C * Plane123C)
  554.             Plane123A = Plane123A / Plane123ABCLen
  555.             Plane123B = Plane123B / Plane123ABCLen
  556.             Plane123C = Plane123C / Plane123ABCLen
  557.             Plane123D = Plane123D / Plane123ABCLen
  558.             
  559.             Dim PlaneFace23A As Double, PlaneFace23B As Double, PlaneFace23C As Double, PlaneFace23D As Double
  560.             Dim PlaneFace23ABCLen As Double
  561.             PlaneFace23A = Vec1G(L) * Plane123C - Vec1B(L) * Plane123B
  562.             PlaneFace23B = Vec1B(L) * Plane123A - Vec1R(L) * Plane123C
  563.             PlaneFace23C = Vec1R(L) * Plane123B - Vec1G(L) * Plane123A
  564.             PlaneFace23D = -(PlaneFace23A * SrcPixels(I + 2) + PlaneFace23B * SrcPixels(I + 1) + PlaneFace23C * SrcPixels(I + 0))
  565.             
  566.             PlaneFace23ABCLen = Sqr(PlaneFace23A * PlaneFace23A + PlaneFace23B * PlaneFace23B + PlaneFace23C * PlaneFace23C)
  567.             PlaneFace23A = PlaneFace23A / PlaneFace23ABCLen
  568.             PlaneFace23B = PlaneFace23B / PlaneFace23ABCLen
  569.             PlaneFace23C = PlaneFace23C / PlaneFace23ABCLen
  570.             PlaneFace23D = PlaneFace23D / PlaneFace23ABCLen
  571.             
  572.             Dim P2ToPlaneDist As Double, P3ToPlaneDist As Double, PlaneCutPosition As Double
  573.             P2ToPlaneDist = Abs(BMIFPAL.Palette(Values2(L)).R * PlaneFace23A + BMIFPAL.Palette(Values2(L)).G * PlaneFace23B + BMIFPAL.Palette(Values2(L)).B * PlaneFace23C + PlaneFace23D)
  574.             P3ToPlaneDist = Abs(BMIFPAL.Palette(Values3(L)).R * PlaneFace23A + BMIFPAL.Palette(Values3(L)).G * PlaneFace23B + BMIFPAL.Palette(Values3(L)).B * PlaneFace23C + PlaneFace23D)
  575.             PlaneCutPosition = P2ToPlaneDist / (P2ToPlaneDist + P3ToPlaneDist)
  576.             
  577.             If PlaneCutPosition * 255 <= DitherValue Then DestPixels(L) = Values2(L) Else DestPixels(L) = Values3(L)
  578.             
  579.             Dim PointOnPlaneAnd2To3VecR As Double, PointOnPlaneAnd2To3VecG As Double, PointOnPlaneAnd2To3VecB As Double
  580.             PointOnPlaneAnd2To3VecR = CDbl(BMIFPAL.Palette(Values2(L)).R) + Vec2To3R * PlaneCutPosition - SrcPixels(I + 2)
  581.             PointOnPlaneAnd2To3VecG = CDbl(BMIFPAL.Palette(Values2(L)).G) + Vec2To3G * PlaneCutPosition - SrcPixels(I + 1)
  582.             PointOnPlaneAnd2To3VecB = CDbl(BMIFPAL.Palette(Values2(L)).B) + Vec2To3B * PlaneCutPosition - SrcPixels(I + 0)
  583.             
  584.             Dim VecToThatPointR As Double, VecToThatPointG As Double, VecToThatPointB As Double, VecToThatPointLen As Double
  585.             VecToThatPointR = PointOnPlaneAnd2To3VecR - Vec1R(L)
  586.             VecToThatPointG = PointOnPlaneAnd2To3VecG - Vec1G(L)
  587.             VecToThatPointB = PointOnPlaneAnd2To3VecB - Vec1B(L)
  588.             VecToThatPointLen = Sqr(VecToThatPointR * VecToThatPointR + VecToThatPointG * VecToThatPointG + VecToThatPointB * VecToThatPointB)
  589.             VecToThatPointR = VecToThatPointR / VecToThatPointLen
  590.             VecToThatPointG = VecToThatPointG / VecToThatPointLen
  591.             VecToThatPointB = VecToThatPointB / VecToThatPointLen
  592.             
  593.             ProjLen = (-Vec1R(L) * VecToThatPointR - Vec1G(L) * VecToThatPointG - Vec1B(L) * VecToThatPointB) / VecToThatPointLen
  594.             
  595.             If ProjLen * 255 <= DitherValue Then DestPixels(L) = Values1(L)
  596.             
  597.         Else '抖动颜色1、2、3、4
  598.             Dim Plane12PA As Double, Plane12PB As Double, Plane12PC As Double, Plane12PD As Double, Plane12PABCLen As Double
  599.             Dim Plane34PA As Double, Plane34PB As Double, Plane34PC As Double, Plane34PD As Double, Plane34PABCLen As Double
  600.             
  601.             Plane12PA = Vec1G(L) * Vec2B(L) - Vec1B(L) * Vec2G(L)
  602.             Plane12PB = Vec1B(L) * Vec2R(L) - Vec1R(L) * Vec2B(L)
  603.             Plane12PC = Vec1R(L) * Vec2G(L) - Vec1G(L) * Vec2R(L)
  604.             
  605.             Plane34PA = Vec3G(L) * Vec4B(L) - Vec3B(L) * Vec4G(L)
  606.             Plane34PB = Vec3B(L) * Vec4R(L) - Vec3R(L) * Vec4B(L)
  607.             Plane34PC = Vec3R(L) * Vec4G(L) - Vec3G(L) * Vec4R(L)
  608.             
  609.             Plane12PD = -(Plane12PA * SrcPixels(I + 2) + Plane12PB * SrcPixels(I + 1) + Plane12PC * SrcPixels(I + 0))
  610.             Plane34PD = -(Plane34PA * SrcPixels(I + 2) + Plane34PB * SrcPixels(I + 1) + Plane34PC * SrcPixels(I + 0))
  611.             
  612.             Plane12PABCLen = Sqr(Plane12PA * Plane12PA + Plane12PB * Plane12PB + Plane12PC * Plane12PC)
  613.             Plane34PABCLen = Sqr(Plane34PA * Plane34PA + Plane34PB * Plane34PB + Plane34PC * Plane34PC)
  614.             
  615.             Plane12PA = Plane12PA / Plane12PABCLen
  616.             Plane12PB = Plane12PB / Plane12PABCLen
  617.             Plane12PC = Plane12PC / Plane12PABCLen
  618.             Plane12PD = Plane12PD / Plane12PABCLen
  619.             
  620.             Plane34PA = Plane34PA / Plane34PABCLen
  621.             Plane34PB = Plane34PB / Plane34PABCLen
  622.             Plane34PC = Plane34PC / Plane34PABCLen
  623.             Plane34PD = Plane34PD / Plane34PABCLen
  624.             
  625.             Dim Distance1ToP34 As Double, Distance2ToP34 As Double
  626.             Dim Distance3ToP12 As Double, Distance4ToP12 As Double
  627.             
  628.             Distance1ToP34 = Abs(Vec1R(L) * Plane34PA + Vec1G(L) * Plane34PB + Vec1B(L) * Plane34PC + Plane34PD)
  629.             Distance2ToP34 = Abs(Vec2R(L) * Plane34PA + Vec2G(L) * Plane34PB + Vec2B(L) * Plane34PC + Plane34PD)
  630.             Distance3ToP12 = Abs(Vec3R(L) * Plane12PA + Vec3G(L) * Plane12PB + Vec3B(L) * Plane12PC + Plane12PD)
  631.             Distance4ToP12 = Abs(Vec4R(L) * Plane12PA + Vec4G(L) * Plane12PB + Vec4B(L) * Plane12PC + Plane12PD)
  632.             
  633.             Dim P12Cut34 As Double, P34Cut12 As Double
  634.             P12Cut34 = Distance3ToP12 + (Distance3ToP12 + Distance4ToP12)
  635.             P34Cut12 = Distance1ToP34 + (Distance1ToP34 + Distance2ToP34)
  636.             
  637.             Dim Value12 As Byte, Value34 As Byte
  638.             If P12Cut34 * 255 <= DitherValue Then Value34 = Values3(L) Else Value34 = Values4(L)
  639.             If P34Cut12 * 255 <= DitherValue Then Value12 = Values1(L) Else Value12 = Values2(L)
  640.             
  641.             Vec1To2R = Vec2R(L) - Vec1R(L)
  642.             Vec1To2G = Vec2G(L) - Vec1G(L)
  643.             Vec1To2B = Vec2B(L) - Vec1B(L)
  644.             Dim Vec3To4R As Long, Vec3To4G As Long, Vec3To4B As Long
  645.             Vec3To4R = Vec4R(L) - Vec3R(L)
  646.             Vec3To4G = Vec4G(L) - Vec3G(L)
  647.             Vec3To4B = Vec4B(L) - Vec3B(L)
  648.             
  649.             Dim CutPoint1R As Double, CutPoint1G As Double, CutPoint1B As Double
  650.             Dim CutPoint2R As Double, CutPoint2G As Double, CutPoint2B As Double
  651.             
  652.             CutPoint1R = Vec1R(L) + Vec1To2R * P34Cut12
  653.             CutPoint1G = Vec1G(L) + Vec1To2G * P34Cut12
  654.             CutPoint1B = Vec1B(L) + Vec1To2B * P34Cut12
  655.             
  656.             CutPoint2R = Vec3R(L) + Vec3To4R * P12Cut34
  657.             CutPoint2G = Vec3G(L) + Vec3To4G * P12Cut34
  658.             CutPoint2B = Vec3B(L) + Vec3To4B * P12Cut34
  659.             
  660.             Dim Dist12 As Double, Dist34 As Double
  661.             Dist12 = Sqr(CutPoint1R * CutPoint1R + CutPoint1G * CutPoint1G + CutPoint1B * CutPoint1B)
  662.             Dist34 = Sqr(CutPoint2R * CutPoint2R + CutPoint2G * CutPoint2G + CutPoint2B * CutPoint2B)
  663.         
  664.             If Dist12 * 255 / (Dist12 + Dist34) <= DitherValue Then DestPixels(L) = Value12 Else DestPixels(L) = Value34
  665.             
  666.         End If
  667.         I = I + 3
  668.         L = L + 1
  669.     Next
  670.     NTm = Timer
  671.     If NTm - Tm >= RefreshInterval Then
  672.         Tm = NTm
  673.         SetDIBits picResult.hDC, picResult.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
  674.         DrawProgress Y / (PH - 1)
  675.         picResult.Refresh
  676.         DoEvents
  677.         If QuitLoop Then Exit For
  678.     End If
  679.     LStart1 = LStart1 + Pitch1
  680.     LStart2 = LStart2 + Pitch2
  681. Next
  682. SetDIBits picResult.hDC, picResult.Image.Handle, 0, PH, DestPixels(0), BMIFPAL, DIB_RGB_COLORS
  683. DrawProgress 1
  684. picResult.Refresh


  685. cmdDither.Enabled = False

  686. OpSrcPic.Enabled = True
  687. OpDitherPic.Enabled = True
  688. OpDitherPic.Value = True
  689. End Sub

  690. Private Sub Form_Load()
  691. With BMIF24
  692.     .biSize = 40
  693.     .biPlanes = 1
  694.     .biBitCount = 24
  695. End With
  696. With BMIFPAL
  697.     .biSize = 40
  698.     .biPlanes = 1
  699.     .biBitCount = COLORS_BITS
  700.     .biClrUsed = COLORS_MAX
  701.     .biClrImportant = COLORS_MAX
  702. End With
  703. LM = LoadResData(101, "LIGHTMATRIX")
  704. Randomize Timer
  705. ProgWidth = picProgress.ScaleWidth
  706. End Sub

  707. Function Lerp(ByVal V1 As Long, ByVal V2 As Long, ByVal Val_0_255 As Long) As Long
  708. Lerp = V1 + (V2 - V1) * Val_0_255 \ 255
  709. End Function

  710. Private Sub Form_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)
  711. On Local Error GoTo eHandlr
  712. Picture = LoadPicture(Data.Files(1))
  713. PW = ScaleX(Picture.Width, vbHimetric, vbPixels)
  714. PH = ScaleY(Picture.Height, vbHimetric, vbPixels)
  715. picSrcPic.Move 0, 0, PW, PH
  716. picSrcPic.PaintPicture Picture, 0, 0
  717. picColor1.Cls
  718. picColor2.Cls
  719. picColor3.Cls
  720. picColor4.Cls
  721. picResult.Cls
  722. picColor1.Visible = False
  723. picColor2.Visible = False
  724. picColor3.Visible = False
  725. picColor4.Visible = False
  726. picResult.Visible = False
  727. picColor1.Move PW * 0, 0, PW, PH
  728. picColor2.Move PW * 1, 0, PW, PH
  729. picColor3.Move PW * 2, 0, PW, PH
  730. picColor4.Move PW * 3, 0, PW, PH
  731. picResult.Move PW * 4, 0, PW, PH
  732. picDither_Resize
  733. HSDither_Change
  734. BMIF24.biWidth = PW
  735. BMIF24.biHeight = PH
  736. BMIFPAL.biWidth = PW
  737. BMIFPAL.biHeight = PH
  738. DrawProgress 0
  739. If ChRandomPalette.Value Then
  740.     Dim I&
  741.     For I = 0 To UBound(BMIFPAL.Palette)
  742.         BMIFPAL.Palette(I).R = Rnd * 255
  743.         BMIFPAL.Palette(I).G = Rnd * 255
  744.         BMIFPAL.Palette(I).B = Rnd * 255
  745.     Next
  746. Else
  747.     If CreateOctreePaletteFromHBITMAP(hDC, Picture.Handle, PW, PH, COLORS_MAX, COLORS_BITS, BMIFPAL.Palette(0)) = 0 Then
  748.         MsgBox "生成调色板失败。", vbExclamation
  749.     End If
  750. End If
  751. DrawPal
  752. cmdDither.Enabled = True
  753. OpSrcPic.Enabled = False
  754. OpDitherPic.Enabled = False
  755. OpSrcPic.Value = True
  756. Exit Sub
  757. eHandlr:
  758. MsgBox Err.Description, vbExclamation, "出错"
  759. End Sub

  760. Sub DrawPal()
  761. Dim X&, Y&
  762. Dim DrX&, DrY&
  763. Dim I&
  764. For Y = 0 To 15
  765.     DrX = 0
  766.     For X = 0 To 15
  767.         picPal.Line (DrX, DrY)-(DrX + 4, DrY + 4), RGB(BMIFPAL.Palette(I).R, BMIFPAL.Palette(I).G, BMIFPAL.Palette(I).B), BF
  768.         I = I + 1
  769.         If I >= COLORS_MAX Then Exit Sub
  770.         DrX = DrX + 5
  771.     Next
  772.     DrY = DrY + 5
  773. Next
  774. End Sub

  775. Private Sub Form_Resize()
  776. On Error Resume Next
  777. picDither.Width = picRightPanel.Left
  778. End Sub

  779. Private Sub Form_Unload(Cancel As Integer)
  780. QuitLoop = True
  781. End
  782. End Sub

  783. Private Sub HSDither_Change()
  784. On Error Resume Next
  785. Dim LeftBegin As Long
  786. LeftBegin = -HSDither.Value
  787. picColor1.Left = LeftBegin + PW * 0
  788. picColor2.Left = LeftBegin + PW * 1
  789. picColor3.Left = LeftBegin + PW * 2
  790. picColor4.Left = LeftBegin + PW * 3
  791. picResult.Left = LeftBegin + PW * 4
  792. End Sub

  793. Private Sub HSDither_Scroll()
  794. HSDither_Change
  795. End Sub

  796. Private Sub OpDitherPic_Click()
  797. picSrcPic.Visible = False
  798. picDither.Visible = True
  799. End Sub

  800. Private Sub OpSrcPic_Click()
  801. picSrcPic.Visible = True
  802. picDither.Visible = False
  803. End Sub

  804. Private Sub picDither_Resize()
  805. On Error Resume Next
  806. Dim PP1W As Long, PP1H As Long, HSMax As Long
  807. PP1W = picDither.ScaleWidth
  808. PP1H = picDither.ScaleHeight
  809. HSDither.Move 0, PP1H - 17, PP1W, 17
  810. HSMax = PW * 5 - PP1W
  811. If HSMax > 0 Then
  812.     HSDither.Max = HSMax
  813.     HSDither.LargeChange = PP1W
  814.     HSDither.Visible = True
  815. Else
  816.     HSDither.Value = 0
  817.     HSDither.Visible = False
  818. End If
  819. End Sub
复制代码
Bin下载: 取得调色板.exe (64 KB, 下载次数: 18, 售价: 1 个宅币)
Src下载: 取得调色板.7z (33.14 KB, 下载次数: 9, 售价: 10 个宅币)
回复

使用道具 举报

1109

主题

1649

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24180 个
贡献
46222 次
宅之契约
0 份
在线时间
2294 小时
注册时间
2014-1-26
 楼主| 发表于 2014-6-20 20:56:04 | 显示全部楼层
Bin的用法忘了补充了。
1、打开EXE
2、把图片拖进去
3、点“抖动按钮”,然后留意底部的滚动条!
回复 赞! 靠!

使用道具 举报

KxIX 该用户已被删除
发表于 2014-6-21 02:20:25 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 赞! 靠!

使用道具 举报

1109

主题

1649

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24180 个
贡献
46222 次
宅之契约
0 份
在线时间
2294 小时
注册时间
2014-1-26
 楼主| 发表于 2014-6-21 19:57:49 | 显示全部楼层
異界型丘比 发表于 2014-6-20 18:20
对我来说可能没什么意义 我基本都是保存PNG的

对我来说,这东西可以做成KKND2游戏的新版地图编辑器。
回复 赞! 靠!

使用道具 举报

1

主题

3

回帖

5

积分

用户组: 初·技术宅

UID
5300
精华
0
威望
0 点
宅币
1 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2019-9-15
发表于 2019-9-15 13:30:44 | 显示全部楼层
大佬,这个工具生成的256色位图可以把颜色保留的和原图接近吗?
回复 赞! 靠!

使用道具 举报

1

主题

3

回帖

5

积分

用户组: 初·技术宅

UID
5300
精华
0
威望
0 点
宅币
1 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2019-9-15
发表于 2019-9-15 13:35:47 | 显示全部楼层
谢谢啦,效果非常不错嘛
回复 赞! 靠!

使用道具 举报

1109

主题

1649

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24180 个
贡献
46222 次
宅之契约
0 份
在线时间
2294 小时
注册时间
2014-1-26
 楼主| 发表于 2019-9-17 11:33:45 | 显示全部楼层
guodanpier2019 发表于 2019-9-15 13:35
谢谢啦,效果非常不错嘛

这个抖动算法的效果并不好,请参阅论坛里的其它帖子
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-3-29 05:13 , Processed in 0.051347 second(s), 37 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表