读写PPM文件 [英] Reading and writting PPM files

查看:86
本文介绍了读写PPM文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用智能代码快速读取和写入ppm代码。

不幸的是我必须使用leelin()函数来查看在读取xmax之前是否要读取以#开头的文本和ymax。

在阅读之前可以在文件指针处查找#(后跟文本)?



这是PPM文件的标题:

 P6 
#CREATOR:GIMP PNM过滤器版本1.1
1280 720
255
(二进制数据)??





我尝试过:



 #include< iostream> 
#pragma warning(disable:4996)//使用命名空间std禁用弃用
;
typedef unsigned char uchar;

// Lee de ficheros:
void leelin(FILE * strin,char * linea);

bool read_image_ppm(char * filename,uchar *& data,int& xmax1,int& ymax1);
bool save_image_ppm(char * filename,uchar * data,int xmax,int ymax);

void main()
{
uchar * data = NULL;
int xmax,ymax;
read_image_ppm(2944_1.ppm,数据,xmax,ymax);
save_image_ppm(out.ppm,数据,xmax,ymax);
删除数据;
cout<<=== END ===<< endl; getchar();
}


bool read_image_ppm(char * filename,uchar *& data,int& xmax1,int& ymax1)
{
xmax1 = ymax1 = 0;
FILE * str = fopen(filename,rb);
if(str == NULL){printf(无法打开%s进行读取!\ n,filename); getchar();返回false; }
char linea [1024];
leelin(str,linea); if(linea [0]!='P'|| linea [1]!='6'){printf(%s PPM文件不是类型P6,所以不能read!\ n,filename); getchar();返回false; }
leelin(str,linea); if(linea [0] =='#')leelin(str,linea);
char * ptr = linea; xmax1 = strtol(ptr,& ptr,10); ymax1 = strtol(ptr + 1,& ptr,10); leelin(str,linea);
if(xmax1< 1 || xmax1> 90000 || ymax1< 1 || ymax1> 90000){printf(%s PPM文件xmax或ymax错误=%i%i,所以无法阅读! \\\
,filename,xmax1,ymax1); getchar();返回false; }
data = new uchar [xmax1 * ymax1 * 3];
for(int j = 0; j< ymax1; j ++)
fread(& data [3 * j * xmax1],1,3 * xmax1,str);
fclose(str);
返回true;
}



bool save_image_ppm(char * filename,uchar * data,int xmax1,int ymax1)
{
FILE * output = fopen(filename,wb);
if(output == NULL)
{
printf(无法打开%s进行写入!\ n,filename);
返回false;
}
fprintf(输出,P6 \ n%d%d \ n%d \ n,xmax1,ymax1,255);
for(int j = 0; j< ymax1; j ++)
fwrite(& data [3 * j * xmax1],1,3 * xmax1,output);
fclose(输出);
返回true;
}


void leelin(FILE * strin,char * linea)
{
//删除0x0D和0x0A
int i;
linea [0] ='\0';
char * ptr = linea;
for(i = 0;(i< 1024&&!feof(strin)); i ++)
{
* ptr ++ = fgetc(strin);
// fscanf(strin,%c,ptr ++); //旧!!
if(ptr [-1] == 10)
break;
}
if(i> = 1)
ptr [-1] ='\0';
else
linea [0] ='\0';
if(i> 2&& ptr [-2] == 0x0D)
ptr [-2] ='\0';
}

解决方案

你的 leelin()功能已经在阅读从文件到缓冲区的一行。所以在阅读之前不需要额外检查评论。只需忽略该行(您通过阅读下一行已在代码中执行此操作)。



要跳过注释行,您可能会使用类似
的内容

  
leelin(str,linea);
while (linea [ 0 ] == ' #');



但是,您也可以通过保存文件指针来提前读取阅读之前阅读和恢复之前(参见 ftell - C ++参考 [ ^ ], fseek - C ++参考 [ ^ ]或 fgetpos fsetpos )。



要仅提前阅读单个字符,您还可以使用 ungetc - C ++参考 [ ^ ]:

  int  readAhead = fgetc(str); 
