转自:http://www.cppblog.com/windcsn/archive/2006/07/27/Grayscale.html
首先来看一下彩色图和灰度图的特点。
在计算机中使用最多的 RGB 彩色空间,分别对应红、绿、蓝三种颜色;通过调配三个分量的比例来组成各种颜色。一般可以使用 1 、 2 、 4 、 8 、 16 、 24、 32 位来存储这三颜色,不过现在一个分量最大是用 8 位来表示,最大值是 255 ,对于 32 位的颜色,高 8 位是用来表示通明度的。彩色图一般指 16 位以上的图。灰度图有一个特殊之处就是组成颜色的三个分量相等;而一般灰度图是 8 位以下。
在彩色电视机系统中,通常使用一种叫 YUV 的色彩空间,其中 Y 表示亮度信号;也就是这个 YUV 空间解决了彩色电视机和黑白电视机的兼容问题。
对于人眼来说,亮度信号是最敏感的,如果将彩色图像转换为灰度图像,仅仅需要转换保存亮度信号就可以。
从 RGB 到 YUV 空间的 Y 转换公式为:
Y = 0.299R+0.587G+0.114B
在 WINDOWS 中,表示 16 位以上的图和以下的图有点不同; 16 位以下的图使用一个调色板来表示选择具体的颜色,调色板的每个单元是 4 个字节,其中一个透明度;而具体的像素值存储的是索引,分别是 1 、 2 、 4 、 8 位。 16 位以上的图直接使用像素表示颜色。
那么如何将彩色图转换为灰度图呢?
灰度图中有调色板,首先需要确定调色板的具体颜色取值。我们前面提到了,灰度图的三个分量相等。
当转换为 8 位的时候,调色板中有 256 个颜色,每个正好从 0 到 255 个,三个分量都相等。
当转换为 4 位的时候,调色板中 16 个颜色,等间隔平分 255 个颜色值,三个分量都相等。
当转换为 2 位的时候,调色板中 4 个颜色,等间隔平分 255 个颜色,三个分量相等。
当转换为 1 位的时候,调色板中两个颜色,是 0 和 255 ,表示黑和白。
将彩色转换为灰度时候,按照公式计算出对应的值,该值实际上是亮度的级别;亮度从 0 到 255 ;由于不同的位有不同的亮度级别,所以 Y 的具体取值如下:
Y = Y/ (1<<(8- 转换的位数 ));
最后一点需要注意,得到 Y 值存放方式是不同的;分别用对应的位数来存储对应的 Y 值。
这里是代码片段:
计算调色板和 Y 的值代码。

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

下面是设置像素值的代码:

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

有一点需要说明的:
在计算 Y 值的时候,使用的整数除法,这是有误差的,为了消除误差,需要采用误差扩散的算法,也就是将该误差值向其邻近的想素点扩散,当然按照一定的比例来分配;例如:整除之后,余数是 5 ,采用 3/2/3 的策略,就是,右边像素和正下面的像素各占 3/8 ,而右下角的像素占 2/8 。在这方面我发现 ACDSEE 做的很好,其图像的渐进做的很好。
源码下载:ImageConvert.zip