2016-07-25 59 views
0

目前我正在完善我的基本级别编辑器程序中的一个功能,该程序允许我保存创建的地图。它会吐出生成的地图的.bmp图像。它通过一个我刚刚发现的名为CImg的图书馆来完成,我几乎不知道这一点。一切似乎都奏效,但生成的.bmp图像没有着色,而是出现在不同的黑白色调中。就像我说的,我对图书馆基本一无所知,所以如果你知道这个问题可能会在这里,我将不胜感激。CImg图像无色

这里的保存功能:

void Map::Save() { 
    Vertex top_left_most, top_right_most, bottom_left_most; 
    int img_w = 0, img_h = 0; 

    std::vector<std::pair<GLuint, GLuint>>::iterator tl = bufferIDs.begin();   //This little block gives the _most variables valid starting vals 
    glBindBuffer(GL_ARRAY_BUFFER, tl->second); 
    glGetBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureCoord), sizeof(Vertex), &top_left_most); 
    top_right_most = bottom_left_most = top_left_most; 


    for (auto i = bufferIDs.begin(); i != bufferIDs.end(); ++i) { //SEEKS TOP LEFT MOST TILE ON MAP 
     Vertex current_coord; 
     glBindBuffer(GL_ARRAY_BUFFER, i->second); 
     glGetBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureCoord), sizeof(Vertex), &current_coord); 

     if ((current_coord.x < top_left_most.x && current_coord.y < top_left_most.y) || 
      (current_coord.x == top_left_most.x && current_coord.y < top_left_most.y) || 
      (current_coord.x < top_left_most.x && current_coord.y == top_left_most.y)) { 

      top_left_most = current_coord; 
     } 
    } 

    for (auto i = bufferIDs.begin(); i != bufferIDs.end(); ++i) { //SEEKS TOP RIGHT MOST TILE ON MAP 
     Vertex current_coord; 
     glBindBuffer(GL_ARRAY_BUFFER, i->second); 
     glGetBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureCoord), sizeof(Vertex), &current_coord); 

     if ((current_coord.x > top_right_most.x && current_coord.y < top_right_most.y) || 
      (current_coord.x == top_right_most.x && current_coord.y < top_right_most.y) || 
      (current_coord.x > top_right_most.x && current_coord.y == top_right_most.y)) { 

      top_right_most = current_coord; 
     } 
    } 

    for (auto i = bufferIDs.begin(); i != bufferIDs.end(); ++i) { //SEEKS BOTTOM LEFT MOST TILE ON MAP 
     Vertex current_coord; 
     glBindBuffer(GL_ARRAY_BUFFER, i->second); 
     glGetBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureCoord), sizeof(Vertex), &current_coord); 

     if ((current_coord.x < bottom_left_most.x && current_coord.y > bottom_left_most.y) || 
      (current_coord.x == bottom_left_most.x && current_coord.y > bottom_left_most.y) || 
      (current_coord.x < bottom_left_most.x && current_coord.y == bottom_left_most.y)) { 

      bottom_left_most = current_coord; 
     } 
    } 

    img_w = (top_right_most.x + 64) - top_left_most.x;  //Calculating image dimensions for the buffer 
    img_h = (bottom_left_most.y + 64) - top_left_most.y; 

    GLuint *image = new GLuint[img_w * img_h];  //Creating the image buffer 

    int int_start_x = 0;  //start_x and y that will be used in buffer pointer positioning computations 
    int int_start_y = 0; 

    //these nested fors fill the buffer 
    for (GLfloat start_y = top_left_most.y; start_y != bottom_left_most.y + 64; start_y += 64) { 

     for (GLfloat start_x = top_left_most.x; start_x != top_right_most.x + 64; start_x += 64) { 

      bool in_map = false; 
      std::vector<std::pair<GLuint, GLuint>>::iterator valid_tile; 
      for (auto i = bufferIDs.begin(); i != bufferIDs.end(); ++i) {   //This for checks to see if tile corresponding to start_x & y is present in map 
       Vertex current_tile_pos; 
       glBindBuffer(GL_ARRAY_BUFFER, i->second); 
       glGetBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureCoord), sizeof(Vertex), &current_tile_pos); 

       if (current_tile_pos.x == start_x && current_tile_pos.y == start_y) { 
        in_map = true; 
        valid_tile = i; 
        break; 
       } 
      } 

      GLuint *imagepos = image;  //Repositioning the pointer into the final image's buffer 
      imagepos += int_start_x + (int_start_y * img_w); 

      if (in_map) {  //if in map, that tile's texture is used to fill the corresponding part of the image buffer 
       GLuint *texture = new GLuint[64 * 64]; 
       glBindTexture(GL_TEXTURE_2D, valid_tile->first); 
       glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); 
       GLuint *texturepos = texture; 

       for (GLuint ypos = 0; ypos != 64; ++ypos) { 
        std::memcpy(imagepos, texturepos, 64 * 4); 
        texturepos += 64; 
        imagepos += img_w; 
       } 

       if (texture) 
        delete[] texture; 
      } 
      else {    //otherwise, a default all-black array is used to fill the corresponding untiled part of the image buffer 
       GLuint *black_buffer = new GLuint[64 * 64]; 
       GLuint *blackpos = black_buffer; 
       GLuint solid_black; 
       char *p = (char *)&solid_black; 
       p[0] = 0; 
       p[1] = 0; 
       p[2] = 0; 
       p[3] = 255; 

       for (GLuint i = 0; i != 64 * 64; ++i) { 
        black_buffer[i] = solid_black; 
       } 

       for (GLuint ypos = 0; ypos != 64; ++ypos) { 
        std::memcpy(imagepos, blackpos, 64 * 4); 
        blackpos += 64; 
        imagepos += img_w; 
       } 

       if (black_buffer) 
        delete[] black_buffer; 

      } 
      int_start_x += 64; 
     } 
     int_start_x = 0; 
     int_start_y += 64; 
    } 

    cimg_library::CImg<GLuint> final_image(image, img_w, img_h); //no color!! 

    final_image.save_bmp("map.bmp"); 

    if (image) 
     delete[] image; 
} 

如果一些解释将是有益的,Vertex是两个GLfloat个简单struct(如TextureCoord),bufferIDsstd::pair S的GLuint秒的std::vector,第一个表示纹理ID,第二个表示VBO ID。

这里是请求的样品图片:

what the image should look like (this is in monochrome)

Same exact image as above, but created using the reinterpret_cast method

回答

0

你行

cimg_library::CImg<GLuint> final_image(image, img_w, img_h); 

是错的,如果你期望的彩色图像,因为这将创建一个单一的通道图像。最后需要3个通道来制作3个通道 - 一个用于红色,一个用于绿色,另一个用于蓝色。

另外,你的数据被存储在GLuint这意味着一个4×2像素的图像将被存储这样的,即带交织的逐像素

RGBA RGBA RGBA RGBA 
RGBA RGBA RGBA RGBA 

CIMG想要存储在一个带交错的平面时尚:

RRRRRRRR 
GGGGGGGG 
BBBBBBBB 
AAAAAAAA 

link解释内存缓冲区的布局CImg