Я работаю над программой, которая читает файл PPM (формат P6) и отображает его с помощью Opengl и c ++.
Изображение PPM может отображаться с моим кодом, но цвета изображения неправильные. Лицо человека должно быть коричневым, а фон — синим.
Я читаю файлы с помощью ifstream и помещаю данные в массив dataByte [] char. Затем я использую glDrawPixels () для отображения изображения. Он работает правильно с файлом PGM.
Вот мой код Мне нужно сделать некоторые операции с изображением. Операции работают нормально, но только когда я отображаю файл PPM, цвета изображения не такие, как в фотошопе.
Фон должен быть синим, но он становится красным и так далее … Я не могу сейчас загружать изображения, так что вот ссылка на скриншот с изображениями
изображение должно отображаться
но это отображать таким образом
Я думаю, что проблема связана с функциями, которые я читаю данные.
#include "stdafx.h"#include <stdlib.h>
#include <GL/glut.h>
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
using namespace std;
GLint width;
GLint height;
GLint wholeLength;
GLint grayLevel;
//GLubyte *dataByte;
char* dataByte;
GLint type;
//ignore the comment in PPM
void ignoreComment(ifstream &f){
char buf[1024];
char t;
t=f.peek();
while (t=='\n' || t=='\r'){
f.get();
t=f.peek();
}
if(t=='#'){
f.getline(buf,1023);
}
}
Это функция, которую я прочитал для изображения и поместил данные в dataByte []. Я думаю, что проблема в том, как я получаю данные из файла PPM. Но я не знаю, как это исправить
void readImage(string fname){ifstream f;
f.open(fname.c_str(), ifstream::in | ifstream::binary);
cout<<fname.c_str()<<endl;
if(!f.is_open() ){
cout<<"Cannot open the file"<<endl;
return;
}
else
cout<<"opened"<<endl;
//get type
ignoreComment(f);
string temp;
f >> temp;
if( (!(temp[0]=='P' ) && !(temp[0]=='p' ) )||
( !(temp[1]=='6' ) && !(temp[1]=='5' ))
){
cout<<temp<<endl;
cout<<"cannot read this format"<<endl;
f.close();
return;
}
else{
cout<<"file opened"<<endl;
cout<<temp<<endl;
}if(temp[1]=='5'){
type=5;
cout<<"type:"<<type<<endl;
}
if(temp[1]=='6'){
type=6;
cout<<"type:"<<type<<endl;
}//get width,height
ignoreComment(f);
f >> width;
ignoreComment(f);
f >> height;
ignoreComment(f);
f >> grayLevel;
if(width < 1 || height < 1 || grayLevel < 0 || grayLevel >255){
cout<<"Cannot get the size or gray level"<<endl;
f.close();
return;
}
//allocate data size
if( type==5){
wholeLength=width*height;
cout<<"width="<<width<<" height:"<<height<<endl;
}
if(type==6){
wholeLength=3*width*height;
cout<<"width="<<width<<" height:"<<height<<endl;
}if(type==5 || type ==6){
//dataByte=new GLubyte[wholeLength];
dataByte=new unsigned char[wholeLength];
//f.read((char*)&dataByte[0], wholeLength);
//GLubyte j;
int w;
if(type==5)
w=width;
if(type==6)
w=3*width;
int count=0;int counth=0;
for(int i=height;i>0;i--){
for(int k=0;k<w;k++){
//j=(GLubyte)f.get();
//dataByte[(i-1)*w+k]=j;
f.read((char*)&dataByte[(i-1)*w+k],sizeof(unsigned char));
count++;
}
cout<<"count:"<<count<<endl;
count=0;
counth++;
}
cout<<"counth:"<<counth<<endl;
}
f.close();
}
int main(int argc, char *argv[] ) {
//string n;
//cout<<"Please enter the name of the image"<<endl;
//cin>>n;
readImage("small.ppm");
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
ori();
getChoice();
glutMainLoop();return 0;
}
Вот мои функции отображения. Они могут отображать файл PGM и файл PPM.
void drawAsType(char * d){
if(type==5){
glDrawPixels(width,height,GL_LUMINANCE,GL_UNSIGNED_BYTE,d);
glFlush();
glutSwapBuffers();
}
if(type==6 ){
glDrawPixels(width,height,GL_RGB,GL_UNSIGNED_BYTE,d);
glFlush();
glutSwapBuffers();
}
}
void changeSize(int w,int h){
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(GLfloat)w,0.0,(GLfloat)h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}void display(void){
glClear(GL_COLOR_BUFFER_BIT);
glRasterPos2i(0,0);glColor3f(1.0f,1.0f,1.0f);
drawAsType(dataByte);
}
void ori(){
glutInitWindowSize(width,height);
glutCreateWindow("Origin");
glutReshapeFunc(changeSize);
glutDisplayFunc(&display);}
Может ли кто-нибудь помочь мне в этом?
Спасибо haraldK’s.
Я обнаружил, что причина в том, что в функции ignoreComent () я использую peek (), чтобы проверить, является ли следующий символ ‘\ n’ или ‘\ t’ или ‘#’.
void ignoreComment(ifstream &f){
char buf[1024];
char t;
while ( t=f.peek(),t=='\n'|| t=='\r'){
f.get();
}
if(t=='#'){
f.getline(buf,1023);
}
}
Функция peek () возвращает следующий символ во входной последовательности, не извлекая его: оставленный как следующий символ, который будет извлечен из потока.—Форма cplusplus.com
Таким образом, после последнего вызова peek () вызывается строка garyLevel.
ignoreComment(f);
Так как первый символ garyLevel равен ‘2’, потому что ‘2’ не следует игнорировать, поэтому программа выполняет следующую строку f >> grayLevel
Затем выполняется часть считанных данных изображения. Вно первым символом в потоке является ‘2’, который был от peek (). Итак, первый символ моего массива dataByte[]
будет 2 вместо реального первого символа блока изображения.
Решение состоит в том, чтобы заменить «2». Так что я должен использовать f.get()
еще раз, прежде чем я начну читать данные RGB.
Так что просто добавьте f.get()
перед двумя для петель
if(type==5 || type ==6){
dataByte=new char[wholeLength];f.get(); /*ADD THIS GUY!*/
int w;
if(type==5)
w=width;
if(type==6)
w=3*width;
int count=0;int counth=0;
char t;
for(int i=height;i>0;i--){
for(int k=0;k<w;k++){
//read image RGB data
}
}