1

My code as follows is giving me issues trying to write a bitmap image with an odd size 250x250 pixels. When I write it with an evenly divisibly by 3 area, eg. 160x160 everything is fine. I have spent a few hours now trying to get the 250x250 and other odd area's to write correctly but they just won't, the image is diagonal and half of it with the wrong color bits.

a busy cat

    int screen_save_part(string filename,unsigned x,unsigned y,unsigned w,unsigned h) //Assumes native integers are little endian
    {
        unsigned sz = w * h;
        FILE *bmp=fopen(filename.c_str(), "wb");
        if (!bmp) return -1;
        fwrite("BM", 2, 1, bmp);

        std::vector<unsigned char> rgbdata(3*sz);
        glReadPixels(x,window_get_region_height_scaled()-h-y,w,h,GL_BGR, GL_UNSIGNED_BYTE, &rgbdata[0]);
        //glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);

        sz <<= 2;
        fwrite(&sz,4,1,bmp);
        fwrite("\0\0\0\0\x36\0\0\0\x28\0\0",12,1,bmp);
        fwrite(&w,4,1,bmp);
        fwrite(&h,4,1,bmp);
        fwrite("\1\0\x18\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",28,1,bmp);

        if (w & 3) {
            w *= 3;
            size_t pad = 3 - (w % 3);
            sz -= sz >> 2;

            for(unsigned i = 0; i <= sz; i += w) {
                fwrite(&rgbdata[0] + i,sizeof(char),w,bmp);
                fwrite("\0\0\0",sizeof(char),pad,bmp);
            }

        } else { fwrite(&rgbdata[0], w*3, h, bmp); }

        fclose(bmp);
        rgbdata.clear();
        return 0;
    }

Ok, but yah I am about to start pulling my hair out here I have gone through literally everything the closest I got was a for loop after that one without any padding and just added an extra row of null data but that gave me a black line on the very top 1px scanline of the image, but it had no stretching issue.

4

1 回答 1

2

您希望扫描线之间的步幅(以字节为单位)为 DWORD 倍数。您现在所做的完全基于像素数(至少if (w & 3)分支建议这一点),而不是每像素的字节数。(w * 3) % 4如果您有 24-bpp 像素,我希望看到测试。如果此值 > 0,那么您需要添加那么多字节(每扫描线)以满足对齐。

尝试替换您的分支:

if (w & 3) {
    ...
}

与此类似(24-bpp 图像):

int scanline_padding = (w * 3) % 4; // This will be a value from 0-3

// DWORD alignment not satisfied, for each scanline add [scanline_padding] bytes
if (scanline_padding > 0) {
  for(unsigned i = 0; i < h; i++) {
    fwrite(&rgbdata[0] + (i * 3 * w),sizeof(char)*3,w,bmp); // Nothing special here
    fwrite("\0\0\0", scanline_padding, 1, bmp);             // Now for the magic
  }
}

// DWORD alignment was satisfied, so we can write the entire thing all at once
else {
  fwrite(&rgbdata[0], w*3, h, bmp);
}

这是未经测试的,但应该可以工作,或者至少应该给你一些大致的方向......

于 2013-11-03T01:58:43.573 回答