#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <chrono>
#include <thread>
#include <cstdio>
#include <windows.h>
const char* grayScaleChars = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. ";
std::vector<unsigned char> readPPM(const std::string& filename, int& width, int& height) {
std::ifstream file(filename, std::ios::binary);
char buffer[4096];
file.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
if (!file.is_open()) {
throw std::runtime_error("无法打开文件: " + filename);
}
std::string format;
file >> format;
if (format != "P6") {
throw std::runtime_error("不支持的PPM格式: " + format);
}
file >> width >> height;
int maxColorValue;
file >> maxColorValue;
file.ignore(1);
std::vector<unsigned char> imageData(width * height * 3);
file.read(reinterpret_cast<char*>(imageData.data()), imageData.size());
return imageData;
}
unsigned char rgbToGray(unsigned char r, unsigned char g, unsigned char b) {
return static_cast<unsigned char>(0.3 * r + 0.59 * g + 0.11 * b);
}
char grayToAscii(unsigned char grayValue) {
int index = (grayValue * 69) / 255;
return grayScaleChars[index];
}
void displayAsciiImage(const std::vector<unsigned char>& imageData, int width, int height, double horizontalCompression, double verticalCompression) {
std::string asciiImage;
int newWidth = static_cast<int>(width * horizontalCompression);
int newHeight = static_cast<int>(height * verticalCompression);
for (int y = 0; y < newHeight; ++y) {
for (int x = 0; x < newWidth; ++x) {
int idx = (static_cast<int>(y / verticalCompression) * width + static_cast<int>(x / horizontalCompression)) * 3;
unsigned char r = imageData[idx];
unsigned char g = imageData[idx + 1];
unsigned char b = imageData[idx + 2];
unsigned char gray = rgbToGray(r, g, b);
asciiImage += grayToAscii(gray);
}
asciiImage += '\n';
}
std::system("cls");
std::cout << asciiImage;
}
std::string generateFrameFilename(const std::string& pattern, int frameNumber) {
char buffer[100];
sprintf(buffer, pattern.c_str(), frameNumber);
return std::string(buffer);
}
int main() {
std::string pattern;
std::cout << "请输入.ppm文件名模式 (如 a_%03d.ppm): ";
std::cin >> pattern;
int fps = 30;
std::cout << "请输入帧率 (例如 30): ";
std::cin >> fps;
int frameDelay = 1000 / fps;
int maxFrames = 10000;
double horizontalCompression, verticalCompression;
std::cout << "请输入图像宽度压缩率 (例如 0.5 表示宽度缩放为原来的50%): ";
std::cin >> horizontalCompression;
std::cout << "请输入图像高度压缩率 (建议为1.0, 若调整比例不同可改变): ";
std::cin >> verticalCompression;
for (int i = 0; i < maxFrames; ++i) {
std::string filename = generateFrameFilename(pattern, i + 1);
int width, height;
std::vector<unsigned char> imageData;
try {
imageData = readPPM(filename, width, height);
} catch (const std::exception& e) {
std::cerr << "无法读取帧: " << filename << " 错误: " << e.what() << std::endl;
break;
}
auto frameStart = std::chrono::high_resolution_clock::now();
displayAsciiImage(imageData, width, height, horizontalCompression, verticalCompression);
auto frameEnd = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> elapsed = frameEnd - frameStart;
if (elapsed.count() < frameDelay) {
std::this_thread::sleep_for(std::chrono::milliseconds(frameDelay) - elapsed);
}
}
return 0;
}