// 从流中读取的下一个内容将包含readAhead作为第一个字符
ungetc( readAhead,str);
if (readAhead == ' #'
{
// 做点什么
}


I made following code to fast read and write ppm using smart code.
Unfortunately I have to use leelin() function to look if a text beginning with # is going to be read before reading xmax and ymax.
It is possible to look for "#" (following with text) at the file pointer before reading?

Here is the header of the PPM file:

P6
# CREATOR: GIMP PNM Filter Version 1.1
1280 720
255
(binary data)



What I have tried:

#include <iostream>
#pragma warning(disable:4996) //disable deprecateds
using namespace std;
typedef unsigned char uchar;

//Lee de ficheros:
void leelin(FILE *strin, char *linea);

bool read_image_ppm(char *filename, uchar  *&data, int &xmax1,int &ymax1);
bool save_image_ppm(char *filename, uchar  *data,int xmax,int ymax);

void main()
{
	uchar *data=NULL;
	int xmax,ymax;
	read_image_ppm("2944_1.ppm",data,xmax,ymax);
	save_image_ppm("out.ppm",data,xmax,ymax);
	delete data;
	cout<<"===END==="<<endl;getchar();
}


bool read_image_ppm(char *filename, uchar  *&data, int &xmax1,int &ymax1)
{
	xmax1=ymax1=0;
	FILE *str = fopen(filename, "rb");
	if (str == NULL) 	{ 		printf("Couldn't open %s for reading!\n", filename);getchar(); 		return false; 	}
	char linea[1024];
	leelin(str,linea);if(linea[0]!='P'||linea[1]!='6')  { 		printf("%s PPM file not type P6, so couldn't read! \n", filename);getchar();		return false; 	}
	leelin(str,linea);if(linea[0]=='#') leelin(str,linea);
	char *ptr=linea;xmax1=strtol(ptr,&ptr,10);ymax1=strtol(ptr+1,&ptr,10);leelin(str,linea);
	if (xmax1<1||xmax1>90000||ymax1<1||ymax1>90000) { 		printf("%s PPM file xmax or ymax is wrong= %i %i, so couldn't read! \n", filename,xmax1,ymax1);getchar();		return false; 	}
	data=new uchar[xmax1*ymax1*3];
	for (int j = 0; j < ymax1; j++) 
		fread(&data[3*j*xmax1], 1, 3*xmax1, str);
	fclose(str);
	return true;
}



bool save_image_ppm(char *filename, uchar  *data,int xmax1,int ymax1)
{
	FILE *output = fopen(filename, "wb");
	if (output == NULL)
	{
		printf("Couldn't open %s for writing!\n", filename);
		return false;
	}
	fprintf(output, "P6\n%d %d\n%d\n", xmax1, ymax1, 255);
	for (int j = 0; j < ymax1; j++) 
		fwrite(&data[3*j*xmax1], 1, 3*xmax1, output);
	fclose(output);
	return true;
}


void leelin(FILE *strin,char *linea)
{
	//removes 0x0D and 0x0A
	int i;
	linea[0]='\0';
	char *ptr=linea;
	for (i=0;(i<1024 && !feof(strin)); i++)
	{
		*ptr++ = fgetc(strin);
		//fscanf(strin, "%c", ptr++);  //OLD!!
		if (ptr[-1] == 10)
			break;
	}
	if (i>=1)
		ptr[-1]='\0';
	else
		linea[0]='\0';
	if (i>2 && ptr[-2]==0x0D)
		ptr[-2]='\0';
}

解决方案

Your leelin() function is already reading a line from the file into a buffer. So there should be no need for an additional check for comments before reading. Just ignore the line (which you are doing already in your code by reading the next line).

To skip comment lines, you might use something like

do
    leelin(str,linea);
while (linea[0] == '#');


However, you may also read ahead by saving the file pointer before reading and restoring it after reading (see ftell - C++ Reference[^], fseek - C++ Reference[^] or fgetpos, fsetpos).

To read only a single character ahead you might also use ungetc - C++ Reference[^]:

int readAhead = fgetc(str);
// Next read from stream will contain readAhead as first character
ungetc(readAhead, str);
if (readAhead == '#')
{
    // do something
}


这篇关于读写PPM文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