2018-05-14 13:45:15 wanty_chen 阅读数 1257
  • 征服C++ 11视频精讲

    扫码进入学习群,领取学习资料+讲师答疑 本教程是C++ Primer Plus 6th 、The C++ Programming Language_4th、Thinking in C++等国外顶级的C++著作的精华和个人超过10年的C++使用经验的完美结合。

    78928 人正在学习 去看看 李宁

1、中值滤波

       中值滤波是对一个滑动窗口内的诸像素灰度值排序,用其中值代替窗口中心象素的原来灰度值,它是一种非线性的图像平滑法,它对脉冲干扰级椒盐噪声的抑制效果好,在抑制随机噪声的同时能有效保护边缘少受模糊。

       二维中值滤波算法是:对于一幅图像的象素矩阵,取以目标象素为中心的一个子矩阵窗口,这个窗口可以是3*3 ,5*5 等根据需要选取,对窗口内的象素灰度排序,取中间一个值作为目标象素的新灰度值。

步骤:

1:通过从图像中的某个采样窗口取出奇数个数据进行排序

       在这里,我们选用的排序方法是冒泡排序

2:用排序后的中值取代要处理的数据即可

       一般的,中值滤波对图像的边界用0做扩张,所以对边界可能会出现扭曲。在这里,我对边界进行了填充,用里圈的值来填充外圈的值。若要用0填充外圈,可将imagedatafilter初始化为0:

memset(imagedatafilter,0,linebyte*bmpHeight);
如果这样,那填充的那个循环就可以去掉不要了,具体代码如下:
#include <cstring>
#include <windows.h>
#include"readbmp.h"
#include"savebmp.h"
#include<assert.h>

#define iFilterW 3
#define iFilterH 3


unsigned char GetMedianNum(int * bArray, int iFilterLen)
{
	int i, j;// 循环变量  
	unsigned char bTemp;

	// 用冒泡法对数组进行排序  
	for (j = 0; j < iFilterLen - 1; j++)
	{
		for (i = 0; i < iFilterLen - j - 1; i++)
		{
			if (bArray[i] > bArray[i + 1])
			{
				// 互换  
				bTemp = bArray[i];
				bArray[i] = bArray[i + 1];
				bArray[i + 1] = bTemp;
			}
		}
	}

	// 计算中值  
	if ((iFilterLen & 1) > 0)
	{
		// 数组有奇数个元素,返回中间一个元素  
		bTemp = bArray[(iFilterLen + 1) / 2];
	}
	else
	{
		// 数组有偶数个元素,返回中间两个元素平均值  
		bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
	}

	return bTemp;
}


