[英]Load different textures Opengl: slows the program
我在 3d 中實現了一個迷宮。 它工作正常,但現在我必須將紋理放入其中。 我想加載不同的紋理,具體取決於它是牆壁、食物還是走廊。 我找到了每次需要紋理時調用 LoadTexture 的方法。
我遇到了一個使用函數 Readjpeg 和 LoadTexture 的模板。 但是結果太慢了。 程序邏輯很好,但是動作很慢。 假設因為我多次從文件中讀取,然后空閑時間不像以前那樣被調用。
v
oid Maze::draw3D(int w, int h){
if (rows == 0 || columns == 0)
throw std::out_of_range("Error: El numero columnas o filas no puede ser cero. Error división por cero");
if (rows > h || columns > w)
throw std::out_of_range("Error: La ventana tiene que tener un tamaño mayor a las fila por columnas");
int numberRow, numberColumn;
int widthRatio =int(w / columns);
int heightRatio = int(h / rows);
//int numberRow;
GLUquadric *sphere=gluNewQuadric();
for(numberRow=0;numberRow < rows; numberRow++)
for(numberColumn=0; numberColumn< columns;numberColumn++)
if(!isCenter(numberRow,numberColumn)){
if( map[numberRow][numberColumn]==WALL ) {
//Selecciona el color actual con el que dibujar. Parámetros R G y B, rango [0..1], así que estamos ante el color azul
//glColor3f(0.0, 0.0, 1.0);
/*glBegin() comienza una secuencia de vértices con los que se construirán primitivas. El tipo de primitivas viene dado por el parámetro de glBegin(), en este caso GL_QUADS.
* Al haber cuatro vértices dentro de la estructura, está definiendo un cuadrado. glEnd() simplemente cierra la estructura.
*
*/
//las x son iguales cambian las y
//ysim =(rows-numberRow);
//numberRow=numberRow;
//Pared suelo
glColor3f(1.0, 0.0, 0.0); // Red = rgb <1, 0, 0>
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),0,(numberRow*heightRatio)-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),0,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),0,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),0,(numberRow)*heightRatio-(HEIGHT/2));
glEnd();
/*
//Pared techo
glColor3f(1.0, 0.0, 0.0); // Red = rgb <1, 0, 0>
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow*heightRatio)-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),DEPTH,(numberRow)*heightRatio-(HEIGHT/2));
//glVertex3i(50,-50,50);
glEnd();
*/
//Pared exterior (las x mas izquierda) (1)
glColor3f(0.0, 1.0, 0.0); //Green = rgb <0, 1, 0>
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),0,(numberRow*heightRatio)-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),0,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i( ((numberColumn)*widthRatio)-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow*heightRatio)-(HEIGHT/2));
glEnd();
//Pared exterior ( las y mas abajo) (2)
glColor3f(0.0, 0.0, 1.0);//Blue = rgb <0, 0, 1>
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i(((numberColumn)*widthRatio)-(WIDTH/2),0, (numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),0, (numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),DEPTH, (numberRow+1)*heightRatio-(HEIGHT/2));
glEnd();
//Pared exterior ( las x mas abajo) (3)106;90;205
glColor3f(1.0, 0.5, 0.0); //Orange = color red 1 green 0.5 blue 0.0
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),DEPTH, (numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),0, (numberRow+1)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),0, (numberRow)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),DEPTH, (numberRow)*heightRatio-(HEIGHT/2));
glEnd();
//Pared exterior ( las y mas arriba) (4)
glColor3f(0.752, 0.752, 0.752); //Grey = color red 0.752941 green 0.752941 blue 0.752941
glBegin(GL_QUADS);
//Vertice arriba izquierda
glVertex3i((numberColumn*widthRatio)-(WIDTH/2),0, (numberRow)*heightRatio-(HEIGHT/2));
//Vertice abajo izquierda
glVertex3i(((numberColumn)*widthRatio)-(WIDTH/2),DEPTH, (numberRow)*heightRatio-(HEIGHT/2));
//Vertice abajo derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),DEPTH, (numberRow)*heightRatio-(HEIGHT/2));
//Vertice arriba derecha
glVertex3i(((numberColumn+1)*widthRatio)-(WIDTH/2),0, (numberRow)*heightRatio-(HEIGHT/2));
glEnd();
//Textura pared techo
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
LoadTexture("Groundplant64x64.jpg",64);
glBegin(GL_QUADS);
glTexCoord2f(-4.0,0.0); glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow*heightRatio)-(HEIGHT/2));
glTexCoord2f(4.0,0.0); glVertex3i((numberColumn*widthRatio)-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
glTexCoord2f(4.0,4.0); glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),DEPTH,(numberRow+1)*heightRatio-(HEIGHT/2));
glTexCoord2f(-4.0,4.0); glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),DEPTH,(numberRow)*heightRatio-(HEIGHT/2));
glEnd();
glDisable(GL_TEXTURE_2D);
}
else if(map[numberRow][numberColumn] == FOOD){
//Selecciona el color actual con el que dibujar. Parámetros R G y B, rango [0..1], así que estamos ante el color blanco
glColor3f(1.0,1.0,0.0); //Orange
/*glBegin() comienza una secuencia de vértices con los que se construirán primitivas. El tipo de primitivas viene dado por el parámetro de glBegin(), en este caso GL_QUADS.
* Al haber cuatro vértices dentro de la estructura, está definiendo un cuadrado. glEnd() simplemente cierra la estructura.
*
*/
//GLUquadric *sphere=gluNewQuadric();
gluQuadricDrawStyle( sphere, GLU_FILL);
gluQuadricNormals( sphere, GLU_SMOOTH);
gluQuadricOrientation( sphere, GLU_OUTSIDE);
gluQuadricTexture( sphere, GL_TRUE);
glPushMatrix();
glTranslated(((numberColumn+0.5)*widthRatio)-(WIDTH/2),DEPTH/3,(numberRow+0.5)*heightRatio-(HEIGHT/2) );
//glRotated(45,1,1,1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
LoadTexture("Flames64x64.jpg",64);
gluSphere(sphere,5.0,50,50);//(numberColumn+1)*widthRatio)-(WIDTH/2),0, (ysim)*heightRatio-(HEIGHT/2)
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
else if(map[numberRow][numberColumn] == PASSAGE){
//Selecciona el color actual con el que dibujar. Parámetros R G y B, rango [0..1], así que estamos ante el color blanco
glColor3f(1.0,0.5,0.0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
LoadTexture("FloorsMedieval64x64.jpg",64);
glBegin(GL_QUADS);
glTexCoord2f(-4.0,0.0); glVertex3i((numberColumn*widthRatio)-(WIDTH/2),2,(numberRow*heightRatio)-(HEIGHT/2));
glTexCoord2f(4.0,0.0); glVertex3i((numberColumn*widthRatio)-(WIDTH/2),2,(numberRow+1)*heightRatio-(HEIGHT/2));
glTexCoord2f(4.0,4.0); glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),2,(numberRow+1)*heightRatio-(HEIGHT/2));
glTexCoord2f(-4.0,4.0); glVertex3i((numberColumn+1)*widthRatio-(WIDTH/2),2,(numberRow)*heightRatio-(HEIGHT/2));
glEnd();
glDisable(GL_TEXTURE_2D);
}
}
}
我們的老師傳給我們以下代碼來使用:
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
void Maze::ReadJPEG(char *filename,unsigned char **image,int *width, int *height)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * infile;
unsigned char **buffer;
int i,j;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
if ((infile = fopen(filename, "rb")) == NULL) {
printf("Unable to open file %s\n",filename);
exit(1);
}
jpeg_stdio_src(&cinfo, infile);
jpeg_read_header(&cinfo, TRUE);
jpeg_calc_output_dimensions(&cinfo);
jpeg_start_decompress(&cinfo);
*width = cinfo.output_width;
*height = cinfo.output_height;
*image=(unsigned char*)malloc(cinfo.output_width*cinfo.output_height*cinfo.output_components);
buffer=(unsigned char **)malloc(1*sizeof(unsigned char **));
buffer[0]=(unsigned char *)malloc(cinfo.output_width*cinfo.output_components);
i=0;
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, buffer, 1);
for(j=0;j<cinfo.output_width*cinfo.output_components;j++)
{
(*image)[i]=buffer[0][j];
i++;
}
}
free(buffer);
jpeg_finish_decompress(&cinfo);
}
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
void Maze::LoadTexture(char *filename,int dim)
{
unsigned char *buffer;
unsigned char *buffer2;
int width,height;
long i,j;
long k,h;
ReadJPEG(filename,&buffer,&width,&height);
buffer2=(unsigned char*)malloc(dim*dim*3);
//-- The texture pattern is subsampled so that its dimensions become dim x dim --
for(i=0;i<dim;i++)
for(j=0;j<dim;j++)
{
k=i*height/dim;
h=j*width/dim;
buffer2[3*(i*dim+j)]=buffer[3*(k*width +h)];
buffer2[3*(i*dim+j)+1]=buffer[3*(k*width +h)+1];
buffer2[3*(i*dim+j)+2]=buffer[3*(k*width +h)+2];
}
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,dim,dim,0,GL_RGB,GL_UNSIGNED_BYTE,buffer2);
free(buffer);
free(buffer2);
}
如果有另一種方法可以在內存中使用不同的紋理(jpeg 中的 64x64 像素圖像)或任何提高速度的想法。 動畫非常非常緩慢。
謝謝
按照@datenwolf 的建議進行更新
我的 readJPEG.cpp
#include "ReadJPEG.h"
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
int ReadJPEG(
std::string const filename,
std::vector<uint8_t> *image,
int *width, int *height )
{
if( !image ) {
return -1;
}
FILE * const infile = fopen(filename, "rb");
if( !infile ) {
std::cerr
<< "error opening file "
<< filename
<< " : "
<< strerror(errno)
<< std::endl;
return -2;
}
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
jpeg_read_header(&cinfo, TRUE);
jpeg_calc_output_dimensions(&cinfo);
jpeg_start_decompress(&cinfo);
if( width ) { *width = cinfo.output_width; }
if( height ) { *height = cinfo.output_height; }
size_t const stride = cinfo.output_width * cinfo.output_components;
// image->resize(cinfo.output.height * stride);
image->resize(cinfo.output_height * stride);
jpeg_read_scanlines(&cinfo, &(*image)[0], cinfo.output_height);
jpeg_finish_decompress(&cinfo);
//jpeg_read_scanlines(&cinfo, &(*image)[0], cinfo.output_height);
return 0;
}
MyLoadTexture.cpp
#include "MyLoadTexture.h"
//using namespace std;
GLuint MyLoadTexture(std::string const filename)
{
GLuint texname = 0;
/* this is actually tied to the OpenGL context, so this should
* actually be a map GLcontext -> std::string -> texturename */
static std::map<std::string, GLuint> loaded_textures;
if( loaded_textures.find(filename) != loaded_textures.end() ) {
texname = loaded_textures[filename];
glBindTexture(GL_TEXTURE_2D, texname);
return texname;
}
int width,height;
std::vector<uint8_t> image;
if( ReadJPEG(filename, &image, &width, &height) ) {
std::cerr
<< "error reading JPEG"
<< std::endl;
return 0;
}
glGenTextures(1, &texname);
if( !texname ) {
std::cerr
<< "error generating OpenGL texture name"
<< std::endl;
return 0;
}
glBindTexture(GL_TEXTURE_2D, texname);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
/* glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGB,
width, height, 0,
GL_RGB,
GL_UNSIGNED_BYTE, buffer );
*/
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGB,
width, height, 0,
GL_RGB,
GL_UNSIGNED_BYTE, &texname);
loaded_textures[filename] = texname;
return texname;
}
注意我改變了@datewnwolf glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer ); by(因為緩沖區不再存在):
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 寬度, 高度, 0, GL_RGB, GL_UNSIGNED_BYTE, &texname);
還有一個詞法錯誤: image->resize(cinfo.output.height * stride); 到圖像->調整大小(cinfo.output_height * stride);
我面臨這個錯誤:
說明 資源路徑位置類型“fopen”未在此范圍內聲明 ReadJPEG.cpp /RandomMaze3d line 22 C/C++ 問題
說明 資源路徑位置類型無法將參數 '2' 的 'unsigned char*' 轉換為 'JSAMPARRAY {aka unsigned char**}' 到 'JDIMENSION jpeg_read_scanlines(j_decompress_ptr, JSAMPARRAY, JDIMENSION)' ReadJPEG.cpp /RandomMaze3d line 50 C/C++問題
語義錯誤(可能與上述錯誤有關):描述資源路徑位置類型無效參數'候選對象是:_IO_FILE * fopen(const char *, const char *) ' ReadJPEG.cpp /RandomMaze3d line 22 Semantic Error
描述資源路徑位置類型無效參數'候選是:unsigned int jpeg_read_scanlines(jpeg_decompress_struct *, unsigned char * *, unsigned int) ' ReadJPEG.cpp /RandomMaze3d line 50 Semantic Error
我也可以保存 use int 而不是 unint_8 和 String 或 char* 而不是 std:string ?? 不是嗎?
更新執行錯誤:
@datenwolf 非常感謝。 我今天早上一直在工作,我可以毫無錯誤地執行。 但是現在我面臨一個奇怪的執行錯誤,我在一個地方更改為以 MyLoadTexture 和新的 ReadJPEG 開始 LoadTextures:
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
MyLoadTexture("Groundplant64x64.jpg");
glBegin(GL_QUADS); ....
給我一個:當我啟動 Groundplant64x64,jpg 時,應用程序傳輸的掃描線太少....文件沒有損壞,因為我可以打開它...我在谷歌搜索但沒有得到答案。
Groundplants 是 96x64 像素(因為我在保存它時犯了一個錯誤)但我也嘗試過使用 fire.jpg,它是 64x64。 jpg 以 85% 的質量保存。我也嘗試保存 100% 和相同的錯誤。
更新執行錯誤2:
@datenwolf 看到我的更新錯誤。 現在,如果我用一個文件運行我以前的函數 loadTextures,它可以很好地使用 64 作為參數,就像開始時一樣。 但是,如果我調用 MyLoadTexture,則窗口會消失而沒有任何錯誤消息。 所以帶有所有紋理的地圖
靜態 std::map 加載紋理;
它不應該在 MyLoadTexture 之外並定義為全局變量。 我想當函數結束時,loaded_textures 消失(它從內存中釋放出來)並假設它變成空白。
問題很明顯在 MyLoadTexture 中,就像我用 LoadTextures("fire.jpg", 64); 一切順利。 然后如果我再次使用 MyLoadTexture("fire.jpg"); 窗口消失(試圖繪制迷宮)。
如前所述 MyLoadTexture 和 ReadJPEG 是公共全局函數,因為我需要從迷宮以外的其他類調用它們,例如 Ghost、Pacman 類。
任何其他建議請。
LoadTexture
正在經歷從磁盤(緩存)讀取文件解析它,然后加載數據的整個麻煩。 有趣的是,您基本上利用了可追溯到 OpenGL-1.0(已在 IIRC 1992 中發布;天哪,我什至沒有相關規范)的時代錯誤,您可以在其中將圖像數據加載到紋理0
。 這樣做不是很聰明。
相反,只需將所有紋理加載一次,每個紋理都加載到它自己的紋理對象中。 您會看到那里所有的glBindTexture
調用。 第二個參數是要使用的紋理的“名稱”。 因此,在加載圖像時,您首先要創建“名稱”,為要與glGenTextures
一起使用的每個圖像創建一個名稱,然后綁定每個名稱,加載圖像,然后轉到下一個圖像。
當繪制所有你需要做的就是glBindTexture
你想要使用的紋理,不需要在那里加載任何東西,因為它已經加載了。
所以在你的代碼中你有很多這種模式的出現:
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
LoadTexture( a_filename );
/* --- draw something --- */
glDisable(GL_TEXTURE_2D);
發生的情況是您綁定 OpenGL 紋理 0(允許與 OpenGL-1.0 保持兼容)並使用 LoadTexture 將圖像加載到其中。 順便說一句,將參數dim
至 LoadTexture 是完全沒有必要的,而且實際上是危險的。 JPEG 文件已經包含您需要的所有信息。
相反,你應該用這樣的東西替換它:
首先稍微改變LoadTexture
。 把它從迷宮課上撕下來,它不屬於那里。 使它成為一個全局函數。 讓它生成一個 OpenGL 紋理名稱,將紋理加載到其中並返回紋理名稱。 此外,所有的二次抽樣都是瘋狂的; OpenGL 可以處理任意紋理尺寸,只需使用它。 最后但並非最不重要的一點是使用貼圖將文件名映射到紋理名稱,這樣已經加載的圖像文件不會重復加載。
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
#include <map>
#include <string>
GLuint LoadTexture(std::string const filename)
{
GLuint texname = 0;
/* this is actually tied to the OpenGL context, so this should
* actually be a map GLcontext -> std::string -> texturename */
static std::map<std::string, GLuint> loaded_textures;
if( loaded_textures.find(filename) != loaded_textures.end() ) {
texname = loaded_textures[filename];
glBindTexture(GL_TEXTURE_2D, texname);
return texname;
}
int width,height;
std::vector<uint8_t> image;
if( ReadJPEG(filename, &image, &width, &height) ) {
std::cerr
<< "error reading JPEG"
<< std::endl;
return 0;
}
glGenTextures(1, &texname);
if( !texname ) {
std::cerr
<< "error generating OpenGL texture name"
<< std::endl;
return 0;
}
glBindTexture(GL_TEXTURE_2D, texname);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGB,
width, height, 0,
GL_RGB,
GL_UNSIGNED_BYTE, &image[0] );
loaded_textures[filename] = texname;
return texname;
}
應用這些更改后, LoadTexture
將只加載一次圖像,並且在以后的調用中使用文件名映射到已加載的 OpenGL 紋理,而不是生成新的紋理。 您可以將它用作替代品,並且它的編寫方式將“適用於”其余代碼。
#include <string>
#include <vector>
#include <stdint.h>
#include <string.h>
#include <errno.h>
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
int ReadJPEG(
std::string const filename,
std::vector<uint8_t> *image,
int *width, int *height )
{
if( !image ) {
return -1;
}
FILE * const infile = fopen(filename.c_str(), "rb");
if( !infile ) {
std::cerr
<< "error opening file "
<< filename
<< " : "
<< strerror(errno)
<< std::endl;
return -2;
}
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
jpeg_read_header(&cinfo, TRUE);
jpeg_calc_output_dimensions(&cinfo);
jpeg_start_decompress(&cinfo);
if( width ) { *width = cinfo.output_width; }
if( height ) { *height = cinfo.output_height; }
size_t const stride = cinfo.output_width * cinfo.output_components;
image->resize(cinfo.output.height * stride);
for(size_t i = 0; i < cinfo.output_height;) {
uint8_t * const row = &(*image)[stride * i];
i += jpeg_read_scanlines(&cinfo, (unsigned char**)&row, 1);
}
jpeg_finish_decompress(&cinfo);
fclose(infile);
return 0;
}
請注意,這個新版本在合理的情況下使用了 RAII 和適當的 C++ 習語; 我強烈建議不要使用引用,因為引用是偽裝的指針,可能會絆倒你。 真實的、顯式的指針可防止您陷入此類陷阱。
說明 資源路徑位置類型“fopen”未在此范圍內聲明 ReadJPEG.cpp /RandomMaze3d line 22 C/C++ 問題
在 ReadJPEG.cpp 的頂部添加一個#include <stdio.h>
- 我也使用iostream
來發出錯誤消息,所以也在那里添加#include <iostream>
,並在 LoadTexture.cpp 中添加一個很好的衡量標准。
說明 資源路徑位置類型無法將參數 '2' 的 'unsigned char*' 轉換為 'JSAMPARRAY {aka unsigned char**}' 到 'JDIMENSION jpeg_read_scanlines(j_decompress_ptr, JSAMPARRAY, JDIMENSION)' ReadJPEG.cpp /RandomMaze3d line 50 C/C++問題 (...) 描述 資源路徑位置類型無效參數 ' 候選是: unsigned int jpeg_read_scanlines(jpeg_decompress_struct *, unsigned char * *, unsigned int) ' ReadJPEG.cpp /RandomMaze3d line 50 Semantic Error
請參閱我編輯的 ReadJPEG 版本(geesh,他使用雙指針間接尋址設計了 libjpeg API)。 無論如何,每個掃描線的循環和輔助指針變量都無法修復。
語義錯誤(可能與上述錯誤有關):描述資源路徑位置類型無效參數'候選對象是:_IO_FILE * fopen(const char *, const char *) ' ReadJPEG.cpp /RandomMaze3d line 22 Semantic Error
另請參閱我編輯過的 ReadJPEG 版本
我也可以節省使用 int 而不是 unint_8
不!!!
對於一個sizeof(int) != sizeof(uint8_t)
。 你可以代替uint8_t
為unsigned char
,雖然,但一個大小char
不是刻在石頭上(它通常是8位,但不總是)。 libjpeg API 使用unsigned char
作為數據類型而不是像uint8_t
這樣的真正固定大小的數據類型,它在任何情況下都是 8 位大小,這有點可恥。
和 String 或 char* 而不是 std:string ?? 不是嗎?
我不知道您指的是哪種特定的String
類型。 但永遠不要在 C++ 代碼中使用 C 風格的char*
“字符串”,除非您與純 C API 交互。 哎呀,我在很大程度上更喜歡 C 而不是 C++,即使在那里我也盡可能遠離char*
並使用一些字符串抽象,如 uStr 或類似的。 裸char*
字符串是完全危險的。
C++ 有一個標准的(作為語言標准庫的一部分)字符串類型。 它被稱為std::string
,如果您正在編寫 C++ 代碼,則可以使用它。 這是沒有爭議的。
同時保持 C++ 標准庫類型將為您節省顯式分配和刪除內存的所有麻煩。 所有這些血腥的細節都很好地隱藏在 STL 的分配器中,如果您虔誠地堅持 RAII(= 從不明確使用new
或delete
操作),您將永遠不會遇到內存泄漏; 當然,您不能總是堅持使用 RAII。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.