这个是我顺手写的玩具,因此有好些bug,例如图像步长、大小不能自适应等等的问题。不过按照这个思路你能拿到很好的结果。个人认为效果也可以,先上效果:
效果可以吧。
实现思路很简单,就是按照灰度查表。但是单纯这样是拿不到好结果的——因此我使用拉普拉斯算子的一个变种进行边缘检测,然后以此进行灰度加强,最后再输出图片。完整代码如下,图像编解码使用WIC接口,手写了一个二维卷积,一个图片转灰度图。组合在一起就是结果:
/*
| Img2Char
| 文件名称: img2chr.cpp
| 文件作用: 唯一的源文件
| 创建日期: 2020-04-16
| 更新日期: 2020-04-18
| 开发人员: JuYan
+----------------------------
Copyright (C) JuYan, all rights reserved.
该程序可以把你的图像变成字符画
WARNING: bug有好几个
*/
#pragma region include和define
#include <list>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <Windows.h>
#include <algorithm>
#include <wincodec.h>
#pragma comment(lib, "Windowscodecs.lib")
#define memalloc(type, num) (type*)_memalloc(sizeof(type) * (num))
#define BUFF2(p, i, j) (*((p) + (j) * w + (i)))
#define KERNEL_W 7
#define KERNEL_H 7
#pragma endregion
#pragma region struct定义
enum ImageChannle
{
Channel_B, Channel_G, Channel_R, Channel_A
};
typedef struct tagImageData
{
BYTE *rgba;
int w, h;
} ImageData;
typedef struct tagGaryImageData
{
BYTE *dat; // 0xff是顶级
int *tmp; // 在各个处理过程中可能用到的temp数据
int w, h;
} GaryImageData;
#pragma endregion
#pragma region 全局变量
IWICImagingFactory *pFactory = NULL;
#pragma endregion
#pragma region 杂项函数
// 打印错误信息
void printmsg(const char *msg, ...)
{
va_list va;
va_start(va, msg);
vfprintf(stderr, msg, va);
putchar('\n');
va_end(va);
}
// 分配内存和释放内存
void* _memalloc(size_t sz)
{
void *p;
p = malloc(sz);
if (p == NULL)
{
printmsg("Can not allocate %d bytes on heap.", sz);
assert(0);
abort();
}
return p;
}
void memfree(void *p)
{
if (p != NULL)
{
free(p);
}
p = NULL;
}
#pragma endregion
#pragma region 图片读写
// 释放一个接口
template<class T> inline void SafeRelease(T * &p)
{
if (p)
{
p->Release();
}
p = NULL;
}
// 读取图片, 得到rgba, 失败返回false
bool LoadImageData(const wchar_t *file, ImageData *res)
{
bool ret;
BYTE *dat;
HRESULT hr;
WICRect rcLock;
UINT i, j, k, datSz, dataStrid