void image_filter_median()
{
	char readPath[] = "D:\\C++_file\\image_deal_C++\\IMAGE_JIEQU\\jiaoyan.bmp";
	readBmp(readPath);

	unsigned char *imagedatafilter;
	unsigned char *imagedata;
	imagedata = pBmpBuf;
	int  aValue[iFilterH*iFilterW];          // 指向滤波器数组的指针  

	int lineByte = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;
	imagedatafilter = new unsigned char[lineByte * bmpHeight];
	int iFilterHM= (iFilterH - 1)/ 2;
	int iFilterWM = (iFilterW - 1) / 2;


	for (int i = iFilterHM; i < bmpHeight - iFilterHM; i++)
		for (int j = iFilterWM; j < bmpWidth - iFilterWM; j++)
			for (int k = 0; k < 3; k++)
			{
				
				for (int m  = 0; m< iFilterH; m++)
					for (int n = 0; n < iFilterW; n++)
						{
							aValue[m * iFilterW + n] = *(imagedata + lineByte* (i+m-1) + (j + n-1) * 3 + k);	
						}
				*(imagedatafilter + bmpWidth * 3 * i + j * 3 + k) = GetMedianNum(aValue, iFilterH * iFilterW); 
				
			}

	for (int i = 0; i < bmpHeight; i++)
		for (int j = 0; j < bmpWidth; j++)
				for (int k = 0; k < 3; k++)
				{

					
					if ((i<iFilterHM) && (j<iFilterWM))
								*(imagedatafilter + lineByte * i + j * 3 + k) = *(imagedatafilter + lineByte* (i + iFilterHM) + (j + iFilterWM) * 3 + k);
					else if ((i<iFilterHM) && (j>=iFilterWM)&&(j<(bmpWidth - iFilterWM)))
						*(imagedatafilter + lineByte * i + j * 3 + k) = *(imagedatafilter + lineByte* (i + iFilterHM) + j  * 3 + k);
					else if ((i<iFilterHM) && ( j >= (bmpWidth - iFilterWM)))
						*(imagedatafilter + lineByte * i + j * 3 + k) = *(imagedatafilter + lineByte* (i + iFilterHM) + (j - iFilterWM) * 3 + k);
					else if ((i>=iFilterHM) && i <(bmpHeight - iFilterHM) && (j< iFilterWM))
						*(imagedatafilter + lineByte * i + j * 3 + k) = *(imagedatafilter + lineByte* i + (j + iFilterWM) * 3 + k);
					else if ((i>=iFilterHM) && i < (bmpHeight - iFilterHM) && (j >= (bmpWidth - iFilterWM)))
						*(imagedatafilter + lineByte * i + j * 3 + k) = *(imagedatafilter + lineByte* i + (j - iFilterWM) * 3 + k);
					else if ((i >= (bmpHeight - iFilterHM)) && (j< iFilterWM))
						*(imagedatafilter + lineByte * i + j * 3 + k) = *(imagedatafilter + lineByte* (i - iFilterHM) + (j + iFilterWM) * 3 + k);
					else if ((i >= (bmpHeight - iFilterHM)) && (j>= iFilterWM)&&(j<(bmpWidth - iFilterWM)))
								*(imagedatafilter + lineByte * i + j * 3 + k) = *(imagedatafilter + lineByte* (i - iFilterHM) + j * 3 + k);
					else if ((i >= (bmpHeight - iFilterHM)) && ( j >= (bmpWidth - iFilterWM)))
						*(imagedatafilter + lineByte * i + j * 3 + k) = *(imagedatafilter + lineByte* (i - iFilterHM) + (j - iFilterWM) * 3 + k);
				
					
				}


	char writePath[] = "D:\\C++_file\\image_deal_C++\\IMAGE_JIEQU\\mm.bmp";
	saveBmp(writePath, imagedatafilter, bmpWidth, bmpHeight, biBitCount, pColorTable);
	printf("中值滤波操作完成,请查看bmp文件。\n\n");
	
}

原图:


滤波后:


2011-10-17 23:45:47 xiaoshengyige 阅读数 4255
  • 征服C++ 11视频精讲

    扫码进入学习群,领取学习资料+讲师答疑 本教程是C++ Primer Plus 6th 、The C++ Programming Language_4th、Thinking in C++等国外顶级的C++著作的精华和个人超过10年的C++使用经验的完美结合。

    78928 人正在学习 去看看 李宁
/*类名称:bmpScreen.h。
;       类功能:提供了一个MFC下截取窗口特定部分并保存为bmp图片的类。
; 类成员函数:void screenShot(CRect rect,int left,int top,char *name)
;    函数参数:Crect rect, int left, int top, int top, char* name。
;  类参数说明:
;            (1)Crect rect     定义截图框的大小。
;            (2)int left          定义截图框距截图窗口左边的距离。
;            (3)int top          定义截图框距截图窗口上边的距离。
;            (4)char *name   定义所截图的bmp图像的名称,该图像默认保存在所建项目的目录下。

*/

下载地址: http://download.csdn.net/detail/xiaoshengyige/3767549

                  

2019-06-10 15:06:57 weixin_41986518 阅读数 103
  • 征服C++ 11视频精讲

    扫码进入学习群,领取学习资料+讲师答疑 本教程是C++ Primer Plus 6th 、The C++ Programming Language_4th、Thinking in C++等国外顶级的C++著作的精华和个人超过10年的C++使用经验的完美结合。

    78928 人正在学习 去看看 李宁

VC++棒子打老鼠游戏源代码,俗称打地鼠,程序可以编译,但运行时候棒子的显示有些问题,也就是程序在处理BMP图像时候有些不完善,不过整体可以玩,相信大家都知道这款游戏 ,现在发布源代码供研究。

 

项目截图:

 

 

代码展示:

 

这个游戏纯属土鳖思路,没有用到什么游戏引擎。

