c/c++控制台图片浏览
最近刚写完c++的大作业,觉得挺有意思,所以就拿来和大家分享交流一下
下面是要求
一.基本要求
使用C++语言编写程序,在控制台(字符界面)上实现图片浏览。
基本功能包括:
1. 能够浏览同一个文件夹下所有的图片,而不是只能用输入名字的方式浏览。
2. 实现图片的彩色显示。
3. 界面友好,操作简便。
4. 编写一个文档,包括程序的基本模块说明,核心功能的实现方法,人员分工等。
不要求可以显示所有的图片,只需能够浏览24位色,不超过150*150的小图片。符合要求的图片可以使用photoshop或者画图板自行制作(可以用示例中自带的图片进行测试)。
这是成品
代码如下
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
#include <Windows.h>
#include<conio.h>
#include <stdio.h>
#include <io.h>
#include <time.h>
using namespace std;
/*
求近似颜色
按照老师给的图片,这些都是24位的bmp图片,所以从其位图数据可以得到每个像素的RGB值分量,R为red,G为green,B为blue
通过RGB可以显示的颜色是很多种的,而控制台只有16种背景颜色,下面列出了14种
所以我们要将每个像素的颜色近似成这14种颜色
你可以将R,G,B想象成X,Y,Z,建立一个空间坐标系,所以,哪两个点的距离最近那么颜色也就最接近
*/
WORD RED = BACKGROUND_RED | BACKGROUND_INTENSITY;//red: 255 green: 0 blue: 0
WORD RED_DARK = BACKGROUND_RED ;//128,0,0
WORD BLUE = BACKGROUND_BLUE | BACKGROUND_INTENSITY;//0 0 255
WORD BLUE_DARK = BACKGROUND_BLUE ;//0,0,128
WORD GREEN = BACKGROUND_GREEN | BACKGROUND_INTENSITY;//0 255 0
WORD GREEN_DARK = BACKGROUND_GREEN ;//0,128,0
WORD MAGENTA = BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY;//255 0 255
WORD MAGENTA_DARK = BACKGROUND_BLUE | BACKGROUND_RED ;//128,0,128
WORD CYAN = BACKGROUND_GREEN |BACKGROUND_BLUE |BACKGROUND_INTENSITY;//0 255 255
WORD CYAN_DARK = BACKGROUND_GREEN | BACKGROUND_BLUE ;//0,128,128
WORD YELLOW = BACKGROUND_RED |BACKGROUND_GREEN |BACKGROUND_INTENSITY;//255 255 0
WORD YELLOW_DARK = BACKGROUND_RED | BACKGROUND_GREEN ;//128,128,0
WORD BLACK = 0;//0,0 0
WORD WHITE = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY;//255 255 255
/*
建立一个Color类,里面有四个属性
int R; RGB中的红色分量
int G; RGB中的绿色分量
int B; RGB中的蓝色分量
WORD value; SetConsoleTextAttribute()中第二个参数的类型,也就是字体背景颜色
还有一个以这四个为参数的构造函数
*/
class Color {
public:WORD Value;int R,G,B;Color() {}Color(WORD value, int r, int g, int b) {Value = value;R = r;G = g;B = b;}
};
/*
对tm时间进行处理,得到类似如下的时间格式
2017年12月8日 星期五 22:43:19 .
getTime函数
year 从1900开始计时,所以加上1900
month 0是一月,所以加一
day 几月几号的号,不用处理
weekDay 一个星期的第几天,0是周日,以此类推.为此专门建立一个getwDay函数,传入数字,通过switch判断,返回汉字日 一 二等
hour minute second 小时分钟秒,不用处理
最后建立字符数组date,返回我们需要的时间格式
*/
class TimeUtils {
public:static char* getTime(tm time) {long year = time.tm_year + 1900;long month = time.tm_mon + 1;long day = time.tm_mday;char weekDay[10];strcpy(weekDay, getwDay((int)time.tm_wday));long hour = time.tm_hour;long minute = time.tm_min;long second = time.tm_sec;char date[100];sprintf(date, "%ld年%ld月%ld日 星期%s %ld:%ld:%ld ", year, month, day, weekDay, hour, minute, second);return date;}static char* getwDay(int d) {switch (d){case 0:return "日";break;case 1:return "一";break;case 2:return "二";break;case 3:return "三";break;case 4:return "四";break;case 5:return "五";break;case 6:return "六";break;default:break;}}
};
/*
建立一个Color类数组,将上面十四种颜色变成Color类都储存进去
*/
Color colors[14] = { Color(RED,255,0,0),Color(RED_DARK,128,0,0),Color(BLUE,0,0,255),Color(BLUE_DARK,0,0,128),Color(GREEN,0,255,0),
Color(GREEN_DARK,0,128,0),Color(MAGENTA,255,0,255),Color(MAGENTA_DARK,128,0,128),Color(CYAN,0,255,255),Color(CYAN_DARK,0,128,128),
Color(YELLOW,255,255,0),Color(YELLOW_DARK,128,128,0),Color(BLACK,0,0,0),Color(WHITE,255,255,255) };
/*
这个方法就是得到一个颜色的近似色
参数为一个像素的RGB值的三个分量
原理:
value代表这个像素点与数组里某个颜色的"距离"(RGB类比XYZ),将value一开始设置的尽量大点
tmp是临时储存一个"距离"
index代表colors数组的第几个颜色
pow(x,y)代表x的y次方
进行一个for循环,将传入的颜色与每个颜色对比
最后返回距离最近的颜色
*/
Color getColor(int r,int g,int b) {
int value = 1000000;
int tmp = 0;
int index = 10;
for (int i = 0; i <14; i++)
{tmp = pow((colors[i].R - r), 2)+ pow((colors[i].G - g), 2) + pow((colors[i].B - b), 2) ;if (tmp<=value){value = tmp;index = i;}
}
return colors[index];
}
/*
该函数可以在控制台画出一个bmp格式文件,参数为当前文件夹图片名首先要搞清楚24位bmp图的结构
由三部分组成
1.文件头
文件头里面的信息是我们不需要的
2.信息头
这里面有图片的格式,宽度,高度等信息
3.位图数据
图片的像素详细信息;这里面的每个值都是0-255的数字,代表某个R,G或B的值
比如,开头三个连在一起是一个像素点的RGB值,然后接着三个又是下一个像素点,以此类推
*/
void drawImage(const char* fileName) {unsigned char *pBmpBuf;//读入图像数据的指针int bmpWidth;//图像的宽int bmpHeight;//图像的高int biBitCount;//图像类型,每像素位数BITMAPINFOHEADER head;//信息头FILE *fp = fopen(fileName, "rb");//fp为文件指针,fopen()为打开一个文件的函数,第一个参数为文件名,第二个为读取方式,r代表read读取,b代表byte字节fseek(fp, sizeof(BITMAPFILEHEADER), 0);//fseek()表示在一个文件内寻找;参数依次为 文件指针 跳过的长度 开始位置fread(&head, sizeof(BITMAPINFOHEADER), 1, fp);//freed表示 从文件fp里,读取1个长度为sizeof(BITMAPINFOHEADER)数据,储存到地址&head里bmpWidth = head.biWidth;bmpHeight = head.biHeight;biBitCount = head.biBitCount;int lineByte = bmpWidth * biBitCount / 8;//每一行的字节数,因为像素RGB值分量有三个,所以这是应该是宽度*3,由于是24位图,所以/8;pBmpBuf = new unsigned char[lineByte * bmpHeight];//定义指针指向的数据大小fread(pBmpBuf, 1, lineByte * bmpHeight, fp);//读取数据,将图片位图数据储存到已经开辟好的临时缓存区int i = bmpHeight*bmpWidth - bmpWidth;//i代表指针位置,由于位图数据的存储是倒过来的,所以第一行第一个应该是最后一行第一个int count = 1;//代表指针位于当前行的位置while (true){//设置字体背景颜色SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), getColor(pBmpBuf[3 * i + 2], pBmpBuf[3 * i + 1], pBmpBuf[3 * i]).Value);//打印空格printf(" ");//当前行位置右移count++;//指针位置右移i++;//如果读到当前最后一行if (count == bmpWidth){//指针进入上一行的第一个i = i - 2 * bmpWidth + 1;//位于当前行第一个count = 1;//图片打印换行printf("\n");}//如果读完,循环结束if (i<0){break;}}//将字体背景色设置回黑色SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),BLACK);fclose(fp);//关闭文件
}
/*
该函数会遍历当前文件夹内所有bmp格式图片,并将图片的相关信息写入一个文本文档中
参数为文本文档名,如果没有该文件则会新建,有则覆盖
*/
void writeMessage(const char* fileName) {//储存文件信息struct _finddata_t fileinfo;//可以将其理解为一个标识符,当你使用_findfirst时会返回一个值,如果为-1则表示找不到图片,//而后使用_findnext函数时需要传入该变量,继续上次的查找long hFile;//要打开或新建的文本文档FILE *file;//打开指定文件,第二个参数为打开方式,writefile = fopen(fileName, "w");//如果未找到bmp文件if ((hFile = _findfirst("*.bmp", &fileinfo)) == -1)return;else {do{//创建时间char createTime[100];//修改时间char writeTime[100];//赋值strcpy(createTime, TimeUtils::getTime(*localtime(&fileinfo.time_create)));strcpy(writeTime, TimeUtils::getTime(*localtime(&fileinfo.time_write)));//将信息写入文本文件fprintf(file, "文件名:%s\n创建时间:%s\n修改时间:%s\n", fileinfo.name, createTime, writeTime);fprintf(file, "文件大小:%dKB", fileinfo.size);fprintf(file, "\n\n");} while (_findnext(hFile, &fileinfo) == 0);}//关闭文件fclose(file);//结束遍历_findclose(hFile);
}
/*
先将图片信息都写入文本文件
而后开始遍历文件夹
在查找到一个图片后,先清屏,然后使用drawImage函数画出图片,使用getchar函数暂停程序
由于最外面是个参数为true的while循环,所以遍历文件夹结束后会重新开始遍历,
这样就会重新输出打印图片了
*/
int main() {writeMessage("图片信息.txt");struct _finddata_t fileinfo;long hFile;while (true){if ((hFile = _findfirst("*.bmp", &fileinfo)) == -1)return -1;else {do{system("cls");drawImage(fileinfo.name);getchar();} while (_findnext(hFile, &fileinfo) == 0);}_findclose(hFile);}return 0;}
c/c++控制台图片浏览相关推荐
- 原创“.NET研究”企业级控件库之图片浏览控件
在上两篇:我介绍了原创企业级控件库之组合查询控件 和原创企业级控件库之大数据量分页控件,受到了很多朋友的支持,给了我很大的动力,在此我特表感谢.有的朋友要求把源码提供上来,我在第一篇就讲了,源码会在我 ...
- 图片浏览(CATransition)转场动画
Main.storyboard ViewController.m // // ViewController.m // 8A04.图片浏览(转场动画) // // Created by huan ...
- iOS_“图片浏览选择”功能的编写思路
最近重新开始练习iOS开发,找感觉. 先做个简单的图片浏览选择功能.不用管是难还是简单,先实现一下. 一.步骤概述 包含三个步骤: 创建页面:图片选择页(collectionView),图片预览页 处 ...
- 一起撸个朋友圈吧 图片浏览(上)【图片点击前景色】
项目地址:github.com/razerdp/Fri- (能弱弱的求个star或者fork么QAQ) 上篇链接:一起撸个朋友圈吧 (Step6)- 评论对齐(点击评论对齐)[下] 下篇链接:一起撸个 ...
- vscode 预览图片 插件_真的动手写的VSCode的插件(图片浏览)之1
由于本职工作中经常做图像处理,于时大量的图片浏览是不可避免的. 怎么样不离开最近经常使用的VSCode,同时去看大量的图像对我来讲就是个不错的需求,尤其是某个目录下的文件. 先谈基本的需求吧,显示一个 ...
- android ViewPager 图片浏览和保存图片
在build.gradle在添加依赖 compile 'com.alibaba:fastjson:1.1.54.android' compile 'org.ligboy.retrofit2:conve ...
- android图片浏览功能,怎么在Android应用中实现一个网页图片浏览功能
怎么在Android应用中实现一个网页图片浏览功能 发布时间:2020-12-05 17:28:31 来源:亿速云 阅读:80 作者:Leah 本篇文章给大家分享的是有关怎么在Android应用中实现 ...
- 表单-图片浏览上传-单选框(二)
一.图片浏览上传 1.依然[table]标签包含, 2.[input]包含了[type]等于[file]. <table border="1" align="cen ...
- jquery插件图片浏览
jquery插件图片浏览 jquery代码部分 (function($){$.fn.mPicsList = function(options){var picsImgs = $(this).find( ...
最新文章
- Android拖拽图片的实现
- bom头解释方法和去掉方法
- 安卓高手之路之 GDI图形引擎篇
- SqlServer 获取汉字的拼音首字母
- WIN2008 R2 Active Directory 之一 部署企业中第一台Windows Ser
- 洛谷 P4245 【模板】任意模数NTT
- jvm timezone
- thinkphp v5.0.11漏洞_ThinkPHP5丨远程代码执行漏洞动态分析
- php课程 10-35 php实现文件上传的注意事项是什么
- 2020 年,远程办公太难?技术大佬齐支招!
- 【爆牙齿】说说我期待中的苹果那块板子。
- scipy.special —— 排列、组合与阶乘
- vs中c语言图形显示,VS2010/MFC编程入门之四十九(图形图像:CDC类及其屏幕绘图函数)...
- 学计算机编程要学什么软件有哪些内容,加工中心自学电脑编程应该学习什么软件...
- Pluralistic Image Completion—多元图像补全—摘要翻译—测试教程(附源码)——CVPR 2019
- 火灾自动报警系统学习心得
- 老王家esp8266及老五家WS2818灯带
- ACL技术,NAT技术,园区网组网
- 我新开的淘宝店铺怎么增加访客和销量
- python glob.glob使用