Загрузка изображения с помощью FreeImage

Я пытаюсь следовать учебнику OpenGL, но в учебнике используется SOIL (что не работает для меня), а я использую FreeImage.

Не могли бы вы сказать мне, почему мой код не работает?

Учебный код:

// Load texture
GLuint tex;
glGenTextures(1, &tex);

int width, height;
unsigned char* image = SOIL_load_image("sample.png", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

Мой код:

// Load textures
GLuint tex;
glGenTextures(1, &tex);

int width, height;

FREE_IMAGE_FORMAT formato = FreeImage_GetFileType("sample.png",0);
FIBITMAP* imagen = FreeImage_Load(formato, "sample.png");
FIBITMAP* temp = imagen;  
imagen = FreeImage_ConvertTo32Bits(imagen);
FreeImage_Unload(temp);

width = FreeImage_GetWidth(imagen);
height = FreeImage_GetHeight(imagen);

GLubyte* textura = new GLubyte[4*width*height];
char* pixeles = (char*)FreeImage_GetBits(imagen);

for(int j= 0; j<width*height; j++)
{
    textura[j*4+0]= pixeles[j*4+2];
    textura[j*4+1]= pixeles[j*4+1];
    textura[j*4+2]= pixeles[j*4+0];
    textura[j*4+3]= pixeles[j*4+3];
}

glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, width, height, 0, GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid*)textura );

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

Мое «решение» просто приводит к черному окну (без ошибок).


person UndeadLeech    schedule 26.10.2013    source источник


Ответы (3)


Программировать на C очень весело

Вы программист. Вам лучше отладить свою программу, потому что "черный экран" в приложении OpenGL может быть вызван миллионом разных причин. С нашей точки зрения мы можем только догадываться. И нам это не нравится.

Мое предположение

(хорошо, иногда нам нравится гадать)

Этот:

FIBITMAP* temp = imagen;  
imagen = FreeImage_ConvertTo32Bits(imagen);
FreeImage_Unload(temp);

Ваши temp и imagen указывают на одно и то же место, поэтому после FreeImage_Unload(temp); оба указывают на... мы не знаем куда. Затем вы получаете от него пиксели:

char* pixeles = (char*)FreeImage_GetBits(imagen);

Что он возвращает? Мы не знаем. После этого вы не проверяете, существует ли pixels. Неопределенное поведение и т. д. Он даже не падает. Кроме того, AFAIR, вы не можете одновременно читать и писать dib.

Вместо этого выполните:

FREE_IMAGE_FORMAT formato = FreeImage_GetFileType("sample.png",0);
if(formato  == FIF_UNKNOWN) { /* go angry here */ } 
FIBITMAP* imagen = FreeImage_Load(formato, "sample.png");
if(!imagen ) { /* go very angry here */ } 
FIBITMAP* temp = FreeImage_ConvertTo32Bits(imagen);
if(!imagen) { /* go mad here */ } 
FreeImage_Unload(imagen);
imagen = temp;

(или просто закомментируйте все конверсии)

Как отлаживать:

  • Проверка на наличие ошибок после загрузки и обработки изображения. Картинка загружается вообще?
  • Проверьте наличие ошибок OpenGL. Там все идет?
  • В пиксельных шейдерах установите белый цвет вывода, чтобы быть уверенным, что ваша геометрия в порядке (что? вы не используете шейдеры? =()
  • После загрузки текстуры запишите ее прямо в файл .raw (или в другом формате) и проверьте ее с помощью редактора растровых изображений.

Как проверить наличие ошибок:

Внимательно прочитайте документацию FreeImage и учебные примеры. Посмотрите на реализацию проверки ошибок. По сути, вам нужно будет установить функцию обратного вызова. Реализуйте это. Установить его. (или хотя бы копипаст). Сделайте то же самое + glGetError() для OpenGL.

Удачного кодирования! знак равно

Редактировать: FreeImage имеет вспомогательную функцию SwapRedBlue32(), поэтому цикл for вам не нужен.

person Ivan Aksamentov - Drop    schedule 26.10.2013
comment
Ваш код выглядит нормально, только imagen = temp; приводит к сбою приложения, но работает без этой строки. Не могу заставить SwapRedBlue32() работать, но мой цикл работает, так что все в порядке. Ты знаешь хороший способ перевернуть картинку? - person UndeadLeech; 27.10.2013
comment
Вы можете использовать FreeImage_Rotate(). Загрузите документацию по адресу здесь для получения подробной информации. Также проверьте функцию FreeImage_SetOutputMessage. Так что в следующий раз нам не нужно будет гадать, где ваш код не сработал =) - person Ivan Aksamentov - Drop; 27.10.2013
comment
Можно ли использовать imagen = FreeImage_FlipHorizontal(imagen) в этой ситуации? Потому что я не могу заставить его работать, потому что он возвращает логическое значение. При вращении он работает, но тогда он переворачивается по вертикали :/. - person UndeadLeech; 27.10.2013
comment
используйте bool result = FreeImage_FlipHorizontal(imagen);, это изменит imagen на месте, нет необходимости копировать в другую переменную. Не забудьте проверить наличие ошибок после: if(!result) { /* Error message here*/ }. - person Ivan Aksamentov - Drop; 27.10.2013

Кажется, вы никогда не связываете объект текстуры, который создаете.

Добавьте вызов glBindTexture( GL_TEXTURE_2D, tex ) после glGenTextures() и еще раз перед попыткой рендеринга с текстурой.

person genpfault    schedule 26.10.2013

Хорошо, я нашел ответ на свой вопрос. :П

Мне нужно запустить приложение в папке «Отладка», а не отлаживать его с помощью VC++.

Единственная проблема в том, что теперь загруженное изображение перевернуто, но я думаю, что смогу это исправить, когда изменю цикл for.

Спасибо за все ответы!

person UndeadLeech    schedule 27.10.2013
comment
Итак, ваша программа просто не может найти указанный файл изображения. Чтобы настроить рабочий каталог при запуске программы под отладчиком Visual Studio: Right Click on Project -> Properties -> Debugging -> Working Directory. - person Ivan Aksamentov - Drop; 27.10.2013