1.使用按钮或QLabel铺满窗口。

2.通过简单算法随机动态的设置按钮矩阵中某个按钮的背景图像。

3.同步2过程反复设置多个按钮背景实现图像动起来,注意调节刷新时间。

4.重写按钮组鼠标事件,设置鼠标移入时光标的图案,可以是个小锤子。

5.单击事件后鼠标同理切换鼠标图案打下和抬起。

6.加入一点声音。

7.没有了。

 

 

 

2019-05-05 19:59:50 Eastmount 阅读数 4951
  • 征服C++ 11视频精讲

    扫码进入学习群,领取学习资料+讲师答疑 本教程是C++ Primer Plus 6th 、The C++ Programming Language_4th、Thinking in C++等国外顶级的C++著作的精华和个人超过10年的C++使用经验的完美结合。

    78928 人正在学习 去看看 李宁

该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门、OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子、图像增强技术、图像分割等,后期结合深度学习研究图像识别、图像分类应用。希望文章对您有所帮助,如果有不足之处,还请海涵~

该系列在github所有源代码:https://github.com/eastmountyxz/ImageProcessing-Python
PS:请求帮忙点个Star,哈哈,第一次使用Github,以后会分享更多代码,一起加油。

同时推荐作者的C++图像系列知识:
[数字图像处理] 一.MFC详解显示BMP格式图片
[数字图像处理] 二.MFC单文档分割窗口显示图片
[数字图像处理] 三.MFC实现图像灰度、采样和量化功能详解
[数字图像处理] 四.MFC对话框绘制灰度直方图
[数字图像处理] 五.MFC图像点运算之灰度线性变化、灰度非线性变化、阈值化和均衡化处理详解
[数字图像处理] 六.MFC空间几何变换之图像平移、镜像、旋转、缩放详解
[数字图像处理] 七.MFC图像增强之图像普通平滑、高斯平滑、Laplacian、Sobel、Prewitt锐化详解

前文参考:
[Python图像处理] 一.图像处理基础知识及OpenCV入门函数
[Python图像处理] 二.OpenCV+Numpy库读取与修改像素
[Python图像处理] 三.获取图像属性、兴趣ROI区域及通道处理
[Python图像处理] 四.图像平滑之均值滤波、方框滤波、高斯滤波及中值滤波
[Python图像处理] 五.图像融合、加法运算及图像类型转换
[Python图像处理] 六.图像缩放、图像旋转、图像翻转与图像平移
[Python图像处理] 七.图像阈值化处理及算法对比
[Python图像处理] 八.图像腐蚀与图像膨胀
[Python图像处理] 九.形态学之图像开运算、闭运算、梯度运算
[Python图像处理] 十.形态学之图像顶帽运算和黑帽运算
[Python图像处理] 十一.灰度直方图概念及OpenCV绘制直方图
[Python图像处理] 十二.图像几何变换之图像仿射变换、图像透视变换和图像校正
[Python图像处理] 十三.基于灰度三维图的图像顶帽运算和黑帽运算
[Python图像处理] 十四.基于OpenCV和像素处理的图像灰度化处理
[Python图像处理] 十五.图像的灰度线性变换
[Python图像处理] 十六.图像的灰度非线性变换之对数变换、伽马变换
[Python图像处理] 十七.图像锐化与边缘检测之Roberts算子、Prewitt算子、Sobel算子和Laplacian算子
[Python图像处理] 十八.图像锐化与边缘检测之Scharr算子、Canny算子和LOG算子
[Python图像处理] 十九.图像分割之基于K-Means聚类的区域分割
[Python图像处理] 二十.图像量化处理和采样处理及局部马赛克特效
[Python图像处理] 二十一.图像金字塔之图像向下取样和向上取样
[Python图像处理] 二十二.Python图像傅里叶变换原理及实现
[Python图像处理] 二十三.傅里叶变换之高通滤波和低通滤波

前面一篇文章我讲解了傅里叶变换、基于傅里叶变换的高通滤波和低通滤波。本文将继续补充常见的图像特效处理,从而让读者实现各种各样的图像特殊效果,并通过Python和OpenCV实现。基础性文章,希望对你有所帮助。同时,该部分知识均为杨秀璋查阅资料撰写,转载请署名CSDN+杨秀璋及原地址出处,谢谢!!

