1

次のコードは、奇数サイズの 250x250 ピクセルのビットマップ イメージを書き込もうとすると問題が発生します。たとえば、3つの領域で均等に割り切れるように書くと。160x160で大丈夫です。250x250 およびその他の奇妙な領域を正しく書き込むために数時間を費やしましたが、うまくいきません。

忙しい猫

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

わかりました、でも、ここで髪を引っ張り始めようとしています。文字通り、最も近いものはすべて、パディングなしの for ループであり、null データの余分な行を追加しただけですが、黒い線が表示されました。画像の最上部の 1px スキャンラインで、ストレッチの問題はありませんでした。

4

1 に答える 1

2

スキャンライン間のストライド (バイト単位) を DWORD の倍数にする必要があります。if (w & 3)現在行っていることは、ピクセルあたりのバイト数ではなく、完全にピクセル数に基づいています (少なくともブランチはこれを示唆しています)。(w * 3) % 424 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 に答える