65.9K
CodeProject 正在变化。 阅读更多。
Home

调色板 - 你一定要喜欢它们!

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (3投票s)

2008 年 12 月 22 日

CPOL

4分钟阅读

viewsIcon

24553

downloadIcon

644

创建我们自己的调色板查看器和拾取器 UserControl

引言

调色板顾名思义。它们定义了您可以在图像中安全使用的颜色,而不会侵犯其颜色深度。例如,256 色图像的 256 色调色板是合适的,或者灰度图像的灰度调色板。在我看来,没有什么比能够读取调色板文件更能表明一个真正优秀的图像编辑程序了。而且,还有什么比用户控件更能提高清晰度和健壮性呢?

背景

首先,调色板文件是如何工作的?好吧,首先,这个图像格式有很多变种,以至于 *\.pal* 扩展名已成为一个通用扩展名,意味着任何打算用作调色板的文件都可能具有此扩展名。对于本文,我们将重点关注“JASC-PAL”格式,该格式最初由 Jasc Software 在 Paint Shop Pro 中使用。

这是一个典型的 JASC-PAL 调色板文件

JASC-PAL
0100
16
255 0 0
0 255 0
0 0 255
255 255 0
0 255 255
255 0 255
100 0 0
0 100 0
0 0 100
100 100 0
0 100 100
100 0 100
200 200 0
0 200 200
200 0 200
255 255 255

让我们分解一下,看看它是如何工作的。

第 1 行 - 文件格式标头

这是文件的一部分,用于将文件标识为 Paint Shop Pro 调色板文件。

第 2 行 - 文件格式版本

此调色板文件中使用的文件格式版本。

第 3 行 - 调色板中的颜色数量

旧规则规定 JASC-PAL 调色板文件只能包含 256 或 16 种颜色。我们不遵循这些规则。

第 4 行及之后 - 调色板数据

每一行定义了单个调色板样本的标准 RGB 值。

Using the Code

很简单!既然我们已经解决了这个问题,我们就开始处理实际的控件。我们将创建一个能够读取调色板文件的控件。它会用其中的样本填充自身,并提供对这些颜色中每一种的选择,这将是一个极其健壮的控件,为了实现这一点,我们将使用一个 FlowLayoutPanel,并为从相关调色板文件中读取的每个样本添加一个面板。但首先,我们需要定义一些全局变量

  • Private FileType As String 

    保存文件类型 - 在标头中定义

  • Private FileVersion As String 

    保存图像版本

  • Private Colours As Integer 

    保存调色板中的颜色数量

  • Private GlobalDataArray As New ArrayList 

    保存实际的调色板数据

  • Private SelectedPanel As Panel 

    保存当前选定的样本面板

  • Private ShowSelection As Boolean 

    显示白色选择框?

全局变量名称本身都比较直观,并且示例下载中的源代码已完全注释。但让我们回顾一下 PaletteReader 控件中函数的通用目的

  • AddColourSwatch - 向控件添加指定颜色的样本
  • OpenPaletteFile - 打开调色板文件,解析标头并存储调色板数据
  • SavePaletteFile - 将当前显示的调色板保存到文件
  • RemoveSwatch - 删除指定索引号的样本
  • AddPaletteSwatches - 添加 OpenPaletteFile 控件传递的数据中包含的样本到控件
  • PurgeGlobalData - 重置所有全局变量
  • HighlightSender - 突出显示引发此事件的样本
  • RemoveHighlightSender - 从引发此事件的样本中移除突出显示
  • SelectSender - 选择引发此事件的样本。

所有这些函数都非常简单,除了 OpenPaletteFileSavePalletFile 函数。OpenPalettefile 是最复杂的

Public Function OpenPaletteFile(ByVal FilePath As String) As Boolean

Try

PurgeGlobalData()

'Create Some Variables To Hold our Data [
Dim DataArray As Array
Dim OpenFile As New System.IO.StreamReader(FilePath)
Dim StringHolder As String = ""
']

'Look At The Header - Is It A Header? Or Have We Started The Data Already? [
Dim PeekHeaderLine As String = ""

PeekHeaderLine = OpenFile.ReadLine()

If PeekHeaderLine.StartsWith("JASC-PAL") Then

'Assign All The Data In The Header To A Variable [
FileType = "JASC-PAL"
FileVersion = OpenFile.ReadLine
Colours = Val(OpenFile.ReadLine)
']

Else