1.图像毛玻璃特效
2.图像浮雕特效
3.图像油漆特效
4.本文小结


PS:文章参考自己以前系列图像处理文章及OpenCV库函数,同时参考如下文献:
《数字图像处理》(第3版),冈萨雷斯著,阮秋琦译,电子工业出版社,2013年.
《数字图像处理学》(第3版),阮秋琦,电子工业出版社,2008年,北京.
《OpenCV3编程入门》,毛星云,冷雪飞,电子工业出版社,2015,北京.
Eastmount - [Android] 通过Menu实现图片怀旧、浮雕、模糊、光照和素描效果
有苦向瓜诉说 - 用Python来画浮雕画


一.图像毛玻璃特效

图像毛玻璃特效如图所示,左边为原始图像,右边为毛玻璃特效图像。它是用图像邻域内随机一个像素点的颜色来替代当前像素点颜色的过程,从而为图像增加一个毛玻璃模糊的特效。
PS:该图片为作者去喀纳斯拍摄,真心美!

Python实现代码主要是通过双层循环遍历图像的各像素点,再用定义的随机数去替换各邻域像素点的颜色,具体代码如下所示。

Image_Processing_13_01.py

#coding:utf-8
import cv2
import numpy as np

#读取原始图像
src = cv2.imread('scenery.png')

#新建目标图像
dst = np.zeros_like(src)

#获取图像行和列
rows, cols = src.shape[:2]

#定义偏移量和随机数
offsets = 5
random_num = 0

#毛玻璃效果: 像素点邻域内随机像素点的颜色替代当前像素点的颜色
for y in range(rows - offsets):
    for x in range(cols - offsets):
        random_num = np.random.randint(0,offsets)
        dst[y,x] = src[y + random_num,x + random_num]

#显示图像
cv2.imshow('src',src)
cv2.imshow('dst',dst)

cv2.waitKey()
cv2.destroyAllWindows()

二.图像浮雕特效

图像浮雕特效是仿造浮雕艺术而衍生的处理,它将要呈现的图像突起于石头表面,根据凹凸程度不同形成三维的立体效果。Python绘制浮雕图像是通过勾画图像的轮廓,并降低周围的像素值,从而产生一张具有立体感的浮雕效果图。传统的方法是设置卷积核,再调用OpenCV的filter2D()函数实现浮雕特效。该函数主要是利用内核实现对图像的卷积运算,其函数原型如下所示:

dst = filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]])

  • src表示输入图像
  • dst表示输出的边缘图,其大小和通道数与输入图像相同
  • ddepth表示目标图像所需的深度
  • kernel表示卷积核,一个单通道浮点型矩阵
  • anchor表示内核的基准点,其默认值为(-1,-1),位于中心位置
  • delta表示在储存目标图像前可选的添加到像素的值,默认值为0
  • borderType表示边框模式

核心代码如下:

kernel = np.array([[-1,0,0],[0,1,0],[0,0,0]])
output = cv2.filter2D(src, -1, kernel)

本小节将直接对各像素点进行处理,采用相邻像素相减的方法来得到图像轮廓与平面的差,类似边缘的特征,从而获得这种立体感的效果。为了增强图片的主观感受,还可以给这个差加上一个固定值,如150。实现效果如图所示。

Python通过双层循环遍历图像的各像素点,使用相邻像素值之差来表示当前像素值,从而得到图像的边缘特征,最后加上固定数值150得到浮雕效果,具体代码如下所示。

# -*- coding: utf-8 -*-
import cv2
import numpy as np

#读取原始图像
img = cv2.imread('scenery.png', 1)

#获取图像的高度和宽度
height, width = img.shape[:2]

#图像灰度处理
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

#创建目标图像
dstImg = np.zeros((height,width,1),np.uint8)

#浮雕特效算法:newPixel = grayCurrentPixel - grayNextPixel + 150
for i in range(0,height):
    for j in range(0,width-1):
        grayCurrentPixel = int(gray[i,j])
        grayNextPixel = int(gray[i,j+1])
        newPixel = grayCurrentPixel - grayNextPixel + 150
        if newPixel > 255:
            newPixel = 255
        if newPixel < 0:
            newPixel = 0
        dstImg[i,j] = newPixel
        
