簡體   English   中英

將像素數組加載到帶有填充行的數組后,如何填充 bmp 文件中像素之間的空白

[英]how do I fill the gaps between pixel in bmp file after loading the pixel array into the array with padded rows

我在 c++ 中編寫了一個程序,使用 SetPixel windows function 將 bmp 圖像的像素繪制到控制台中,但是在將像素陣列加載到像素之間的像素陣列中后,圖像打印在了陣列上。 在此先感謝您的幫助!

在此處輸入圖像描述

這是控制台上打印圖像的output。

這是我提供給它的原始圖像。

在此處輸入圖像描述

正如您在此處看到的,在控制台上打印后圖像寬度也會發生變化。

// bmp bitmap
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
using namespace std;

#pragma pack(1)
struct BitmapFileHeader {
    unsigned short type;
    unsigned int size;
    unsigned short reserved1;
    unsigned short reserved2;
    unsigned int offset;
};
#pragma pack(0)

unsigned char grayScale(unsigned char r, unsigned char g, unsigned char b) {
    return ((r + g + b) / 3);
}
int main() {
    char *data;
    FILE *filePointer;
    int **ImageArray;
    BitmapFileHeader *bmp = (struct BitmapFileHeader*)malloc(sizeof(struct BitmapFileHeader));
    BITMAPINFOHEADER *BitmapInfoHeader = (BITMAPINFOHEADER*)malloc(sizeof(BITMAPINFOHEADER));
    HWND console = GetConsoleWindow();
    HDC context = ::GetDC(console) ;
    
    filePointer = fopen("tom.bmp", "rb");
    if(!filePointer) {
        perror("");
    }
    fread(reinterpret_cast<BitmapFileHeader*>(bmp), sizeof(BitmapFileHeader), 1, filePointer);
    fread(reinterpret_cast<BITMAPINFOHEADER*>(BitmapInfoHeader), sizeof(BITMAPINFOHEADER), 1, filePointer);

    if(BitmapInfoHeader->biSize == 40 && BitmapInfoHeader->biCompression == BI_BITFIELDS) {
        printf("This types of image uses Extra bit masks\n");
    }
    // row pading 
    int RowSize = ((BitmapInfoHeader->biBitCount * BitmapInfoHeader->biWidth + 31) / 32) * 4;
    int PixelArraySize = RowSize * BitmapInfoHeader->biHeight;
    int height = BitmapInfoHeader->biHeight * 5;
    int width = BitmapInfoHeader->biWidth * 5;
    
    printf("RowSize: %d PixelArraySize: %d\n", RowSize, PixelArraySize);
    
    ImageArray = (int**)malloc(sizeof(int*)*height);
    
    // memory allocation
    for(int i = 0; i < height; i++)
        ImageArray[i] = (int*)malloc(sizeof(int)*width);
        
    data = (char*)malloc(PixelArraySize);
    fseek(filePointer, bmp->offset, SEEK_SET);
    
     
    // set image into array 
    for(int ii = 0; ii < height; ii+=3) {
        fread(data, RowSize, 3, filePointer);
        for(int jj = 0; jj < width; jj+=3) {
            ImageArray[ii][jj] = grayScale(data[jj+2], data[jj+1], data[jj]);
                SetPixel(context, -jj+1000, -ii+500, RGB(data[jj+2], data[jj+1], data[jj]));
            }
    }
    fclose(filePointer);
    return 0;
}

這是我寫的代碼。

一個像素由三個字節描述,每個 RGB 通道一個。 您在這里處理兩個索引:行數據中像素的索引和像素在寬度方向上的 position。 您放置像素並使用相同的索引訪問行數據。

所以:

    for (int jj = 0; jj < width; jj++) {      // jj: position
        int kk = 3 * jj;                      // kk: data index

        ImageArray[ii][jj] = grayScale(data[kk + 2], data[kk + 1], data[kk]);
        SetPixel(context, -jj + 1000, -ii + 500, RGB(data[kk + 2], data[kk + 1], data[kk]));
    }

垂直間隙,即空白行,來自增加 3,您應該只增加 1。(這里沒有“數據索引”,因為您讀取了當前行ii的行寬數據。)

如果你想放大你的圖像,正如寬度和高度乘以 5 所暗示的那樣,你必須添加第三個索引:你現在有兩個位置,源位置和目標位置。 如果將循環分開,這將更容易:在第一個嵌套循環中創建源圖像的ImageArray ,然后在目標坐標上循環將縮放的目標圖像繪制到控制台:

int scale = 5;
int ww = scale * w;
int hh = scale * h;

// read ImageArray

for (int y = 0; y < h; y++) {
    fread(data, RowSize, 3, filePointer);

    for (int x = 0; x < w; x++) {
        ImageArray[y][x] = ...;
            SetPixel(context, -jj+1000, -ii+500, RGB(data[jj+2], data[jj+1], data[jj]));
        }
}

for (int yy = 0; yy < hh; yy++) {
    fread(data, RowSize, 3, filePointer);

    for (int xx = 0; xx < ww; xx++) {
        int x = xx / scale;
        int y = yy / scale;

        SetPixel(context, yy, xx, ImageArray[y][x]);
    }
}

(這里,單字母是資源值,雙字母是目標值。)

暫無
暫無

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

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