'If There Is No Header, Start Over [
OpenFile.Close()
OpenFile = New System.IO.StreamReader(FilePath)
']

End If

']

'Read In Our Data And Flatten It To A Single Line [
StringHolder = OpenFile.ReadToEnd
StringHolder = StringHolder.Replace(vbNewLine, " ")
']

'Close Our StreamReader [
OpenFile.Close()
']

'Split Our Data Into Sections [
DataArray = StringHolder.Split(" ")
']

'Remove Empty Items From Those Sections [
For Each StringData As String In DataArray

If Not StringData.Length = 0 Then
GlobalDataArray.Add(StringData)
End If

Next
']

'Start To Add The Swatches To The Control [
AddPaletteSwatches()
']

Catch MyException As Exception

'Return A Failure And Exit [
Return False
Exit Function
']

End Try

'Return A Success [
Return True
']

End Function

此函数的基本过程如下:

  1. 清除全局数据,准备打开新文件。
  2. 检查标头并读取标头信息。
  3. 将文件的其余部分分割成单独的值。
  4. 删除空值。
  5. 开始添加样本。

非常简单!那么接下来呢?嗯,许多图像编辑应用程序不仅可以读取和显示调色板,还可以创建和保存自定义调色板。这就是我们的 AddColourSwatchSavePaletteFile 函数的用武之地。让我们先看看 AddColourSwatch

Public Function AddColorSwatch(ByVal PanelColour As Color) As Boolean

Try

'Create A New Palette Colour Panel [
Dim NewPanel As New Panel

NewPanel.BackColor = PanelColour
NewPanel.BackgroundImage = My.Resources.Palette_Seperator
NewPanel.Margin = New Padding(0)
NewPanel.Size = New Size(12, 12)
']

AddHandler NewPanel.MouseEnter, AddressOf HighlightSender
AddHandler NewPanel.MouseLeave, AddressOf RemoveHighlightSender
AddHandler NewPanel.Click, AddressOf SelectSender

'Add It To Our Palette Holder [
SwatchLayoutPanel.Controls.Add(NewPanel)
']

Catch MyException As Exception

'Return A Failure And Exit [
Return False
Exit Function
']

End Try

'Return A Success [
Return True
']

End Function

此函数是 public 的,允许从控件的父窗体访问它,非常适合添加样本。但它是如何工作的呢?让我们来看看

  1. 创建一个新的 panel,为其分配背景图像并设置适当的大小(12x12)
  2. 向其添加事件处理程序,允许它在鼠标悬停或单击时被突出显示。
  3. 将其添加到 FlowLayoutPanel

那么如何保存呢?保存自定义调色板和样本的功能是许多图像编辑应用程序的共同点,包括 Photoshop CS3 和 CS4 以及 Paint Shop Pro。

Public Function SavePaletteFile(ByVal SaveAsJASCPAL As Boolean, _
ByVal FilePath As String) As Boolean

Try

'Open A Stream [
Dim MyStreamWriter As New System.IO.StreamWriter(FilePath)
']

'If We're Supposed To Be Saving As A JASC-PAL file, Write the Header [
If SaveAsJASCPAL Then
MyStreamWriter.WriteLine("JASC-PAL")
MyStreamWriter.WriteLine("0100")
MyStreamWriter.WriteLine(SwatchLayoutPanel.Controls.Count.ToString)
End If

']

'Write The RGB Value For Each Swatch To The File [
For Each CurrentPanel As Panel In SwatchLayoutPanel.Controls
MyStreamWriter.Write(CurrentPanel.BackColor.R & " ")
MyStreamWriter.Write(CurrentPanel.BackColor.G & " ")
MyStreamWriter.Write(CurrentPanel.BackColor.B & vbNewLine)
Next
']

'Close Everything Off [
MyStreamWriter.Flush()
MyStreamWriter.Close()
']

Catch MyException As Exception

'Return A Failure And Exit [
Return False
Exit Function
']

End Try

'Return A Success [
Return True
']

End Function

它确实如此简单。遍历 SwatchLayoutPanel 中的每个面板,并将其 RGB 值写入目标文件。

结论...

这样就完成了!一个高度可扩展的调色板查看器和选择器,可供您在应用程序中使用!我真诚地希望您在使用和修改它时和我一样快乐!

致谢

  • 非常感谢 Mark James 的 Silk Icon Pack(在演示应用程序中使用)。请访问他的网站 这里

历史

  • 2008 年 12 月 22 日 - 文章于 19:00 上传
© . All rights reserved.