#显示图像
cv2.imshow('src', img)
cv2.imshow('dst',dstImg)

#等待显示
cv2.waitKey()
cv2.destroyAllWindows()

三.图像油漆特效

图像油漆特效类似于油漆染色后的轮廓图形,它主要采用自定义卷积核和cv2.filter2D()函数实现,Python实现代码主要通过Numpy定义卷积核,再进行特效处理,卷积核如公式(13-1)所示,其中心权重为10,其余值均为-1。

完整代码如下所示:

# -*- coding: utf-8 -*-
import cv2
import numpy as np

#读取原始图像
src = cv2.imread('scenery.png')

#图像灰度处理
gray = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#自定义卷积核
kernel = np.array([[-1,-1,-1],[-1,10,-1],[-1,-1,-1]])

#图像浮雕效果
output = cv2.filter2D(gray, -1, kernel)

#显示图像
cv2.imshow('Original Image', src)
cv2.imshow('Emboss_1',output)

#等待显示
cv2.waitKey()
cv2.destroyAllWindows()

输出结果如下图所示:


四.本文小结

讲到这里,作者将分享的几个特效就讲解完毕,后续将继续分享包括素描、黄昏、灯光、流光等效果,希望读者喜欢。最后补充作者五一假期的一些感受!

《这些年璋娜去过的地方》
一座城市,一道文化。一个故事,两个主角。
这些年璋娜走过的山河,陪你感受这大千世界,
留下的片片剪影和段段文字,异样的人生,精彩的生活。

图1 青海•茶卡盐湖 2017-8-30
纯洁、清澈、蓝白交织,如同一场梦境,美得恍如隔世,它就是“天空之境”茶卡盐湖。

图2 广州•小蛮腰长隆 2017-5-30
稳坐珠江夜游船,翻转长隆水世界。笑谈粤广风流人,宁负天下不负卿。

图3 云南•昆明丽江大理 2018-4-2
彩云之南,我心的方向。孔雀飞去,回忆悠长。玉龙雪山,闪耀着银光。秀色丽江,人在路上。彩云之南,归去的地方。往事芬芳,随风飘扬。蝴蝶泉边,歌声在流淌。泸沽湖畔,心在荡漾。

图4 西安•钟鼓楼兵马俑 2018-6-16
这里是炎帝故里和皇帝葬地,这里有十四个王朝建都于此,这里山川秀美、人文荟萃,这里让你感受中华上下五千年的文化,又何止五千年,这里就是西安。放慢脚步,品一个城市的文化。

图5 重庆•洪崖洞 2018-6-24
朝辞筑城下渝州,北理少年今似昨。浮生徘徊宛若梦,冷暖自知君莫愁。两位老友的结婚,让我感受了重庆文化。毕业分开之后,大家天南地北,再难聚,但很美。

图6 甘肃•敦煌莫高窟阳关 2018-9-9
在人类绚丽多姿、异彩纷呈的历史创造中,有四种文化范围最广、自成体系、光芒四射,它们是希腊文化、伊斯兰文化、印度文化和中国文化,而这四种文化曾经在一个迷人的地方交汇过,并被灿烂地表现出来,这个地方就是中国的文化圣地——敦煌。

图7 新疆•伊犁赛里木湖 2018-9-15
大西洋上最后的一滴眼泪,总闪烁着圣洁迷人的样子,不挂一丝,不染一尘。这就是伊犁的赛里木湖。站在空中草原拉那提,自己是那么的渺小,人生那些破事根本不值一提,热爱生命,敬畏自然。

图8 新疆•喀纳斯白哈巴禾木 2018-9-19
在新疆,有一种秋来绚烂如画的美,那里湖水清澈,水随着光影与周边的景物变换颜色;那里天空异常湛蓝,白云朵朵深情地望着山坡上的金黄,似置梦境,宛入油画。那就是神秘又美丽的喀纳斯。

图9 福建•厦门鼓浪屿 2019-2-22
这是一个自带文艺属性的地方,哪里都有自由浪漫的气息,在这里要学会随遇而安,走走停停,流水马龙,烟笼人家。

这些年,我们还走过四川、湖北、广西等地,
但它们还有太多风景、文化、故事等待着去抒写,还有西藏、大兴安岭、川西。

