簡體   English   中英

在C / C ++中將1位bmp文件轉換為數組

[英]Converting 1-bit bmp file to array in C/C++

我希望將一個可變高度/寬度的1位bmp文件轉換為一個值為0或1的簡單二維數組。我沒有任何代碼和大多數庫中的圖像編輯經驗。發現涉及比我需要更高的比特深度。 對此有任何幫助都會很棒。

這是讀取單色.bmp文件的代碼

(見DMB的回答下面一個小的修復奇數大小.bmps)

#include <stdio.h>
#include <string.h>
#include <malloc.h>

unsigned char *read_bmp(char *fname,int* _w, int* _h)
{
    unsigned char head[54];
    FILE *f = fopen(fname,"rb");

    // BMP header is 54 bytes
    fread(head, 1, 54, f);

    int w = head[18] + ( ((int)head[19]) << 8) + ( ((int)head[20]) << 16) + ( ((int)head[21]) << 24);
    int h = head[22] + ( ((int)head[23]) << 8) + ( ((int)head[24]) << 16) + ( ((int)head[25]) << 24);

    // lines are aligned on 4-byte boundary
    int lineSize = (w / 8 + (w / 8) % 4);
    int fileSize = lineSize * h;

    unsigned char *img = malloc(w * h), *data = malloc(fileSize);

    // skip the header
    fseek(f,54,SEEK_SET);

    // skip palette - two rgb quads, 8 bytes
    fseek(f, 8, SEEK_CUR);

    // read data
    fread(data,1,fileSize,f);

    // decode bits
    int i, j, k, rev_j;
    for(j = 0, rev_j = h - 1; j < h ; j++, rev_j--) {
        for(i = 0 ; i < w / 8; i++) {
            int fpos = j * lineSize + i, pos = rev_j * w + i * 8;
            for(k = 0 ; k < 8 ; k++)
                img[pos + (7 - k)] = (data[fpos] >> k ) & 1;
        }
    }

    free(data);
    *_w = w; *_h = h;
    return img;
}

int main()
{
    int w, h, i, j;
    unsigned char* img = read_bmp("test1.bmp", &w, &h);

    for(j = 0 ; j < h ; j++)
    {
        for(i = 0 ; i < w ; i++)
            printf("%c ", img[j * w + i] ? '0' : '1' );

        printf("\n");
    }

    return 0;
}

它是普通的C,所以沒有指針轉換 - 在C ++中使用它時要小心。

最大的問題是.bmp文件中的行是4字節對齊的,這對於單比特圖像很重要。 因此我們將線尺寸計算為“width / 8 +(width / 8)%4”。 每個字節包含8個像素,而不是一個,因此我們使用基於k的循環。

我希望其他代碼是顯而易見的 - 很多人都被告知.bmp標題和pallete數據(我們跳過的8個字節)。

樣本圖片

預期產量:

0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
0 0 0 0 0 0 1 1 1 1 0 0 1 1 0 0 
0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 
0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 
0 0 0 1 0 0 1 1 1 1 0 0 0 0 0 0 
0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 
0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 
0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 
0 0 0 0 0 0 1 1 1 1 0 0 1 0 0 0 
0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 
0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 
0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 
0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 
0 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 
0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 

我在20x20測試圖像上嘗試了Viktor Lapyov的解決方案: 在此輸入圖像描述

但是使用他的代碼,我得到了這個輸出(稍微重新格式化,但你可以看到問題):

在此輸入圖像描述

最后4個像素未被讀取。 問題出在這里。 (忽略行中的最后一個部分字節。)

// decode bits
int i, j, k, rev_j;
for(j = 0, rev_j = h - 1; j < h ; j++, rev_j--) {
    for(i = 0 ; i < w / 8; i++) {
        int fpos = j * lineSize + i, pos = rev_j * w + i * 8;
        for(k = 0 ; k < 8 ; k++)
            img[pos + (7 - k)] = (data[fpos] >> k ) & 1;
    }
}

我重寫了內部循環,如下所示:

// decode bits
int i, byte_ctr, j, rev_j;
for(j = 0, rev_j = h - 1; j < h ; j++, rev_j--) {
    for( i = 0; i < w; i++) {
        byte_ctr = i / 8;
        unsigned char data_byte = data[j * lineSize + byte_ctr];
        int pos = rev_j * w + i;
        unsigned char mask = 0x80 >> i % 8;
        img[pos] = (data_byte & mask ) ? 1 : 0;
    }
}

一切都很好:

在此輸入圖像描述

以下c代碼適用於任何大小的單色位圖。 我假設你的位圖在緩沖區中,高度和寬度從文件初始化。 所以

// allocate mem for global buffer
if (!(img = malloc(h * w)) )
     return(0);

int i = 0, k, j, scanline;

// calc the scanline. Monochrome images are
// padded with 0 at every line end. This
// makes them divisible by 4.
scanline = ( w + (w % 8) ) >> 3;

// account for the paddings
if (scanline % 4)
    scanline += (4 - scanline % 4);

// loop and set the img values
for (i = 0, k = h - 1; i < h; i++)
    for (j = 0; j < w; j++) {
        img[j+i*w] = (buffer[(j>>3)+k*scanline])
           & (0x80 >> (j % 8));
    }

希望這可以幫助。 將它轉換為2D現在是一個微不足道的事情:但如果你迷失在這里是將1D數組轉換為2D的數學假設r&c是行和列,w是寬度然后:。 c + r * w = r,c

如果你有進一步的評論打擊我,我出去了!

讓我們想一下a1x7單色位圖,即這是一個7像素寬的直線位圖。 將此圖像存儲在Windows操作系統上; 由於7不能被4整除,因此它將在其中填充額外的3個字節。

因此BITMAPINFOHEADER結構的biSizeImage將顯示總共4個字節。 盡管如此,biHeight和biWidth成員將正確地指出真正的位圖尺寸。

上面的代碼將失敗,因為7/8 = 0(通過與所有c編譯器一樣四舍五入)。 因此循環“i”將不會執行,因此將“k”。

這意味着向量“img”現在包含與“數據”中包含的像素不對應的垃圾值,即結果不正確。

如果它不滿足基本情況,那么通過歸納推理,那么對於一般情況來說它很可能不會有很多好處。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM