level 10
基本内容:
1.色彩与数据
2.图片格式
3.从最简单的图片格式PPM谈图像
4.像素绘制图片的问题
5.块传输的显示方式
6.jpeg解码代码的使用
7.显示mp3内嵌的jpeg图片
8.浅谈解码器接口与程序扩展
总结:代码分析与出错解决的过程。
正文:
再谈之前,希望初学者的你最少要掌握C语言的基础知识,for循环,函数,文件操作,内存分配这些还没有掌握的,还是安下心继续学习基础。当然,俺不是什么高手,只是把学习的东西分享一下罢了。如果你已经过了基础知识这关,本文还有一些关于windows程序相关的少量的内容,看不懂的话,请实际在代码中敲击,本文还涉及到16进制查看软件
hxd
的使用,请百度hxd关键字,下载这个据说用delphi语言写的软件,是免费的软件,支持中文界面,挺好用的。本文提供的源程序通过MinGW(gcc)编译器和VS编译器,请实际动手去编译。(gcc是命令行编译方式)请作好心理准备。C语言倒底能干什么?或许你很好奇,如果能从本文中悟到什么,那就达到本文分享的目的了。
2019年05月12日 06点05分
2
level 10
一、色彩与数据
数据,还是数据,计算机基本上就是围绕着处理数据在运作着。数据输入-》处理-》数据输出就是我们写程序干的主要事。色彩在计算机里也是以数据的方式表示着,屏幕上一个像素点由三原色数据表示,显示一个点的过程,如果从系统底层上来讲,就是向一个地址写入三源色数据。不理解的话,以后随着眼界的打开,你会理解今天所看到的。三原色就是红,绿,兰,英文Red, Green, Blue,所以用C语言来表示这个数据的话,如下:unsigned char r, g, b; unsigned char 取值范围是[0-255]。你自己可以算一下可以表示多少种颜色?屏幕上的图像就是连续的N个RGB数据数组。数组的C语言表示不用我说了吧?就这么简单。
二、图片格式
学了这么久的C语言,计算机用了不少时间吧?图片也下载了不少吧?你是否对这些文件感兴趣过?jpg, png, gif, bmp, tga, ppm, psd,tiff等等,太多了,据说这世界上的图片格式多得你可能都不认识,你可以百度一下xnview这个图片软件支持多少种图片格式。这此文件大多数都是由二进制数据组成的,还记得文件打开方式fopen("xxxx", "rb")这个C语言语句吗?对,就是用来打开二进制文件的。从操作系统的角度上来讲,计算机处理文件数据,只有二进制,不存在C语言教程里的讲的文本方式,不信,你用二进制方式打开一个文本文件,还是可以读出来。Windows API里CreateFile函数也是用来打开文件的,但是你查完参数资料就会发现,并没有一个叫文本方式的参数在里面,所有文件打开都是二进制方式的。图像文件大多由文件头和数据构成,所以你学过的结构体当然是有用处的。文件头的用处就是用结构体来描述图片信息的相关数据,比如图像的高度和宽度,颜色深度等,当然还有一些文字信息表示图片由什么软件创建的,版本号之类的,大家有兴趣的话,可以百度相关的图片格式,找到这些内容和图片格式所涉及到的算法,深入学习计算机语言就是这么来的,别人告诉你有这么一个东西,自己就要去搜索查资料,这都不会的话,还是别学计算机语言了。
2019年05月12日 06点05分
3
level 10
三、从最简单的图片格式PPM谈图像
PPM是来自linux世界里的一种图片格式,因为简单,所以就从它开始说起,这里我们只谈24位真彩色的PPM,其它的色彩请自行百度,它的文件头非常简单,由标志位和图像高度,宽度,色彩最大值四个要素组成。文件头后紧跟着就是图像数据,正如你在上面所看到的,图像数据排列顺序正好是RGB RGB RGB。。。这样的顺序,也就是说每三个字节表示一个像素。第一个像素对应图像的第一个点,BMP文件格式和这种格式相反,图像数据排列是BGR BGR BGR这样的,第一个像素对应的是图像最后一排数据的第一个点,也就是说图像是倒着的。下面我们来生成一个简单的PPM格式图片,代码如下:
#include <stdio.h>
#include <windows.h>
int main()
{
//windows资源
HDC hdcScreen; //屏幕
HDC hdcCompatible;//内存DC
HBITMAP hbmScreen;//位图句柄
HWND hwnd;//窗口句柄
int i, j;
int bmWidth = 200, bmHeight = 200; //图像宽和高
COLORREF pixel; //像素值
unsigned char rgb[3];//rgb色彩值
FILE *out;
//获取控制台窗口句柄,并在切图前隐藏
hwnd = GetConsoleWindow();
ShowWindow(hwnd, SW_HIDE);
//下面代码取自MSDN中关于切屏的代码
hdcScreen = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); //获取桌面DC资源
hdcCompatible = CreateCompatibleDC(hdcScreen);//创建一个兼容DC资源
//创建一个桌面大小的位图资源
hbmScreen = CreateCompatibleBitmap(hdcScreen,
GetDeviceCaps(hdcScreen, HORZRES),
GetDeviceCaps(hdcScreen, VERTRES));
SelectObject(hdcCompatible, hbmScreen);//将位图资源和兼容DC关联
//将桌面内容拷贝到兼容DC资源中,相当于切图
BitBlt(hdcCompatible,
0,0,
bmWidth, bmHeight,
hdcScreen,
0,0,
SRCCOPY);
//打开二进制文件写入
out = fopen("test.ppm", "wb");
if(!out){
printf("can't create file test.ppm\n");
return -1;
}
//写入PPM头部
fprintf(out, "P%d\n%d %d\n255\n",6, bmWidth, bmHeight);
for(i = 0; i < bmHeight; ++i)
{
for(j = 0; j < bmWidth; ++j)
{
pixel = GetPixel(hdcCompatible, j, i);//取得指定点像素
//取颜色分量
rgb[0] = GetRValue(pixel); //R
rgb[1] = GetGValue(pixel); //G
rgb[2] = GetBValue(pixel); //B
fwrite(rgb, 1, 3, out); // 写入三字节
}
}
ShowWindow(hwnd, SW_SHOW);//显示控制台窗口
puts("test.ppm 写入成功");
fclose(out);
//清理使用的资源
DeleteDC(hdcCompatible);
DeleteDC(hdcScreen);
DeleteObject(hbmScreen);
}
2019年05月12日 06点05分
4
level 10
编译运行该代码,将在当前目录下生成一个200*200大小的PPM文件,大小大概是117KB,你可以使用一些主流图片查看器软件来观看这个生成的图片,比如irfanView, acdsee,美图看看什么的等软件一般都支持这种格式。关于windows头文件,如果不清楚的话,可以简单的理解为系统提供的库函数集合,里面包含了成千的C语言函数,比标准C语言库函数总量大了足足好几倍,背下来是不可能的,需要的时候百度查资料既可,不管是linux还是windows,总会提供C语言库函数没有的功能,当作函数调用既可,没什么大不了的。至于学不学windows编程,兴趣在你自己,学不学都没什么,顺便吐一下,别想着用C语言写大型界面程序,程序一长,那种程序结构维护起来,会让人发狂的,连《windows程序设计》一书的作者都抛却C语言,跑去用C#写界面去了。这不是本文的重点,重点在于理解文件数据,任何平台,只要给我一个画点的函数,我们可以画出整个世界!
接下来,我们打开下载好的16进制编辑软件Hxd,将生成的test.ppm拖入到软件中,如下图所示:
仔细看一下红笔圈起来的地方,你可以清楚的看见PPM文件头的样子,是不是和上面代码里标注的那行是一样的么?P6就是标志位,P表示这是PPM/PBM/PGM文件,第二个值取值范围[1-6],6表示24位色彩,其它值表示什么,自行百度。接下来用0A格开,过后就是图片的宽和高,用空格格开,然后是最大色值255,紧跟着又是一个0A值作为文件头结束,从偏移0F开始就是图片数据了,有趣吧?有没有想法,设计一个自己的图片文件格式??给你一个小任务:根据上面的程序注释,自行修改上面的代码,实现切图屏幕左下角200*200像素的图片,程序就是拿来修改着玩的。
2019年05月12日 06点05分
7