最后用米兰昆德拉的一句话结尾“真正的生活,是你现在做的事,是你那样的生活。”更是璋娜现在得样子,晚安

(By:Eastmount 2019-05-5 深夜6点写于花溪 https://blog.csdn.net/Eastmount )

2012-02-21 11:34:57 Mirage520 阅读数 1181
  • 征服C++ 11视频精讲

    扫码进入学习群,领取学习资料+讲师答疑 本教程是C++ Primer Plus 6th 、The C++ Programming Language_4th、Thinking in C++等国外顶级的C++著作的精华和个人超过10年的C++使用经验的完美结合。

    78928 人正在学习 去看看 李宁
Visual C++的CBitmap类的功能是比较弱的,它只能显示出在资源中的图标、位图、光标以及图元文件的内容,而不像VB中的Image控件可以显示出绝大多数的外部图像文件(BMP、GIF、JPEG等)。如果想要在对话框或其他窗口中显示外部图像文件则只能借助于第三方提供的控件或代码,未免过于繁琐.

   现在,.net引入了一个功能非常强大的新类 ----- CImage.有了CImage类,Visual C++在图像方面的缺憾将一去不复返。CImage是MFC和ATL共享的新类,它能从外部磁盘中调入一个JPEG、GIF、BMP和PNG格式的图像文件加以显示,而且这些文件格式可以相互转换。例如通过简单的几句,就可以实现CImage类和CBitmap类实例的:

HBITMAP hBitmap=image.Detach();
CBitmap bmp;
bmp.Attach(hBitmap);

这样一来,就又回归到以前操纵CBitmap的方式了.CImage本身封装了DIB(设备无关位图)的功能,因而能够处理每个位图像素。

它具有下列最酷特性:
  1、AlphaBlend支持像素级的颜色混合,从而实现透明和半透明的效果。
  2、PlgBlt能使一个矩形区域的位图映射到一个平行四边形区域中,而且还可能使用位屏蔽操作。
  3、TransparentBlt在目标区域中产生透明图像,SetTransparentColor用来设置某种颜色是透明色。
  4、MaskBlt在目标区域中产生源位图与屏蔽位图合成的效果。

由于CImage在不同的Windows操作系统中其某些性能是不一样的,因此在使用时要特别注意。例如,CImage::PlgBlt和 CImage::MaskBlt只能在 Windows NT 4.0 或更高版本中使用,但不能运行在Windows 95/98 应用程序中。CImage::AlphaBlend和CImage::TransparentBlt也只能在 Windows 2000/98或其更高版本中使用。即使在Windows 2000运行程序还必须将stdafx.h文件中的WINVER和_WIN32_WINNT的预定义修改成0x0500才能正常使用。

使用CImage的一般方法

  使用CImage的一般方法是这样的过程:

  (1) 打开应用程序的stdafx.h文件添加CImage类的包含文件:

#include <atlimage.h>

  (2) 定义一个CImage类对象,然后调用CImage::Load方法装载一个外部图像文件。

  (3) 调用CImage::Draw方法绘制图像。Draw方法具有如下定义:

BOOL Draw( HDC hDestDC, int xDest, int yDest,
int nDestWidth, int nDestHeight, int xSrc, int ySrc,
int nSrcWidth, int nSrcHeight );
BOOL Draw( HDC hDestDC, const RECT& rectDest, const RECT& rectSrc );
BOOL Draw( HDC hDestDC, int xDest, int yDest );
BOOL Draw( HDC hDestDC, const POINT& pointDest );
BOOL Draw( HDC hDestDC, int xDest, int yDest,
int nDestWidth, int nDestHeight );
BOOL Draw( HDC hDestDC, const RECT& rectDest );


  其中,hDestDC用来指定绘制的目标设备环境句柄,(xDest, yDest)和pointDest用来指定图像显示的位置,这个位置和源图像的左上角点相对应。nDestWidth和nDestHeight分别指定图像要显示的高度和宽度,xSrc、ySrc、nSrcWidth和nSrcHeight用来指定要显示的源图像的某个部分所在的位置和大小。 rectDest和rectSrc分别用来指定目标设备环境上和源图像所要显示的某个部分的位置和大小。

  需要说明的是,Draw方法综合了StretchBlt、TransparentBlt和AlphaBlend函数的功能。默认时,Draw的功能和 StretchBlt相同。但当图像含有透明色或Alpha通道时,它的功能又和TransparentBlt、AlphaBlend相同。因此,在一般情况下,我们都应该尽量调用CImage::Draw方法来绘制图像。

  例如,下面的示例Ex_Image是实现这样的功能:当选择"文件"ò"打开"菜单命令后,弹出一个文件打开对话框。当选定一个图像文件后,就会在窗口客户区中显示该图像文件内容。这个示例的具体步骤如下:

  (1) 创建一个默认的单文档程序项目Ex_Image。

  (2) 打开stdafx.h文件中添加CImage类的包含文件atlimage.h。

  (3) 在CEx_ImageView类添加ID_FILE_OPEN的COMMAND事件映射程序,并添加下列代码:

void CEx_ImageView::OnFileOpen()
{
 CString strFilter;
 CSimpleArray<GUID> aguidFileTypes;
 HRESULT hResult;

 // 获取CImage支持的图像文件的过滤字符串
 hResult = m_Image.GetExporterFilterString(strFilter,aguidFileTypes,
_T( "All Image Files") );
 if (FAILED(hResult)) {
  MessageBox("GetExporterFilter调用失败!");
  return;
 }
 CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
 if(IDOK != dlg.DoModal()) 
  return;

 m_Image.Destroy();
 // 将外部图像文件装载到CImage对象中
 hResult = m_Image.Load(dlg.GetFileName());
 if (FAILED(hResult)) {
  MessageBox("调用图像文件失败!");
  return;
 }

 // 设置主窗口标题栏内容
 CString str;
 str.LoadString(AFX_IDS_APP_TITLE);
 AfxGetMainWnd()->SetWindowText(str + " - " +dlg.GetFileName());

 Invalidate(); // 强制调用OnDraw
}


  (4) 定位到CEx_ImageView::OnDraw函数处,添加下列代码:

void CEx_ImageView::OnDraw(CDC* pDC)
{
 CEx_ImageDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 if (!m_Image.IsNull()) {
  m_Image.Draw(pDC->m_hDC,0,0);
 }
}


  (5) 打开Ex_ImageView.h文件,添加一个公共的成员数据m_Image:

public:
CImage m_Image;


  (6) 编译并运行。单击"打开"工具按钮,在弹出的对话框中指定一个图像文件后,单击"打开"按钮,其结果如图7.21所示。


将图片用其它格式保存

  CImage::Save方法能将一个图像文件按另一种格式来保存,它的原型如下:

HRESULT Save( LPCTSTR pszFileName, REFGUID guidFileType= GUID_NULL);

  其中,pszFileName用来指定一个文件名,guidFileType用来指定要保存的图像文件格式,当为GUID_NULL时,其文件格式由文件的扩展名来决定,这也是该函数的默认值。它还可以是GUID_BMPFile(BMP文件格式)、GUID_PNGFile(PNG文件格式)、 GUID_JPEGFile(JPEG文件格式)和GUID_GIFFile(GIF文件格式)。

  例如,下面的过程是在Ex_Image示例基础上进行的,我们在CEx_ImageView类添加ID_FILE_SAVE_AS的COMMAND事件映射程序,并添加下列代码:

void CEx_ImageView::OnFileSaveAs()
{
 if (m_Image.IsNull()) {
  MessageBox("你还没有打开一个要保存的图像文件!");
  return;
 }

 CString strFilter;
 strFilter = "位图文件|*.bmp|JPEG 图像文件|*.jpg| \
GIF 图像文件|*.gif|PNG 图像文件|*.png||";
 CFileDialog dlg(FALSE,NULL,NULL,NULL,strFilter);
 if ( IDOK != dlg.DoModal()) 
  return;

 // 如果用户没有指定文件扩展名,则为其添加一个
 CString strFileName;
 CString strExtension;

 strFileName = dlg.m_ofn.lpstrFile;
 if (dlg.m_ofn.nFileExtension == 0) 
 {
  switch (dlg.m_ofn.nFilterIndex)
  {
   case 1:
    strExtension = "bmp"; break;
   case 2:
    strExtension = "jpg"; break;
   case 3:
    strExtension = "gif"; break;
   case 4:
    strExtension = "png"; break;
   default:
    break;
  }
  strFileName = strFileName + '.' + strExtension;
 }

 // 图像保存
 HRESULT hResult = m_Image.Save(strFileName);
 if (FAILED(hResult)) 
  MessageBox("保存图像文件失败!");

将图片用其它格式保存

  CImage::Save方法能将一个图像文件按另一种格式来保存,它的原型如下:

HRESULT Save( LPCTSTR pszFileName, REFGUID guidFileType= GUID_NULL);

  其中,pszFileName用来指定一个文件名,guidFileType用来指定要保存的图像文件格式,当为GUID_NULL时,其文件格式由文件的扩展名来决定,这也是该函数的默认值。它还可以是GUID_BMPFile(BMP文件格式)、GUID_PNGFile(PNG文件格式)、 GUID_JPEGFile(JPEG文件格式)和GUID_GIFFile(GIF文件格式)。

  例如,下面的过程是在Ex_Image示例基础上进行的,我们在CEx_ImageView类添加ID_FILE_SAVE_AS的COMMAND事件映射程序,并添加下列代码:

void CEx_ImageView::OnFileSaveAs()
{
 if (m_Image.IsNull()) {
  MessageBox("你还没有打开一个要保存的图像文件!");
  return;
 }

 CString strFilter;
 strFilter = "位图文件|*.bmp|JPEG 图像文件|*.jpg| \
GIF 图像文件|*.gif|PNG 图像文件|*.png||";
 CFileDialog dlg(FALSE,NULL,NULL,NULL,strFilter);
 if ( IDOK != dlg.DoModal()) 
  return;

 // 如果用户没有指定文件扩展名,则为其添加一个
 CString strFileName;
 CString strExtension;

 strFileName = dlg.m_ofn.lpstrFile;
 if (dlg.m_ofn.nFileExtension == 0) 
 {
  switch (dlg.m_ofn.nFilterIndex)
  {
   case 1:
    strExtension = "bmp"; break;
   case 2:
    strExtension = "jpg"; break;
   case 3:
    strExtension = "gif"; break;
   case 4:
    strExtension = "png"; break;
   default:
    break;
  }
  strFileName = strFileName + '.' + strExtension;
 }

 // 图像保存
 HRESULT hResult = m_Image.Save(strFileName);
 if (FAILED(hResult)) 
  MessageBox("保存图像文件失败!");
变成黑白图片

  由于许多图像文件使用颜色表来发挥显示设备的色彩显示能力,因而将一张彩色图片变成黑色图片时需要调用CImage::IsIndexed来判断是否使用颜色表,若是则修改颜色表,否则直接将像素进行颜色设置。例如下面的代码:

void CEx_ImageView::MakeBlackAndwhite(CImage* image)
{
 if (image->IsNull()) return;

 if (!image->IsIndexed()) {
  // 直接修改像素颜色
  COLORREF pixel;
  int maxY = image->GetHeight(), maxX = image->GetWidth();
  byte r,g,b,avg;
  for (int x=0; x<maxX; x++) {
   for (int y=0; y<maxY; y++) {
    pixel = image->GetPixel(x,y);
    r = GetRValue(pixel);
    g = GetGValue(pixel);
    b = GetBValue(pixel);
    avg = (int)((r + g + b)/3);
    image->SetPixelRGB(x,y,avg,avg,avg);
   }
  }
 } else {
  // 获取并修改颜色表
  int MaxColors = image->GetMaxColorTableEntries();
  RGBQUAD* ColorTable;
  ColorTable = new RGBQUAD[MaxColors];
  image->GetColorTable(0,MaxColors,ColorTable);
  for (int i=0; i<MaxColors; i++)
  {
   int avg = (ColorTable[i].rgbBlue + ColorTable[i].rgbGreen + ColorTable[i].rgbRed)/3;
   ColorTable[i].rgbBlue = avg;
   ColorTable[i].rgbGreen = avg;
   ColorTable[i].rgbRed = avg;
  }
  image->SetColorTable(0,MaxColors,ColorTable);
  delete(ColorTable);
 }
}




转帖:

VC实现屏幕捕捉

阅读数 1210

CImage类学习

阅读数 465

没有更多推荐了,返回首页