转发后小视频转发服务器为什么没图像

为什么自己的一些qq图片不能转发??(我记得我没有设置禁止转发呀…………)_百度知道
按默认排序
是不是作者设置不准转发了,要不你试试保存图片然后自己发,是在不行截屏。
哦,我漏说了,作者是我自己…………
我想把自己的一些照片转发…………可它却弹出了那个
真的没遇见过。你看看你的设置
你可以复制图片
然后自己发表
对方空间不允许你转发
我的也是,怎么办?
其他类似问题
qq图片的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁从信箱转发过来的图片,为什么在QQ空间不显示、打不开?
从信箱转发过来的图片,为什么在QQ空间不显示、打不开?
有人从外面发图片到我邮箱,我就转到我的QQ空间,为什么不显示,也打不开?
不区分大小写匿名
你把图片保存再传都空间相册
再用就OK了
你分析得对,但我不是这个问题。我在邮箱上已打开看了的,是一篇日志带图片,我就转到我的空间,结果点不开,看不见东西,不知是国外发来要下载吧。不过我还是要谢谢你!
客气了,我也又过那种事、然后我一生气就把那日志删了。你可以试试把那张图保存到你的相册里然后插入图片点从相册里选择。。我没试过 你可以试试
QQ空间打不开、QQ空间进不去等,同时伴随着桌面淘宝图标删除不掉等问题。原因一:这是一个被蓄意打包和正常软件捆绑安装的广告木马,该木马运行后,若用户访问带有flash的站点,病毒会强行播放flash广告,因病毒插入的视频是在正常flash的片头及片尾展示,而该qq空间绝大多数都有flash,本来正常插入的flash已被木马攻占,所以便出现了各种"QQ空间打不开"、"QQ空间进不去"的问题。原因二:"淘宝图标"等病毒也会造成"QQ空间打不开"、"QQ空间进不去",因为桌面图标占用了系统一些注册表项,导致系统异常。原因三:被木马感染的系统文件被杀软删除,也会导致这个问题。感染这类恶意插件后的现象有:1、qq空间打不开、为什么qq空间打不开2、IE主页被篡改,无法修复。3、点击右键,只有"打开主页,创建快捷图标"两个选项4、恶意图标删除后自动生成到桌面。可牛杀毒插件清理工具可一键解决由病毒木马导致的"为什么qq空间打不开"、"qq空间打不开"等问题。修复步骤:1、首先下载可牛杀毒插件清理工具。2、点击"扫描"按钮。3、扫描结束后会自动勾选安全级别为危险的插件。这时点击"清除"按钮。4、待流氓插件被清除后,请下载可牛免费杀毒,进行全面的木马病毒清理。 可牛杀毒插件清理工具下载地址:
先把您要放在主页的图片上传到QQ相册中。
然后在相册中打开这张图片。鼠标右键,点击属性,获得 这张图片的链接地址。
然后点击自定义, -- 模块 -- 新建模块 -- 新建 大图模块
好的话还望采纳
相关知识等待您来回答
QQ空间领域专家翻看手机图片库有一张照片来自qqfavourite这是不是视频截图照片?还是转发的保存下的照片?_百度知道
翻看手机图片库有一张照片来自qqfavourite这是不是视频截图照片?还是转发的保存下的照片?
提问者采纳
只是视频截的图?而不是其他途径弄来的图吗?
其他类似问题
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁智能手机教程子分类这几天老是有人问小弟我图像获取的有关问题,其实这个有关问题很多人都回答过,小弟我也总结过,可能没有写在CSDN的博客下,这里在转发一上,希望大家不要在为这个有关
&来源:读书人网&【读书人网():综合教育门户网站】
这几天老是有人问我图像获取的问题,其实这个问题很多人都回答过,我也总结过,可能没有写在CSDN的博客上,这
这几天老是有人问我图像获取的问题,其实这个问题很多人都回答过,我也总结过,可能没有写在CSDN的博客上,这里在转发一下,希望大家不要在为这个问题加我了。本帖最后由 laviewpbt 于
22:32:57 编辑
我在博客园上发表过的,可能那里用VB的人不多/laviewpbt/archive//1493222.html/laviewpbt/archive//1492878.html一:利用GDI快速获取图像数据及处理中需注意的问题示例工程:/laviewpbt/GetDibits.rar说明:本文中大部分资料亦适合于VC或其他编程语言。谈起VB中的图像,很多人觉得VB对图像的支持太弱了,实际上,我觉得,比起VC,VB对图像的编程要方便很多。神奇的AutoRedraw,多格式的图像文件支持,AutoSize让你少去不少麻烦等等,而这些在VC中都是需要不少额外的代码的,并且VB内部用底层函数对这些功能的封装,使得其执行效率亦是相当高的。那么,今天,我要给大家用一个简单的反色程序说明如何用VB实现对各种色深的图片的处理,让你对VB信心十足。一、打开图像。这个很简单,直接使用&LoadPicture(其实就是对OleLoadPicture这个函数的封装),其支持BMP,JPG,GIF,ICO,WMF,EMF格式。这里说明一下,对于由柯达控件生成的BMP,部分GIF和JPEG2000,以及32位的ICO这个函数似乎会产生一些未知的错误。JPG格式加载后,无论原始的JPG是否是8位的,在内存中VB是以24位的DIB格式图像保存的,而GIF则以8位索引色放置于内存。至于BMP格式,则可以按照原始的文件位数加载。我们可以用下面的函数来认证。Private&Function&GetBitmapColorDepth(Pic&As&StdPicture)&As&Long&&&&&&&&Dim&Bmp&As&Bitmap&&&&&&&&GetGDIObject&Pic.Handle,&Len(Bmp),&Bmp&&&&&&&&GetBitmapColorDepth&=&Bmp.bmBitsPixel&&&&End&Function二、保存图像。这个也很简单,SavePicture函数,注意,对于BMP、ICO、WMF、EMF格式,SavePicture函数能以原始格式保存,而对于加载的GIF和&JPG格式,只能将图像保存为BMP格式,无论你给他的路径参数的后缀是什么(看到有些VB的书上居然说将后缀改为JPG就能保存为JPG格式,真是傻)。并且该函数能保留原始的位深,这对我们来说是个好消息。那么这个函数的实现在我看来也很简单,用VB内部的语言来表达就是:&&&&Put&#FileNum,&,&BmpInfoHeader&&&&&&&&&&'BMP文件头&&&&Put&#FileNum,&,&mBmpInfo&&&&&&&&&&&&&&&&'位图信息头&&&&If&mBmpInfo.biBitCount&&=&8&Then&Put&#FileNum,&,&ColorTable&&'调色板&&&&Put&#FileNum,&,&DibBytes&&&&&&&&&&&&&&&&'位图数据三、图像数据的获得这个地方就是大家常常说VB慢的罪魁祸首,因为VB的自带了一个四不像的Point和Pset函数,而这两个函数可以得到和设置图像的颜色,因此,常常会作为初学者的最爱工具,而最终的结果就是让VB落得一个骂名:龟速。&总结一下,在&VB中可以用来得到图像数据的常用API函数有:Point|P&GetPixel|SetP&&GetBitmapBits|SetBitmapB&GetDIBits|SetDIBits&;&SafeArray模拟指针等等。抛弃前两组不说,因为他们是一丘之貉。第三组函数因为是DDB函数,是设备相关的,个人认为不是很好,因为我体验过他莫名其妙的失败。最后一组因为其复杂性,不作为向大家推荐的函数。因此,我们重点谈谈&GetDIBits。&&&&Private&Declare&Function&GetDIBits&Lib&"gdi32"&Alias&"GetDIBits"&(ByVal&aHDC&As&Long,&ByVal&hBitmap&As&Long,&ByVal&nStartScan&As&Long,&ByVal&nNumScans&As&Long,&lpBits&As&Any,&lpBI&As&BITMAPINFO,&ByVal&wUsage&As&Long)&As&Long谈起GetDIBits,我们重点讲讲参数lpBits,这个参数表示存储图像数据的缓冲区首地址,编程时只需要将一个数组的第一个元素赋值给他就可以了,&而如何确定这个数组的大小是值得商榷的。我们知道,对于不同的位深每个像素所占用的字节数是不同的,既然VB保留了被加载的图像的位深,那么我们在对图像进行后续处理的时候就应该按照这个位深来给图像数据缓冲区分配内存。不过,也许大家在实际的应用中并没有这样做,而是统一把&BITMAPINFO.bmiHeader.biBitCount设置为32或者为24,那么这里其实GetDIBits&帮我们帮图像的原始格式的数据转换为我们所需要的数据了。&&&&&好,下面给出一个简单的处理反色的函数。[最优解释]顶顶顶~[其他解释]Option&ExplicitPrivate&Type&BITMAPFILEHEADER&&&&bfType&&&&&&As&Integer&&&&bfSize&&&&&&As&Long&&&&bfReserved1&As&Integer&&&&bfReserved2&As&Integer
&&&&bfOffBits&&As&LongEnd&TypePrivate&Type&Bitmap&&bmType&As&Long&&bmWidth&As&Long&&bmHeight&As&Long&&bmWidthBytes&As&Long&&bmPlanes&As&Integer&&bmBitsPixel&As&Integer&&bmBits&As&LongEnd&TypePrivate&Type&BITMAPINFOHEADER&&&&&&'40&bytes&&biSize&As&Long&&&&&&&&&&&&&&&&&&'BITMAPINFOHEADER结构的大小&&biWidth&As&Long&&biHeight&As&Long&&biPlanes&As&Integer&&&&&&&&&&&&&&'设备的为平面数,现在都是1&&biBitCount&As&Integer&&&&&&&&&&&&'图像的颜色位图&&biCompression&As&Long&&&&&&&&&&&&'压缩方式&&biSizeImage&As&Long&&&&&&&&&&&&&&'实际的位图数据所占字节&&biXPelsPerMeter&As&Long&&&&&&&&&&'目标设备的水平分辨率&&biYPelsPerMeter&As&Long&&&&&&&&&&'目标设备的垂直分辨率&&biClrUsed&As&Long&&&&&&&&&&&&&&&&'使用的颜色数&&biClrImportant&As&Long&&&&&&&&&&'重要的颜色数。如果该项为0,表示所有颜色都是重要的End&Type&Private&Type&RGBQUAD&&&&&&&&&&&&&&&&'只有bibitcount为1,2,4时才有调色板&&&&Blue&As&Byte&&&&&&&&&&&&&&&&&&&&'蓝色分量&&&&Green&As&Byte&&&&&&&&&&&&&&&&&&&&'绿色分量&&&&Red&As&Byte&&&&&&&&&&&&&&&&&&&&&&'红色分量&&&&Reserved&As&Byte&&&&&&&&&&&&&&&&'保留值End&TypePrivate&Type&BITMAPINFO&&&&bmiHeader&As&BITMAPINFOHEADER&&&&bmiColors&As&RGBQUADEnd&TypePrivate&Const&BI_RGB&=&0&Private&Const&DIB_RGB_COLORS&=&0&Private&Declare&Function&GetDIBits&Lib&"gdi32"&(ByVal&aHDC&As&Long,&ByVal&hBitmap&As&Long,&ByVal&nStartScan&As&Long,&ByVal&nNumScans&As&Long,&lpBits&As&Any,&lpBI&As&BITMAPINFO,&ByVal&wUsage&As&Long)&As&LongPrivate&Declare&Function&GetGDIObject&Lib&"gdi32.dll"&Alias&"GetObjectA"&(ByVal&hObject&As&Long,&ByVal&nCount&As&Long,&ByRef&lpObject&As&Any)&As&LongPrivate&Declare&Function&SetDIBits&Lib&"gdi32"&(ByVal&hDC&As&Long,&ByVal&hBitmap&As&Long,&ByVal&nStartScan&As&Long,&ByVal&nNumScans&As&Long,&lpBits&As&Any,&lpBI&As&BITMAPINFO,&ByVal&wUsage&As&Long)&As&Long
Private&Declare&Function&GetDC&Lib&"user32"&(ByVal&hwnd&As&Long)&As&LongPrivate&Declare&Function&ReleaseDC&Lib&"user32"&(ByVal&hwnd&As&Long,&ByVal&hDC&As&Long)&As&LongPrivate&Function&Invert(Pic&As&StdPicture)&As&Boolean&&'&&&&Dim&i&&&&&&&&&&As&Long,&hDC&&&&As&Long&&&&Dim&Bmp&As&Bitmap,&BmpInfo&As&BITMAPINFO&&&&GetGDIObject&Pic.Handle,&Len(Bmp),&Bmp&&&&With&BmpInfo.bmiHeader&&&&&&&&.biSize&=&Len(BmpInfo.bmiHeader)&&&&&&&&.biWidth&=&Bmp.bmWidth&&&&&&&&.biHeight&=&Bmp.bmHeight&&&&&&&&.biPlanes&=&1&&&&&&&&.biBitCount&=&Bmp.bmBitsPixel&&&&&&&&&&&&&&'按图像实际的位深设置&,&&&&&&&&&.biCompression&=&BI_RGB&&&&End&With&&&&hDC&=&GetDC(0)&&&&ReDim&PicData(Bmp.bmWidthBytes&*&Bmp.bmHeight&-&1)&As&Byte&&&&'按图像数据实际的大小分配缓冲区&&&&GetDIBits&hDC,&Pic.Handle,&0,&Bmp.bmHeight,&PicData(0),&BmpInfo,&DIB_RGB_COLORS&&&&For&i&=&0&To&UBound(PicData)&&&&&&&&PicData(i)&=&255&-&PicData(i)&&&&Next&&&&SetDIBits&hDC,&Pic.Handle,&0,&Bmp.bmHeight,&PicData(0),&BmpInfo,&DIB_RGB_COLORS&&&&ReleaseDC&0,&hDCEnd&Function&调用方式类似于如下:&Call&Invert(Picture1.Picture)然后刷新一下:&Picture1.Refresh.&注意,VB中的Image对象的位深是和屏幕色深一致的,而&picture对象才会保留原始文件的位深,因此测试一定要用Picture1.Picture,不然就失去了意义。以上假设你加载的是一副24&位的图像(不管原始是什么格式).&&&在以上函数中,语句.biBitCount&=&Bmp.bmBitsPixel&&表示按照实际的位深来读取数据,而&ReDim&PicData(Bmp.bmWidthBytes&*&Bmp.bmHeight&-&1)&As&Byte&则表示按图像数据实际的大小分配缓冲区&,这时的GetDIBits&我们可以理解为一个copymemory的过程。如果你把GetDIBits&那句改为&&&&CopyMemory&PicData(0),&ByVal&Bmp.bmBits,&Bmp.bmWidthBytes&*&Bmp.bmHeight,得到的效果是一样的(感觉和模拟指针有点联系),其中&Bmp.bmBits实际上就是图像在内存的首地址,类似的SetDIBits&也可以用CopyMemory&来代替。&&&&值得说明的一点是,对于这个PicData数组的类型,不同的人可以有不同的爱好,如果.biBitCount&设置为8位及其以下位深的图像,我们没有理由将其声明为Byte之外的任何类型,若biBitCount&设置为24或&32,可能有很多人喜欢或习惯将PicData声明为RGBQUAD&结构类型,以方便理解每个分量的意义,这也无可非议,但是要注意在设置为24位的时候要删除RGBQUAD的Reserved分量声明,否则数组中的数据是不对的。另外,还有一点,对图像数据很多人喜欢用二维数据或者三维数组来记录,这样做的目的无非是数组的意义明确,我们不推荐你这样做,原因是二维数组的寻址是有系统自动完成的,在实际的操作中,有着大量的重复寻址的操作,系统确无法在这个过程中实施优化,如果是一维数组,这个操作就完全由我们掌握。若你决定用二维或三维的数据来保存图像的数据,你很可能会在编码的过程中得到不正确的结果,这是因为你对VB的数组在内存中的保存顺序不了解。对于VB中的二维数组,比如&Data(3,5),在内存中,其摆放的顺序是Data(0,0),&Data(1,0),&Data(2,0),&Data(3,0),&Data(0,1),Data(1,1),Data(2,1),Data(3,1)……,不是我们常见的矩阵从左到右,然后在从上到下,而图像的数据是按照从上到下一个扫描行一个扫描行依次保存的。因此,你所用的二维数组的第一维必须是一个扫描行的大小。简单的总结下可用的数组声明方式。PicData(Bmp.bmWidthBytes&*&Bmp.bmHeight&-&1)&As&Byte&&‘通用型PicData(Bmp.bmWidthBytes-1&,&Bmp.bmHeight&-&1)&As&Byte&&‘通用型
PicData(Bmp.bmWidth-1,&Bmp.bmHeight&-&1)&As&RGBQUAD&‘只对biBitCount=32有效PicData(3,Bmp.bmWidth-1,&Bmp.bmHeight&-&1)&As&Byte&&‘只对biBitCount=32有效PicData(Bmp.bmWidth-1,&Bmp.bmHeight&-&1)&As&long‘只对biBitCount=32有效注意:请按照上面数组的位数设置GetDIBits的lpBits参数。以上的反色代码假设你加载的是一副24位或32位的图像,但是如果你加载一副8位或8位以下的BMP图像,然后执行该代码看看(提示,一定要保存下先哦),怎么样,VB悄无声息的消失了,这一次,你问10个人有9个人可能不知道问题出在那里,似乎每个函数都没有问题,如果你单步调试,发现执行到GetDIBits&这里VB挂掉,因此,问题就出在这个函数上。&&&&我们知道,8位及8位以下的图像都有调色板,那么调色板的信息如何得到呢,我们注意到Private&Type&BITMAPINFO&&&&bmiHeader&As&BITMAPINFOHEADER&&&&bmiColors&As&RGBQUADEnd&Type&&&&这个结构中除了位图信息头之外还有个RGBQUAD&元素,GetDIBits&函数在执行时会自动将图像的信息填充到这个结构体中,而对于8位位图,一般有256个RGBQUAD&元素的调色板,而我们的声明中只给了他一个元素的空间,因此,会造成访问非法内存之类的事情发生,导致IDE崩溃。&&&&那么,解决问题的方式就是修改BITMAPINFO&结构的声明方式,现修改如下:&&&&Private&Type&BITMAPINFO&&&&&&&&bmiHeader&As&BITMAPINFOHEADER&&&&&&&&bmiColors(255)&As&RGBQUAD&&&&End&Type&&&&然后执行类似的代码,很多情况下,你看到的不正确的效果,至于为什么,详细的分析见&&http://topic.csdn.net/u//3bb480ae-3eeb-4f5d-80db-19ecc61202e6.html&&&&实际上,在PS中能对索引色进行调增的选项很少,只有调整菜单中的若干项,而那若干项其实都是读调色板进行处理的,而没有改变实际的图像数据,因此,对于&8位色以下的图像,反色的过程应该类似如下:&&&&For&i&=&0&To&255&&&&&&&&BmpInfo.bmiColors(i).Red&=&255&-&BmpInfo.bmiColors(i).Red&&&&&&&&BmpInfo.bmiColors(i).Green&=&255&-&BmpInfo.bmiColors(i).Green&&&&&&&&BmpInfo.bmiColors(i).Blue&=&255&-&BmpInfo.bmiColors(i).Blue&&&&Next&&&&&对于4位色以及1为色,调色板中最多只会有16和2个元素,对于8位色,也会存在调色板中只有在【17,255】个元素的情况,但是由于对索引色图像的处理时一般不改动数据,而只改变调色板,为了方便,这里的&bmiColors(255)&As&RGBQUAD&直接定义为255个比较方便。&&&&按照严格的定义,索引色中实际使用的调色板数应该由biClrUsed&As&Long给出,但是,我观察过很多图像,这个值默认都是0,即使8位色没有使用256个或4位色没有使用哪个16个调色板,因此,如果你必须得到实际用的调色板数,可以根据bmiColors的颜色数字来判断。提示:PS中会把白色和黑色两种索引色放在调色板的最前面(如果有的话)。&&&&好了,也许你认为完美了,其实不然,我们再回到24色及32位色的问题上,&&&&&For&i&=&0&To&UBound(PicData)&&&&&&&&PicData(i)&=&255&-&PicData(i)&&&&Next&&&&从严格的以上讲,这个代码所执行的过程已经大于了反色算法的需求了,这里因为是简单反色算法,所以我们看不出什么异常。而实际过程是,我们很有可能处理了一些我们不需要处理的数据。还记得扫描行的概念吗,扫描行的字节数必须是4的倍数(这是指DIB,对于DDB是2个倍数,一定要分清哦),不够的部分用0&补齐。由我们上述的代码可以看到,对于这些用0补齐的部分反色后就变为255了,因此,最终的反色算法应该如下:Public&Function&Invert(Pic&As&StdPicture)&As&Boolean&&'&&&&Dim&i&&&&&&&&&&As&Long,&j&&&&&&&&&&As&Long&&&&Dim&hDC&&&&&&&&As&Long,&Speed&&&&&&As&Long&&&&Dim&Pixel&&&&&&As&Long&&&&Dim&Bmp&&&&&&&&As&Bitmap,&BmpInfo&&As&BITMAPINFO&&&&GetGDIObject&Pic.Handle,&Len(Bmp),&Bmp&&&&With&BmpInfo.bmiHeader&&&&&&&&.biSize&=&Len(BmpInfo.bmiHeader)&&&&&&&&.biWidth&=&Bmp.bmWidth
&&&&&&&&.biHeight&=&Bmp.bmHeight&&&&&&&&.biPlanes&=&1&&&&&&&&.biBitCount&=&Bmp.bmBitsPixel&&&&&&&&.biCompression&=&BI_RGB&&&&End&With&&&&hDC&=&GetDC(0)&&&&ReDim&PicData(Bmp.bmWidthBytes&*&Bmp.bmHeight&-&1)&As&Byte&&&&GetDIBits&hDC,&Pic.Handle,&0,&Bmp.bmHeight,&PicData(0),&BmpInfo,&DIB_RGB_COLORS&&&&If&Bmp.bmBitsPixel&&=&8&Then&&&&&&&&For&i&=&0&To&255&&&&&&&&&&&&BmpInfo.bmiColors(i).Red&=&255&-&BmpInfo.bmiColors(i).Red&&&&&&&&&&&&BmpInfo.bmiColors(i).Green&=&255&-&BmpInfo.bmiColors(i).Green&&&&&&&&&&&&BmpInfo.bmiColors(i).Blue&=&255&-&BmpInfo.bmiColors(i).Blue&&&&&&&&Next&&&&Else&&&&&&&&Pixel&=&Bmp.bmBitsPixel&"&8&&&&&&&&For&j&=&0&To&Bmp.bmHeight&-&1&&&&&&&&&&&&Speed&=&j&*&Bmp.bmWidthBytes&&&&&&&&&&&&For&i&=&0&To&Bmp.bmWidth&-&1&&&&&&&&&&&&&&&&PicData(Speed)&=&255&-&PicData(Speed)&&&&&&&&&&'Blue&&&&&&&&&&&&&&&&PicData(Speed&+&1)&=&255&-&PicData(Speed&+&1)&&'Green&&&&&&&&&&&&&&&&PicData(Speed&+&2)&=&255&-&PicData(Speed&+&2)&&'Red&&&&&&&&&&&&&&&&Speed&=&Speed&+&Pixel&&&&&&&&&&&&&&&&&&&&&&&&&&'这里这样写是标准的过程,而没有考虑优化&&&&&&&&&&&&Next&&&&&&&&Next&&&&End&If&&&&SetDIBits&hDC,&Pic.Handle,&0,&Bmp.bmHeight,&PicData(0),&BmpInfo,&DIB_RGB_COLORS&&&&ReleaseDC&0,&hDCEnd&Function&&&&讲了一大堆,其实过程很简单,但是要注意到这些细节,还是有些学问的,这里拿反色只是举个例子,大家可以举一反三。顺便谈一下,上述过程和模拟指针有多大区别啊,上面不是谈到如果按照实际的位数调用哪个GetDIBits&函数,就可以看成一个CopyMemory的过程吗,用模拟指针实际上就是不要这个CopyMemory的过程了,而直接访问图像内存中的地址。Public&Function&Invert(Pic&As&StdPicture)&As&Boolean&&'&&&&Dim&i&&&&&&&&&&As&Long,&j&&&&&&&&&&As&Long&&&&Dim&hDC&&&&&&&&As&Long,&Speed&&&&&&As&Long&&&&Dim&Pixel&&&&&&As&Long&&&&Dim&Bmp&&&&&&&&As&Bitmap,&BmpInfo&&As&BITMAPINFO
&&&&GetGDIObject&Pic.Handle,&Len(Bmp),&Bmp&&&&With&BmpInfo.bmiHeader&&&&&&&&.biSize&=&Len(BmpInfo.bmiHeader)&&&&&&&&.biWidth&=&Bmp.bmWidth&&&&&&&&.biHeight&=&Bmp.bmHeight&&&&&&&&.biPlanes&=&1&&&&&&&&.biBitCount&=&Bmp.bmBitsPixel&&&&&&&&.biCompression&=&BI_RGB&&&&End&With&&&&hDC&=&GetDC(0)&&&&ReDim&PicData(Bmp.bmWidthBytes&*&Bmp.bmHeight&-&1)&As&Byte&&&&GetDIBits&hDC,&Pic.Handle,&0,&Bmp.bmHeight,&PicData(0),&BmpInfo,&DIB_RGB_COLORS&&&&If&Bmp.bmBitsPixel&&=&8&Then&&&&&&&&For&i&=&0&To&255&&&&&&&&&&&&BmpInfo.bmiColors(i).Red&=&255&-&BmpInfo.bmiColors(i).Red&&&&&&&&&&&&BmpInfo.bmiColors(i).Green&=&255&-&BmpInfo.bmiColors(i).Green&&&&&&&&&&&&BmpInfo.bmiColors(i).Blue&=&255&-&BmpInfo.bmiColors(i).Blue&&&&&&&&Next&&&&Else&&&&&&&&Pixel&=&Bmp.bmBitsPixel&"&8&&&&&&&&For&j&=&0&To&Bmp.bmHeight&-&1&&&&&&&&&&&&Speed&=&j&*&Bmp.bmWidthBytes&&&&&&&&&&&&For&i&=&0&To&Bmp.bmWidth&-&1&&&&&&&&&&&&&&&&PicData(Speed)&=&255&-&PicData(Speed)&&&&&&&&&&'Blue&&&&&&&&&&&&&&&&PicData(Speed&+&1)&=&255&-&PicData(Speed&+&1)&&'Green&&&&&&&&&&&&&&&&PicData(Speed&+&2)&=&255&-&PicData(Speed&+&2)&&'Red&&&&&&&&&&&&&&&&Speed&=&Speed&+&Pixel&&&&&&&&&&&&&&&&&&&&&&&&&&'这里这样写是标准的过程,而没有考虑优化&&&&&&&&&&&&Next&&&&&&&&Next&&&&End&If&&&&SetDIBits&hDC,&Pic.Handle,&0,&Bmp.bmHeight,&PicData(0),&BmpInfo,&DIB_RGB_COLORS&&&&ReleaseDC&0,&hDCEnd&Function&&&&讲了一大堆,其实过程很简单,但是要注意到这些细节,还是有些学问的,这里拿反色只是举个例子,大家可以举一反三。顺便谈一下,上述过程和模拟指针有多大区别啊,上面不是谈到如果按照实际的位数调用哪个GetDIBits&函数,就可以看成一个CopyMemory的过程吗,用模拟指针实际上就是不要这个CopyMemory的过程了,而直接访问图像内存中的地址。[其他解释]二:&利用GDI+快速获取图像数据及处理中需注意的问题&示例工程:/laviewpbt/LockBits.rar&GDI+是对GDI的很大程度上的改进,其设计理念以及操作的方式和GDI相比有了本质的不同,因其优秀的抗锯齿功能以丰富接口函数深受广大图像和图形编程者的爱好,同GDI相比,在编程上有着较大的不同。
在GDI+的一些列函数中,有两个比较特殊,他们是GdiplusStartup以及GdiplusShutdown,在执行所有的GDI+图形或图像的函数前,一定要先调用GdiplusStartup函数,否则将返回GdiplusNotInitialized的错误,在程序关闭之前一定要调用GdiplusShutdown,否则如果你是处于VB的IDE中,则不定时的会出现VB的IDE需要关闭的错误,此时,即使你不管他,一旦在VB中有输入中文或复制等动作时,VB就会出现假死,VB中的任何按钮都不可点击。GDI+对图像格式的支持相对于GDI有了很大的扩展,在VB6.0中,不支持透明图像,比如Png格式,这个是有历史原因的,在VB6.0发行的时候,Png格式并未获得流行。GDI+可打开的格式有BMP、JPEG、GIF、PNG、TIFF&等,其中GIF、TIFF可包含多帧图像。同样,GDI+亦支持对上述格式的保存,但是不能保存多帧的GIF,这和GIF的版权可能有关。在VB中调用GDI+也是一件简单的事情,网络上已经有完整的平板化GDI+的API下载,无法找到链接或者需要的可以直接和我联系。好了,废话少说,下文我们简单谈谈如何利用GDI+获取图像的数据。首先,我们需要做的是打开一副图像,这个在GDI+中有个函数GdipLoadImageFromFile,这个函数我们经常看到有两个版本的声明,分别为:Private&Declare&Function&GdipLoadImageFromFile&Lib&"gdiplus"&(ByVal&FileName&As&String,&Image&As&Long)&As&LongPrivate&Declare&Function&GdipLoadImageFromFile&Lib&"gdiplus"&(ByVal&FileName&As&Long,&hImage&As&Long)&As&Long其中第一个版本的FileName不能直接用我们的路径,而是用StrConv(FileName,&vbUnicode),否则调用会失败,第二个版本则用StrPtr(FileName)。如果我们调用成功,则Image的值不为0。如果image不为0,则说明我们调用成功,此时如果需要显示他,则可以直接调用GdipDrawImage或其其他重载函数。为了得到图像数据以便我们进一步处理,我们需要寻找合适的函数,GDI+中同样有类似于GDI的GetPixel函数,即GdipBitmapGetPixel,同样这个不适合于图像处理,接着我们在GDI+的平板化API中寻找了GdipBitmapLockBits/&GdipBitmapUnlockBits这样一对函数,其声明如下:Public&Declare&Function&GdipBitmapLockBits&Lib&"gdiplus"&(ByVal&bitmap&As&Long,&rect&As&RECTL,&ByVal&flags&As&ImageLockMode,&ByVal&PixelFormat&As&Long,&lockedBitmapData&As&BitmapData)&As&longPublic&Declare&Function&GdipBitmapUnlockBits&Lib&"gdiplus"&(ByVal&bitmap&As&Long,&lockedBitmapData&As&BitmapData)&As&long&&&&&&我们先看看这个BitmapData结构。Public&Type&BitmapData&&&Width&As&Long&&&Height&As&Long&&&stride&As&Long&&&PixelFormat&As&Long&&&scan0&As&Long&&&Reserved&As&LongEnd&Type查看MSDN,可以知道Width、Height分别表示图像的宽度和高度,stride表示图像的扫描行宽度,PixelFormat表示图像格式,而这个scan0则表示图像的内存地址。这个scan0真是个令人欢喜的东西令人忧的东西啊,欢喜的是我们找到图像的数据了,忧的而是他是个指针,而VB没有指针。在我很久前发布的一篇文章vb.net中彩色图像数据的快速获取中所采用的方法是用Marshal.Copy把数据拷贝到一个临时数组中,那是因为在VB.NET真的无法用指针,并且使用这种方法一会造成速度缓慢,因为图像数据处理完后又要拷贝回去,二是占用的内存要多一倍。令人欣慰的是,在VB6.0中,我们可以用模拟指针的方法间接实现直接访问内存。具体请参考&图像处理系列之三:VB中的指针。在调用GdipBitmapLockBits后,如果调用成功,则会将相关信息填充到lockedBitmapData结构体中,类似于GetDIBits函数,该函数也可以设置要获取的格式,即PixelFormat参数,但是,由于GDI+的出发点不同,他会动态的加载Image,即调用GdipLoadImageFromFile函数并没有为图像分配对应的内存,因此我们强烈建议这里的PixelFormat设置成和图像实际的格式一致,这个格式可以通过GdipGetImagePixelFormat获得。至于参数中的RECTL,则表示要获取数据的矩形区域,如果你只需获取部分数据,则可以在这里改变,一般我们都需要获取图像的整个数据,这里有几个函数可以使用,如下:GdipGetImageWidth/&GdipGetImageHeight&或者GdipGetImageDimension在处理完图像的数据后,类似于SetDibits,我们要调用GdipBitmapUnlockBits来更新图像。&&&&&&&当然,如果图像是索引图像或者单色位图,我们对其进行处理时并不关心他的每个像素点的数据,而更关心其调色板,实际上,PS中对索引图像的一系列处理也只是调整了他的调色板。那么判断一副图像是否是索引图像或者单色图像最简单的方式就是利用上述GdipGetImagePixelFormat返回的值,如果返回值是PixelFormat8bppIndexed,&PixelFormat4bppIndexed,&PixelFormat1bppIndexed,则为索引图像,但是有一点要注意灰度图像是一种特殊的索引图像,由于其调色板的特殊性,灰度图像的处理是不可以直接改变其调色板的,而是改变其图像数据,这里我们不做介绍。当我们知道所处理的对象是索引图像时,则可以先通过GdipGetImagePaletteSize函数得到其调色板的大小,然后利用GdipGetImagePalette来填充我们所定义的调色板,由于VB中结构体的某些内存分配方面的限制,为编程统一方便,GDI+中的调色板在VB中需要按如下方式定义:Private&Type&ColorPalette&'(8bpp)&&&flags&&&&&&&&As&PaletteFlags&&&Count&&&&&&&&As&Long
&&&Entries(255)&As&RGBQUADEnd&Type这样,如果图像没有256个调色板值,也没有关系,我们可以通过GdipGetImagePaletteSize所确定的值做适当处理,同时由上式也可以看到,公式(PaletteSize-8)/4即为我们的调色板中实际用到的RGBQUAD结构体个数。之后,把我们的图像算法应用到这个调色板后,在通过GdipSetImagePalette更新图像的调色板则完成了整个处理过程。另外,在GDI+中除了可以利用GdipLoadImageFromFile从文件中创建GDI+的Image对象,还可利用GdipCreateBitmapFromGdiDib从GDI的DIB对象、利用GdipCreateBitmapFromHBITMAP从StdPicture对象,利用GdipCreateBitmapFromHICON从Icon的句柄,利用GdipCreateBitmapFromScan0从位图在内存的首地址等等对象创建Image,因此可方便的将GDI的图形对象转换到GDI+中。依旧以反色为例,则GDI+版本的程序可以这样写:'***************************GDI+版反色*********************************'**&&作者&&&&&&&&&&:&&&&laviewpbt'**&&开发时间&&&&&&:&&&&'**&&最后修改时间&&:&&&&&&'**&&联系方式&&&&&&:&&&&&&QQ:'**&&E-MAIL&&&&&&:&&&&&&'**&&All&Rights&Resered'***********************************************************************Private&Function&Invert(Image&As&Long)&As&Boolean&&&&Dim&PixelFormat&&&&&&&&&As&Long&&&&Dim&Dimensions&&&&&&&&&&As&RECTF,&Rct&&&&&&&&&&&&&&&As&RECT&&&&Dim&BmpData&&&&&&&&&&&&&As&BitmapData,&Rtn&&&&&&&&&&As&Long&&&&Dim&DataArr(0&To&3)&&&&&As&Byte,&pDataArr(0&To&0)&&&As&Long&&&&Dim&OldArrPtr&&&&&&&&&&&As&Long,&OldpArrPtr&&&&&&&&&As&Long&&&&Dim&LineAddBytes&&&&&&&&As&Long,&PixelAddBytes&&&&&&As&Long&&&&Dim&X&&&&&&&&&&&&&&&&&&&As&Long,&Y&&&&&&&&&&&&&&&&&&As&Long&&&&GdipGetImageBounds&Image,&Dimensions,&UnitPixel&&&&&&&&&&&&&&&&&&&'&得到图像的大小,以像素为单位,这个函数理论上不会不成功&&&&GdipGetImagePixelFormat&Image,&PixelFormat&&&&&&&&&&&&&&&&&&&&&&&&'&得到图像的真正格式&&&&Select&Case&PixelFormat&&&&Case&PixelFormat32bppRGB,&PixelFormat24bppRGB&&&&&&&&Rct.Right&=&Dimensions.nWidth&&&&&&&&Rct.Bottom&=&Dimensions.nHeight&&&&&&&&GdipBitmapLockBits&Image,&Rct,&ImageLockModeRead,&PixelFormat,&BmpData&&&&'读取图像的数据&&&&&&&&MakePoint&VarPtrArray(DataArr),&VarPtrArray(pDataArr),&OldArrPtr,&OldpArrPtr&&&&'模拟指针
&&&&&&&&pDataArr(0)&=&BmpData.scan0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'指向图像在内存中的首地址&&&&&&&&PixelAddBytes&=&IIf(PixelFormat&=&PixelFormat32bppRGB,&4,&3)&&&&&&&&&&&&&&&&&&&&'每个像素所占用的字节数&&&&&&&&LineAddBytes&=&BmpData.Stride&-&BmpData.Width&*&PixelAddBytes&&&&&&&&&&&&&&&&&&&'每个扫描行中多余的字节数,不需要处理的&&&&&&&&For&Y&=&1&To&BmpData.Height&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'从上到下扫描&&&&&&&&&&&&For&X&=&1&To&BmpData.Width&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'从左到右扫描&&&&&&&&&&&&&&&&DataArr(0)&=&255&-&DataArr(0)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'具体的算法&&&&&&&&&&&&&&&&DataArr(1)&=&255&-&DataArr(1)&&&&&&&&&&&&&&&&DataArr(2)&=&255&-&DataArr(2)&&&&&&&&&&&&&&&&pDataArr(0)&=&pDataArr(0)&+&PixelAddBytes&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'指针移位&&&&&&&&&&&&Next&&&&&&&&&&&&pDataArr(0)&=&pDataArr(0)&+&LineAddBytes&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'一到下一个扫描行的起始位置&&&&&&&&Next&&&&&&&&FreePoint&VarPtrArray(DataArr),&VarPtrArray(pDataArr),&OldArrPtr,&OldpArrPtr&&&&'释放模拟指针&&&&&&&&GdipBitmapUnlockBits&Image,&BmpData&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'更新数据
&&&&Case&PixelFormat8bppIndexed,&PixelFormat4bppIndexed,&PixelFormat1bppIndexed&&&&&&&&Dim&Palette&&&&&&&&&As&ColorPalette&&&&&&&&Dim&PaletteSize&&&&&As&Long&&&&&&&&GdipGetImagePaletteSize&Image,&PaletteSize&&&&&&&&GdipGetImagePalette&Image,&Palette,&PaletteSize&&&&&&&&For&Y&=&0&To&(PaletteSize&-&8)&/&4&-&1&&&&&&&&&&&&Palette.Entries(Y).Blue&=&255&-&Palette.Entries(Y).Blue&&&&&&&&&&&&Palette.Entries(Y).Green&=&255&-&Palette.Entries(Y).Green&&&&&&&&&&&&Palette.Entries(Y).Red&=&255&-&Palette.Entries(Y).Red&&&&&&&&Next&&&&&&&&GdipSetImagePalette&Image,&Palette&&&&End&SelectEnd&FunctionGDI+中没有DC属性,取而代之的是Graphics对象,要绘制图像,必须先创建Graphics,GdipCreateFromHDC函数可以将DC转换为Graphics,然后调用绘图函数绘制后一定要记得GdipDeleteGraphics已删除。同样,当不在使用Image对象时,也需要调用GdipDisposeImage释放他。&'******************************你的评论是我发表文章的极大动力**'**************************'***************************欢迎和你讨论图像技术问题:QQ&************************&[其他解释]二:&利用GDI+快速获取图像数据及处理中需注意的问题&示例工程:/laviewpbt/LockBits.rar&GDI+是对GDI的很大程度上的改进,其设计理念以及操作的方式和GDI相比有了本质的不同,因其优秀的抗锯齿功能以丰富接口函数深受广大图像和图形编程者的爱好,同GDI相比,在编程上有着较大的不同。在GDI+的一些列函数中,有两个比较特殊,他们是GdiplusStartup以及GdiplusShutdown,在执行所有的GDI+图形或图像的函数前,一定要先调用GdiplusStartup函数,否则将返回GdiplusNotInitialized的错误,在程序关闭之前一定要调用GdiplusShutdown,否则如果你是处于VB的IDE中,则不定时的会出现VB的IDE需要关闭的错误,此时,即使你不管他,一旦在VB中有输入中文或复制等动作时,VB就会出现假死,VB中的任何按钮都不可点击。GDI+对图像格式的支持相对于GDI有了很大的扩展,在VB6.0中,不支持透明图像,比如Png格式,这个是有历史原因的,在VB6.0发行的时候,Png格式并未获得流行。GDI+可打开的格式有BMP、JPEG、GIF、PNG、TIFF&等,其中GIF、TIFF可包含多帧图像。同样,GDI+亦支持对上述格式的保存,但是不能保存多帧的GIF,这和GIF的版权可能有关。在VB中调用GDI+也是一件简单的事情,网络上已经有完整的平板化GDI+的API下载,无法找到链接或者需要的可以直接和我联系。好了,废话少说,下文我们简单谈谈如何利用GDI+获取图像的数据。首先,我们需要做的是打开一副图像,这个在GDI+中有个函数GdipLoadImageFromFile,这个函数我们经常看到有两个版本的声明,分别为:Private&Declare&Function&GdipLoadImageFromFile&Lib&"gdiplus"&(ByVal&FileName&As&String,&Image&As&Long)&As&LongPrivate&Declare&Function&GdipLoadImageFromFile&Lib&"gdiplus"&(ByVal&FileName&As&Long,&hImage&As&Long)&As&Long其中第一个版本的FileName不能直接用我们的路径,而是用StrConv(FileName,&vbUnicode),否则调用会失败,第二个版本则用StrPtr(FileName)。如果我们调用成功,则Image的值不为0。如果image不为0,则说明我们调用成功,此时如果需要显示他,则可以直接调用GdipDrawImage或其其他重载函数。为了得到图像数据以便我们进一步处理,我们需要寻找合适的函数,GDI+中同样有类似于GDI的GetPixel函数,即GdipBitmapGetPixel,同样这个不适合于图像处理,接着我们在GDI+的平板化API中寻找了GdipBitmapLockBits/&GdipBitmapUnlockBits这样一对函数,其声明如下:Public&Declare&Function&GdipBitmapLockBits&Lib&"gdiplus"&(ByVal&bitmap&As&Long,&rect&As&RECTL,&ByVal&flags&As&ImageLockMode,&ByVal&PixelFormat&As&Long,&lockedBitmapData&As&BitmapData)&As&longPublic&Declare&Function&GdipBitmapUnlockBits&Lib&"gdiplus"&(ByVal&bitmap&As&Long,&lockedBitmapData&As&BitmapData)&As&long
&&&&&&我们先看看这个BitmapData结构。Public&Type&BitmapData&&&Width&As&Long&&&Height&As&Long&&&stride&As&Long&&&PixelFormat&As&Long&&&scan0&As&Long&&&Reserved&As&LongEnd&Type查看MSDN,可以知道Width、Height分别表示图像的宽度和高度,stride表示图像的扫描行宽度,PixelFormat表示图像格式,而这个scan0则表示图像的内存地址。这个scan0真是个令人欢喜的东西令人忧的东西啊,欢喜的是我们找到图像的数据了,忧的而是他是个指针,而VB没有指针。在我很久前发布的一篇文章vb.net中彩色图像数据的快速获取中所采用的方法是用Marshal.Copy把数据拷贝到一个临时数组中,那是因为在VB.NET真的无法用指针,并且使用这种方法一会造成速度缓慢,因为图像数据处理完后又要拷贝回去,二是占用的内存要多一倍。令人欣慰的是,在VB6.0中,我们可以用模拟指针的方法间接实现直接访问内存。具体请参考&图像处理系列之三:VB中的指针。在调用GdipBitmapLockBits后,如果调用成功,则会将相关信息填充到lockedBitmapData结构体中,类似于GetDIBits函数,该函数也可以设置要获取的格式,即PixelFormat参数,但是,由于GDI+的出发点不同,他会动态的加载Image,即调用GdipLoadImageFromFile函数并没有为图像分配对应的内存,因此我们强烈建议这里的PixelFormat设置成和图像实际的格式一致,这个格式可以通过GdipGetImagePixelFormat获得。至于参数中的RECTL,则表示要获取数据的矩形区域,如果你只需获取部分数据,则可以在这里改变,一般我们都需要获取图像的整个数据,这里有几个函数可以使用,如下:GdipGetImageWidth/&GdipGetImageHeight&或者GdipGetImageDimension在处理完图像的数据后,类似于SetDibits,我们要调用GdipBitmapUnlockBits来更新图像。&&&&&&&当然,如果图像是索引图像或者单色位图,我们对其进行处理时并不关心他的每个像素点的数据,而更关心其调色板,实际上,PS中对索引图像的一系列处理也只是调整了他的调色板。那么判断一副图像是否是索引图像或者单色图像最简单的方式就是利用上述GdipGetImagePixelFormat返回的值,如果返回值是PixelFormat8bppIndexed,&PixelFormat4bppIndexed,&PixelFormat1bppIndexed,则为索引图像,但是有一点要注意灰度图像是一种特殊的索引图像,由于其调色板的特殊性,灰度图像的处理是不可以直接改变其调色板的,而是改变其图像数据,这里我们不做介绍。当我们知道所处理的对象是索引图像时,则可以先通过GdipGetImagePaletteSize函数得到其调色板的大小,然后利用GdipGetImagePalette来填充我们所定义的调色板,由于VB中结构体的某些内存分配方面的限制,为编程统一方便,GDI+中的调色板在VB中需要按如下方式定义:Private&Type&ColorPalette&'(8bpp)&&&flags&&&&&&&&As&PaletteFlags&&&Count&&&&&&&&As&Long&&&Entries(255)&As&RGBQUADEnd&Type这样,如果图像没有256个调色板值,也没有关系,我们可以通过GdipGetImagePaletteSize所确定的值做适当处理,同时由上式也可以看到,公式(PaletteSize-8)/4即为我们的调色板中实际用到的RGBQUAD结构体个数。之后,把我们的图像算法应用到这个调色板后,在通过GdipSetImagePalette更新图像的调色板则完成了整个处理过程。另外,在GDI+中除了可以利用GdipLoadImageFromFile从文件中创建GDI+的Image对象,还可利用GdipCreateBitmapFromGdiDib从GDI的DIB对象、利用GdipCreateBitmapFromHBITMAP从StdPicture对象,利用GdipCreateBitmapFromHICON从Icon的句柄,利用GdipCreateBitmapFromScan0从位图在内存的首地址等等对象创建Image,因此可方便的将GDI的图形对象转换到GDI+中。依旧以反色为例,则GDI+版本的程序可以这样写:'***************************GDI+版反色*********************************'**&&作者&&&&&&&&&&:&&&&laviewpbt'**&&开发时间&&&&&&:&&&&'**&&最后修改时间&&:&&&&&&'**&&联系方式&&&&&&:&&&&&&QQ:'**&&E-MAIL&&&&&&:&&&&&&'**&&All&Rights&Resered'***********************************************************************Private&Function&Invert(Image&As&Long)&As&Boolean&&&&Dim&PixelFormat&&&&&&&&&As&Long&&&&Dim&Dimensions&&&&&&&&&&As&RECTF,&Rct&&&&&&&&&&&&&&&As&RECT&&&&Dim&BmpData&&&&&&&&&&&&&As&BitmapData,&Rtn&&&&&&&&&&As&Long
&&&&Dim&DataArr(0&To&3)&&&&&As&Byte,&pDataArr(0&To&0)&&&As&Long&&&&Dim&OldArrPtr&&&&&&&&&&&As&Long,&OldpArrPtr&&&&&&&&&As&Long&&&&Dim&LineAddBytes&&&&&&&&As&Long,&PixelAddBytes&&&&&&As&Long&&&&Dim&X&&&&&&&&&&&&&&&&&&&As&Long,&Y&&&&&&&&&&&&&&&&&&As&Long&&&&GdipGetImageBounds&Image,&Dimensions,&UnitPixel&&&&&&&&&&&&&&&&&&&'&得到图像的大小,以像素为单位,这个函数理论上不会不成功&&&&GdipGetImagePixelFormat&Image,&PixelFormat&&&&&&&&&&&&&&&&&&&&&&&&'&得到图像的真正格式&&&&Select&Case&PixelFormat&&&&Case&PixelFormat32bppRGB,&PixelFormat24bppRGB&&&&&&&&Rct.Right&=&Dimensions.nWidth&&&&&&&&Rct.Bottom&=&Dimensions.nHeight&&&&&&&&GdipBitmapLockBits&Image,&Rct,&ImageLockModeRead,&PixelFormat,&BmpData&&&&'读取图像的数据&&&&&&&&MakePoint&VarPtrArray(DataArr),&VarPtrArray(pDataArr),&OldArrPtr,&OldpArrPtr&&&&'模拟指针&&&&&&&&pDataArr(0)&=&BmpData.scan0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'指向图像在内存中的首地址&&&&&&&&PixelAddBytes&=&IIf(PixelFormat&=&PixelFormat32bppRGB,&4,&3)&&&&&&&&&&&&&&&&&&&&'每个像素所占用的字节数&&&&&&&&LineAddBytes&=&BmpData.Stride&-&BmpData.Width&*&PixelAddBytes&&&&&&&&&&&&&&&&&&&'每个扫描行中多余的字节数,不需要处理的&&&&&&&&For&Y&=&1&To&BmpData.Height&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'从上到下扫描&&&&&&&&&&&&For&X&=&1&To&BmpData.Width&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'从左到右扫描&&&&&&&&&&&&&&&&DataArr(0)&=&255&-&DataArr(0)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'具体的算法
&&&&&&&&&&&&&&&&DataArr(1)&=&255&-&DataArr(1)&&&&&&&&&&&&&&&&DataArr(2)&=&255&-&DataArr(2)&&&&&&&&&&&&&&&&pDataArr(0)&=&pDataArr(0)&+&PixelAddBytes&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'指针移位&&&&&&&&&&&&Next&&&&&&&&&&&&pDataArr(0)&=&pDataArr(0)&+&LineAddBytes&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'一到下一个扫描行的起始位置&&&&&&&&Next&&&&&&&&FreePoint&VarPtrArray(DataArr),&VarPtrArray(pDataArr),&OldArrPtr,&OldpArrPtr&&&&'释放模拟指针&&&&&&&&GdipBitmapUnlockBits&Image,&BmpData&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'更新数据&&&&Case&PixelFormat8bppIndexed,&PixelFormat4bppIndexed,&PixelFormat1bppIndexed&&&&&&&&Dim&Palette&&&&&&&&&As&ColorPalette&&&&&&&&Dim&PaletteSize&&&&&As&Long&&&&&&&&GdipGetImagePaletteSize&Image,&PaletteSize&&&&&&&&GdipGetImagePalette&Image,&Palette,&PaletteSize&&&&&&&&For&Y&=&0&To&(PaletteSize&-&8)&/&4&-&1&&&&&&&&&&&&Palette.Entries(Y).Blue&=&255&-&Palette.Entries(Y).Blue&&&&&&&&&&&&Palette.Entries(Y).Green&=&255&-&Palette.Entries(Y).Green&&&&&&&&&&&&Palette.Entries(Y).Red&=&255&-&Palette.Entries(Y).Red&&&&&&&&Next&&&&&&&&GdipSetImagePalette&Image,&Palette&&&&End&SelectEnd&FunctionGDI+中没有DC属性,取而代之的是Graphics对象,要绘制图像,必须先创建Graphics,GdipCreateFromHDC函数可以将DC转换为Graphics,然后调用绘图函数绘制后一定要记得GdipDeleteGraphics已删除。同样,当不在使用Image对象时,也需要调用GdipDisposeImage释放他。&'******************************你的评论是我发表文章的极大动力**'**************************'***************************欢迎和你讨论图像技术问题:QQ&************************&[其他解释]帮你断一下[其他解释]顶顶,我昨天还引用了你写的一个图片保存代码。[其他解释]好&&,,顶
[其他解释]不顶对不起国家啊![其他解释]楼主乃达人!佩服。[其他解释]引用:顶顶,我昨天还引用了你写的一个图片保存代码。那个代码有一些BUG的,我一直没有去更正他。[其他解释]null

我要回帖

更多关于 如何转发小视频 的文章

 

随机推荐