简体   繁体   中英

Load different textures Opengl: slows the program

Im implementing a Maze in 3d. It works fine, but now i have to put textures in it. Id like to load different textures depending if its a wall or food or corridor. I found the way calling LoadTexture every time i need a texture.

Ive met a template using the functions Readjpeg and LoadTexture. But the result is too slow. The program logic is good, but movements are very slow. Suppose because i read from file many times and the idle then is not called as times as before.

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);

                }

        }


}

Our teacher pass us the following code to use:

/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
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);
}

If theres another way that i could have different textures ( are 64x64 pixels images in jpeg) in memory or any ideas to improve the speed. The animation is very very slow.

Thanks

Update as suggested by @datenwolf

my 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;
}

Note ive changed @datewnwolf glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer ); by ( as buffer doesnt exist anymore):
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, &texname);

also an lexical error: image->resize(cinfo.output.height * stride); to image->resize(cinfo.output_height * stride);

Im facing this errors:

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

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

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

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

Also i could save use int instead of unint_8 and String or char* instead of std:string ?? Isnt it ?

Update execution error:

@datenwolf thanks a lot. ive been working this morning and i can execute without errors. But now im facing a weird execution error, ive changed in one place to begin the LoadTextures with MyLoadTexture and new ReadJPEG as:

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
MyLoadTexture("Groundplant64x64.jpg");
glBegin(GL_QUADS); .... 

Gives me an: Application transferred too few scanlines when i launch Groundplant64x64,jpg....the file is not corrupted as i can open it...Im googleing but dont get answer.

Groundplants is 96x64 pixels ( as i made a mistake saving it) but ive tried also with fire.jpg which is 64x64. jpg is saved at 85% of quality.I also have tried to save a 100% and same error.

Update execution error 2:

@datenwolf see my update error. Now if i run my previous function loadTextures with a file it works well with 64 as parameter as at the beginning. But if i call MyLoadTexture just the window disappear without any error message. So the map with all the textures

static std::map loaded_textures;

Shouldnt it be outside MyLoadTexture and defined as global variable. I suppose that when the function ends, loaded_textures dissapear ( it gets free from memory) and suppose it gets blank.

The problem is clearly in MyLoadTexture as if i substitute by LoadTextures("fire.jpg", 64); all goes well. Then if i use again MyLoadTexture("fire.jpg"); the window disappears ( in the attempt of drawing the maze).

As told before MyLoadTexture and ReadJPEG are public global functions as i need to call them from other classes than Maze as for example Ghost, Pacman classes.

Any other suggestion please.

LoadTexture is going through the whole hassle of reading the file from disk (cache) parsing it, then load the data. And funny enough, you essentially exploit an anachronism that dates back to OpenGL-1.0 (that's been released in IIRC 1992; geesh I don't even have the spec for that around) where you could load image data into texture 0 . That's not very smart to do.

Instead just load all the textures once, each into it's own texture object. You see all those glBindTexture calls you have there. The second parameter is an "name" for which texture to use. So when loading the images you'd first create "names", one for each image you want to use with glGenTextures , then bind each name, load the image and then go to the next image.

When drawing all you have to do then is just glBindTexture the texture you want to use, no need to load anything there, because it's already loaded.

Update due to request in comment

So in your code you have a lot of occurrences of this pattern:

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
LoadTexture( a_filename );
/* --- draw something --- */
glDisable(GL_TEXTURE_2D);

What happens there is that you bind OpenGL texture 0 (which is allowed to stay compatible with OpenGL-1.0) and load a image into it using LoadTexture. BTW, that parameter dim to LoadTexture is totally unnecessary and in fact dangerous . JPEG files already have all the information you need.

Instead you should replace it with something like this:

First change LoadTexture a little bit. Rip it out of the Maze class, it does not belong there. Make it a global function. Let it generate a OpenGL texture name, load the texture into it and return the texture name. Also all that subsampling is crazy; OpenGL can work with arbitrary texture dimenstions, just use that. Last but not least use a map to map filenames to texture names, so that image files that are already loaded are not redundantly reloaded.

/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
#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;
}

With these changes applied LoadTexture will load an image only once, and on later calls use the filename to map to the already loaded OpenGL texture instead of generating a new one. You can use it as a drop-in replacement and the way it's written it will "just work" with the rest of your code.

Update 2, improved version for ReadJPEG

#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;
}

Note that this new version uses RAII and proper C++ idioms where sensible; I strongly advice against using references, since references are pointers in disguise and can trip you up. Real, explicit pointer prevent you from tripping into such pitfalls.

Update 3 due to question update:

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

Add a #include <stdio.h> to the top of ReadJPEG.cpp – also I used iostream for emitting error messages so also add #include <iostream> there, and in LoadTexture.cpp for good measure.

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

See my edited version of ReadJPEG (geesh, who designed the libjpeg API using a double pointer indirection). Anyway, nothing a loop over each scanline and a helper pointer variable can't fix.

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

Also see my edited version of ReadJPEG

Also i could save use int instead of unint_8

No!!!

For one sizeof(int) != sizeof(uint8_t) . You could substitute uint8_t for unsigned char though, but the size of a char is not carved in stone (it's usually 8 bits, but not always). It's kind of shamefull that the libjpeg API uses unsigned char as a datatype instead of a truely fixed size datatype like uint8_t which always under all circumstances is 8 bits in size.

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

I don't know which particular String type you're referring to. But never use C-style char* "strings" in C++ code, except for when you're interfacing with pure C APIs. Heck, I largely perfer C over C++ and even there I stay away from char* as far as I can and use some string abstraction like uStr or similar. Naked char* strings are outright dangerous.

C++ has a standard (as part of the language standard library) string type. It's called std::string and if you're writing C++ code you use it. This is not debateable.

Also keeping to C++ standard library types will save you all the hassle with explicitly allocating and deleting memory. All those gory details are nicely tucked away down in the allocators of the STL and if you religiously stick to RAII (= never explicitly use new or delete operatos) you'll never experience memory leaks; of course you can't always stick to RAII.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM