C :操纵PPM文件的问题
C++: Issues with manipulating a PPM file
我正在研究一个可以在ppm文件上执行各种效果和操纵的程序。但是,出于测试原因,它使用CIN而不是输入文件。它应该能够一次执行多种效果,但是我什至很难做到。我将在将有效的行上运行一个removeBlue(),然后以不同的值重试,然后将其删除红色或绿色。之类的东西。有很多代码,所以我将尝试仅包括必要的内容。
#include <vector>
#include <stdlib.h>
#include <cstdlib>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;
class SimpleImageEffect
{
public:
virtual void processImage(vector<Point> &points) = 0;
};
class RemoveRed : public SimpleImageEffect
{
public:
virtual void processImage(vector<Point> &points)
{
for (Point& p : points)
{
p.setRed(0);
}
}
};
//Just an example of one of the effect classes.
//The code in them is correct, so I won't include the others unless needed.
vector<Point> parse_line(string line)
{
istringstream scanner{line};
vector<Point> result{};
int red = -1;
int green = -1;
int blue = -1;
int counter = 0;
while(scanner.good())
{
if (counter == 0)
{
counter++;
scanner >> red;
}
else if (counter == 1)
{
counter++;
scanner >> green;
}
else if (counter == 2)
{
scanner >> blue;
Point p{ red, green, blue };
result.push_back(p);
counter = 0;
}
}
return result;
}
void readFromCin()
{
string line = "";
vector<string> lines_in_file{};
int i, effect_choice;
SimpleImageEffect *effect = nullptr;
getline(cin, line);
while (line.length() > 0)
{
lines_in_file.push_back(line);
getline(cin, line);
}
for (int i = 0; i < lines_in_file.size(); i++)
{
if (lines_in_file[i] != "P3")
{
effect_choice = strToInt(lines_in_file[i]);
}
else if (lines_in_file[i] == "P3")
{
cout << lines_in_file[i] << endl;
cout << lines_in_file[i+1] << endl;
cout << lines_in_file[i+2] << endl;
}
vector<Point> points = parse_line(lines_in_file[i]);
if (effect_choice == 1) effect = new RemoveRed;
if (effect_choice == 2) effect = new RemoveGreen;
if (effect_choice == 3) effect = new RemoveBlue;
if (effect_choice == 4) effect = new NegateRed;
if (effect_choice == 5) effect = new NegateGreen;
if (effect_choice == 6) effect = new NegateBlue;
if (effect_choice == 7) effect = new AddNoise;
if (effect_choice == 8) effect = new HighContrast;
if (effect_choice == 9) effect = new ConvertToGrayscale;
effect->processImage(points);
for (auto p : points)
{
cout << p;
cout << endl;
}
}
}
int main(int argc, char** argv)
{
string menu_choice;
getline(cin, menu_choice);
if (menu_choice == "1")
{
readFromFile();
}
else
{
readFromCin();
}
return 0;
}
因此,以
的输入运行它2
1
P3
1 1
255
50 50 50
将返回
P3
1 1
255
0 50 50
,但是如果我用
运行它2
3
P3
1 2
255
50 50 50
1 2 3
它返回
P3
1 2
255
0 50 50
0 2 3
我绝对不知道是什么原因引起了问题,因此,任何帮助都将不胜感激。谢谢。
您的算法逻辑结构闻起来很大,这就是我看到的:
- 将所有非空线读为
lines_in_file
(对我来说看起来不错) - 对于每行(有问题,都需要内部循环中的其他逻辑):
- 如果不是" p3",请尝试解析[ every ]行作为整数并设置
effect_choice
(从您的代码中不清楚,在提供几个整数的行上发生了什么,但是从您的代码中进行了判断问题描述第一个整数通过strToInt
函数成功解析) - 如果" p3",则将当前行和下两条复制到输出
- [每个]线被解析为数字的三胞胎向量
-
effect
是按新的效果设置的effect_choice
的实际效果(对于每行,您也不会结束delete
CC_6,因此您正在以每条线计数泄漏内存。您当前的效果看起来像是它们可能是可能的作为"过程"功能类型的静态函数实现,因此您无需分配每个功能,只需存储请求函数的特定内存地址即可。您将其称为processImage
,而您仅处理线路,而不是整个图像。 -
effect
用于当前线三重态 - 输出线三联
- 如果不是" p3",请尝试解析[ every ]行作为整数并设置
- 循环到下一行(!)
所以输入:
2
3
P3
1 2
255
50 50 50
1 2 3
我相信(由于您没有提供很多代码),这发生了:
行已读取,并且根据特定行的情况:
line" 2":effect_choice = 2
,effect = RemoveGreen
,零三重序列分解为points
,RemoveGreen::processImage()
在空矢量上运行,空矢量打印(即没有)。
行" 3": effect_choice = 3
, effect = RemoveBlue
,零三重序列分解为 points
, RemoveBlue::processImage()
在空的矢量上运行,空矢量打印。
行" p3":线: {"P3", "1 2", "255"}
打印,零三重序列解析为 points
, RemoveGreen::processImage()
在空的矢量上运行,空矢量打印。
行" 1 2":effect_choice = 1
,effect = RemoveRed
,零三重序列分解为points
,RemoveRed::processImage()
在空矢量上运行,空矢量打印。
行" 255":effect_choice = 255
,零三重序列分解为points
,RemoveRed::processImage()
在空矢量上运行,空矢量打印。
线" 50 50 50":effect_choice = 50
,一个三重态{50, 50, 50}
分解为points
,RemoveRed::processImage()
运行,修改三重态输出{0, 50, 50}
。
行" 1 2 3":effect_choice = 1
,effect = RemoveRed
,一个三重态{1, 2, 3}
分解为points
,RemoveRed::processImage()
越过它,修改了三重态输出{0, 2, 3}
。
所有这些都应该在调试器中清晰可见,同时介绍代码,因此您可能不会调试它,这会使我的问题退缩,并且您会随着时间的流逝而付出巨大的痛苦,因为没有调试器的调试是,更加困难。
还编写代码而无需考虑算法和代码体系结构,因此需要更大的可能调试,因此从编写代码开始,您在这里浪费了更多时间。
。您应该首先设计一些算法和代码体系结构(处理了哪些数据,如何,何时需要新内存,如何释放它,代码需要循环,需要跳过或仅运行一次,等)。
仅写概述它将如何在单行注释中工作,然后将太通用的注释分为更简单的步骤,直到可以通过几行C 代码实现它们,然后将它们移动/修改它们,直到您觉得想要的算法将会用最小的" cruft"来实现(大多数评论确实可以,真正请求的内容,例如"将红色设置为零"为零",并且任何处理/准备/移动/etc et et et eq它通过智能设计)。(例如,在当前代码中,您可以在不循环的情况下通过文件标头读取,并且仅在像素数据倒入后才开始循环)
然后编写代码,可能从某个空功能定义开始,以便您已经可以在调试器中"运行"它并验证空虚的作品,然后实现您认为足够清楚的评论(或其中的一小组)实施并可以轻松测试(对尚未实现的零件没有很大的依赖)。调试 测试新代码。如果有效,请尝试清理源以删除实际不需要的任何内容,进行工作的变量名称等...然后验证它在最终版本中工作。
并再次进行另一个评论(组),直到完成为止。
使用单元测试使写入折叠代码,测试 调试,清理源回合更容易,尤其是在这种情况下,I/O是纯数据,因此很容易喂养专业的测试输入输入数据进入测试并验证预期的输出数据。
- 使用mongocxx驱动程序时包含头文件问题
- 在WSL:configure_file上对config_file的每次调用都失败:配置文件时出现问题
- 编译要在英特尔Hyperscan中使用的.cc文件时出现问题
- 使用 seekg() 读取C++中的文件时出现问题
- sqlite3 和生成文件中的链接出现问题
- C++头文件和类实现出现问题
- 用户输入字符串的文件附加问题..C++
- node-gyp 的先有鸡还是先有蛋的问题:指向依赖项中的头文件
- 读取文件并将其存储在unordered_map中时出现问题
- 编译 llvm 插件时出现问题:llvm/Config/llvm-config.h:没有这样的文件或目录
- 我在使用C++文件时遇到了一些问题
- 在Linux上使用Clang / OLLVM交叉编译helloworld Windows可执行文件时的问题
- 将文件复制到自定义位置,存在字符串转换问题
- DirectX12 的问题:"d3dApp.h":没有这样的文件或目录
- (ODR 使用问题)在不同文件中priority_queue名称相同的结构
- C++模板编程设计问题 - 根据输入文件返回不同的类型
- 读取制表符分隔的文件时出现问题 C++
- 当我在 CLion 中读取数组中的 txt 文件时C++编码问题
- 使用 RapidXML 解析大型 XML(大小大于 65 KB)文件时出现问题
- C++:读取.BMP文件时出现问题;文件结束时间早于预期