加载不同的纹理 Opengl:减慢程序

Load different textures Opengl: slows the program

我正在 3d 中实现迷宫。它工作正常,但现在我必须在其中添加纹理。我喜欢加载不同的纹理,具体取决于它是墙壁、食物还是走廊。我找到了每次需要纹理时调用 LoadTexture 的方法。

我遇到了一个使用函数 Readjpeg 和 LoadTexture 的模板。但是结果太慢了。程序逻辑很好,但是动作很慢。假设因为我从文件中读取了很多次,然后 idle 没有像以前那样被调用。

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, 宽度,高度,0, GL_RGB, GL_UNSIGNED_BYTE, 缓冲区); 通过(因为缓冲区不再存在):
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 宽度,高度,0, GL_RGB, GL_UNSIGNED_BYTE, &texname);

也是一个词法错误: 图像->调整大小(cinfo.output.height * 步幅); 到 图像->调整大小(cinfo.output_height * 步幅);

我遇到了这个错误:

描述资源路径位置类型 “fopen”未在此范围内声明 ReadJPEG.cpp /RandomMaze3d 第 22 行 C/C++ 问题

描述资源路径位置类型 无法将参数“2”的“unsigned char*”转换为“JSAMPARRAY {aka unsigned char**}”到“JDIMENSION jpeg_read_scanlines(j_decompress_ptr,JSAMPARRAY, JDIMENSION)”ReadJPEG.cpp/RandomMaze3d第 50 行 C/C++ 问题

语义错误(可能与上述错误有关): 描述资源路径位置类型 无效参数 ' 候选人是: _IO_FILE * fopen(常量字符 *, 常量字符 *) ' ReadJPEG.cpp /RandomMaze3d 第 22 行语义错误

描述资源路径位置类型 无效参数 ' 候选人是: unsigned int jpeg_read_scanlines(jpeg_decompress_struct *, unsigned char * *, unsigned int) ' ReadJPEG.cpp /RandomMaze3d 第 50 行语义错误

我也可以使用 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% quality.I 也曾尝试保存 100% 和同样的错误。

更新执行错误2:

@datenwolf 看到我的更新错误。现在,如果我 运行 我以前的函数 loadTextures 和一个文件,它可以很好地使用 64 作为参数,就像开始时一样。但是,如果我调用 MyLoadTexture,window 就会消失,而不会出现任何错误消息。所以具有所有纹理的地图

静态 std::map loaded_textures;

不应该在MyLoadTexture之外定义为全局变量吗?我想当函数结束时,loaded_textures 消失(它从内存中释放出来)并假设它变成空白。

问题显然在 MyLoadTexture 中,好像我用 LoadTextures("fire.jpg", 64) 代替了一样;一切顺利。然后如果我再次使用 MyLoadTexture("fire.jpg"); window 消失了(试图画迷宫)。

如前所述,MyLoadTexture 和 ReadJPEG 是 public 全局函数,因为我需要从 Maze 以外的 类 调用它们,例如 Ghost、Pacman 类.

请提出其他建议。

LoadTexture 正在经历从磁盘(缓存)读取文件、解析文件、然后加载数据的整个过程。有趣的是,您实际上利用了可追溯到 OpenGL-1.0 的时代错误(已在 1992 年 IIRC 中发布;哎呀,我什至没有关于它的规范),您可以在其中将图像数据加载到纹理中 0 .这样做不是很明智。

相反,只加载所有纹理一次,每个纹理都加载到它自己的纹理对象中。您会看到那里的所有 glBindTexture 个电话。第二个参数是要使用的纹理的 "name"。因此,在加载图像时,您首先要创建 "names",每个要与 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 将图像加载到其中。顺便说一句,LoadTexture 的参数 dim 完全没有必要,实际上 危险 。 JPEG 文件已经包含了您需要的所有信息。

相反,您应该将其替换为如下内容:

先稍微改一下LoadTexture。将它从迷宫 class 中拉出来,它不属于那里。使它成为一个全局函数。让它生成一个 OpenGL 纹理名称,将纹理加载到其中并 return 纹理名称。同样,所有子采样都是疯狂的; 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 纹理,而不是生成新纹理。您可以将它用作直接替换,它的编写方式将 "just work" 与您的其余代码一起使用。

更新 2,ReadJPEG 的改进版本[​​=76=]
#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++ 习语;我强烈建议不要使用引用,因为引用是伪装的指针,可能会误导你。真实、显式的指针可以防止您陷入此类陷阱。

更新 3 由于问题更新:

Description Resource Path Location Type ‘fopen’ was not declared in this scope ReadJPEG.cpp /RandomMaze3d line 22 C/C++ Problem

在 ReadJPEG.cpp 的顶部添加一个 #include <stdio.h> – 我也使用 iostream 来发出错误消息,所以也在那里添加 #include <iostream>,在 LoadTexture.cpp 为了好的措施。

Description Resource Path Location Type cannot convert ‘unsigned char*’ to ‘JSAMPARRAY {aka unsigned char**}’ for argument ‘2’ to ‘JDIMENSION jpeg_read_scanlines(j_decompress_ptr, JSAMPARRAY, JDIMENSION)’ ReadJPEG.cpp /RandomMaze3d line 50 C/C++ Problem (…) Description Resource Path Location Type Invalid arguments ' Candidates are: unsigned int jpeg_read_scanlines(jpeg_decompress_struct *, unsigned char * *, unsigned int) ' ReadJPEG.cpp /RandomMaze3d line 50 Semantic Error

查看我编辑的 ReadJPEG 版本(天哪,谁使用双指针间接设计了 libjpeg API)。无论如何,没有什么是每条扫描线的循环和辅助指针变量无法修复的。

Semantic errors ( perhaps related with above errors): Description Resource Path Location Type Invalid arguments ' Candidates are: _IO_FILE * fopen(const char *, const char *) ' ReadJPEG.cpp /RandomMaze3d line 22 Semantic Error

另请参阅我编辑的 ReadJPEG 版本

Also i could save use int instead of unint_8

没有!!!

一个 sizeof(int) != sizeof(uint8_t)。虽然您可以用 uint8_t 代替 unsigned char,但是 char 的大小并不是一成不变的(通常是 8 位,但并非总是如此)。有点可耻的是,libjpeg API 使用 unsigned char 作为数据类型,而不是像 uint8_t 这样的真正固定大小的数据类型,它在所有情况下都是 8 位大小。

and String or char* instead of std:string ?? Isnt it ?

我不知道您指的是哪种 String 类型。但是 从不 在 C++ 代码中使用 C 风格的 char* "strings",除非您与纯 C API 交互。哎呀,我在很大程度上更喜欢 C 而不是 C++,即使在那里我也尽可能远离 char* 并使用一些字符串抽象,如 uStr 或类似的。裸露的 char* 琴弦非常危险。

C++ 有一个标准(作为语言标准库的一部分)字符串类型。它叫做 std::string,如果你正在编写 C++ 代码,你就可以使用它。这个没有争议。

同时保持 C++ 标准库类型将为您省去显式分配和删除内存的所有麻烦。所有这些血淋淋的细节都很好地隐藏在 STL 的分配器中,如果您虔诚地坚持 RAII(= 从不明确使用 newdelete 运算符),您将永远不会遇到内存泄漏;当然你不能总是坚持RAII。