C에서 GBA 형식으로 변환하기 위해 24bpp 비트 맵에서 각 픽셀에 대한 RGB 값 얻기

StackOverflow https://stackoverflow.com/questions/1531268

  •  20-09-2019
  •  | 
  •  

문제

각 픽셀에 대한 RGB 값을 읽고 싶습니다. .bmp 파일을 변환 할 수 있습니다 bmp GBA (Gameboy Advance)에 적합한 형식으로.

각 픽셀에 대해 RGB 만 가져 와서이 정보를 파일에 작성해야합니다.

나는 사용하려고한다 <windows.h> 구조 :

typedef struct
{
    char signature[2];
    unsigned int fileSize;
    unsigned int reserved;
    unsigned int offset;
}BmpHeader;

typedef struct
{
    unsigned int headerSize;
    unsigned int width;
    unsigned int height;
    unsigned short planeCount;
    unsigned short bitDepth;
    unsigned int compression;
    unsigned int compressedImageSize;
    unsigned int horizontalResolution;
    unsigned int verticalResolution;
    unsigned int numColors;
    unsigned int importantColors;

}BmpImageInfo;

typedef struct
{
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    unsigned char reserved;
}Rgb;

typedef struct
{
    BmpHeader header;
    BmpImageInfo info;
    Rgb colors[256];
    unsigned short image[1];
}BmpFile;

그러나 나는 RGB 구조 만 있으면됩니다. 그래서 내가 "in.bmp"를 읽었다 고 가정 해 봅시다.

FILE *inFile, *outFile;
inFile = fopen("C://in.bmp", "rb");

Rgb Palette[256];
for(i=0;i<256;i++)
{
   fread(&Palette[i],sizeof(Rgb),1,inFile);
}

fclose(inFile);

이 올바른지? RGB 정보 만 파일에 어떻게 작성합니까?

도움이 되었습니까?

해결책

먼저 임베디드 팔레트에서 사용할 수있는 색상 수를 얻을 수 있습니다. 이것은 DIB 헤더에서 사용할 수 있습니다.

그런 다음 팔레트가 포함 된 모든 색상 구성 요소를 읽을 수 있습니다.

오프셋과 같은 모든 헤더 정보를 볼 수 있습니다. http://en.wikipedia.org/wiki/bmp_file_format.

작동해야합니다 : (편집 : 파일로 작성하려면 코드 추가)

FILE *inFile, *outFile;
BMPHeader header;
BMPImageInfo info;
RGB *palette, *p;
int i = 0;

inFile = fopen("C://in.bmp", "rb");
if( !inFile )
   return;

if( fread(&header, sizeof(BMPHeader), 1, inFile) != 1 )
   return; // Manage error and close file

if( fread&info, sizeof(BMPImageInfo), 1, inFile) != 1 )
   return; // Manage error and close file

if( info.numColors > 0 )
{
   palette = (RGB*)malloc(sizeof(RGB) * info.numColors);
   if( fread(palette, sizeof(RGB), info.numColors, inFile) != info.numColors )
      return; // manage error and close file
}

fclose(inFile)

// Binary method => if read later by another computer
outFile = fopen("path", "wb");
if( !outFile )
   return;

if( fwrite(&info.numColors, sizeof(unsigned int), 1, outFile) != 1 )
   return; // Manage Error and close file

if( fwrite(&palette, sizeof(RGB), info.numColors, outFile) != info.numColors )
   return; // Manage error and close file

fclose(outFile);

// Text method => if read later by human
outFile = fopen("path", "w");
if( !outFile )
   return;

for( i=0; i<info.numColors; ++i )
{
   p = &palette[i];
   if( fprintf(outFile, "R:%d, G:%d, B:%d\n", p->red, p->green, p->blue) < 0 )
      return; // Manage error and close file
}

fclose(outFile);

다른 팁

창문에 있다면 사용할 수 있습니다 loadBitMap Win32의 기능

그런 다음 핸들이 dib 비트 맵으로 변환하고 그런 식으로 픽셀로 이동합니다.

나는 약간의 테스트를하고 Patrice의 프로그램을 약간 확장했습니다. 나는 좋은 C 프로그래머가 아니기 때문에 모든 신용은 그에게 가고 내 부품은 그의만큼 우아하지 않습니다. 죄송합니다.

경고 : 미래의 거대한 소스 코드.

#include <stdio.h>
#pragma pack(2)


typedef struct
{
    char signature[2];
    unsigned int fileSize;
    unsigned int reserved;
    unsigned int offset;
} BmpHeader;

typedef struct
{
    unsigned int headerSize;
    unsigned int width;
    unsigned int height;
    unsigned short planeCount;
    unsigned short bitDepth;
    unsigned int compression;
    unsigned int compressedImageSize;
    unsigned int horizontalResolution;
    unsigned int verticalResolution;
    unsigned int numColors;
    unsigned int importantColors;

} BmpImageInfo;

typedef struct
{
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    //unsigned char reserved; Removed for convenience in fread; info.bitDepth/8 doesn't seem to work for some reason
} Rgb;


int main( int argc, char **argv ) {

    FILE *inFile;
    BmpHeader header;
    BmpImageInfo info;
    Rgb *palette;
    int i = 0;

    printf( "Opening file %s for reading.\n", argv[1] );

    inFile = fopen( argv[1], "rb" );
    if( !inFile ) {
        printf( "Error opening file %s.\n", argv[1] );
        return -1;
    }

    if( fread(&header, 1, sizeof(BmpHeader), inFile) != sizeof(BmpHeader) ) {
        printf( "Error reading bmp header.\n" );
        return -1;
    }

    if( fread(&info, 1, sizeof(BmpImageInfo), inFile) != sizeof(BmpImageInfo) ) {
        printf( "Error reading image info.\n" );
        return -1;
    }

    if( info.numColors > 0 ) {
        printf( "Reading palette.\n" );
        palette = (Rgb*)malloc(sizeof(Rgb) * info.numColors);
        if( fread(palette, sizeof(Rgb), info.numColors, inFile) != (info.numColors * sizeof(Rgb)) ) {
            printf( "Error reading palette.\n" );
            return -1; // error
        }
    }

    printf( "Opening file %s for writing.\n", argv[2] );
    FILE *outFile = fopen( argv[2], "wb" );
    if( !outFile ) {
        printf( "Error opening outputfile.\n" );
        return -1;
    }
    Rgb *pixel = (Rgb*) malloc( sizeof(Rgb) );
    int read, j;
    for( j=0; j<info.height; j++ ) {
        printf( "------ Row %d\n", j+1 );
        read = 0;
        for( i=0; i<info.width; i++ ) {
            if( fread(pixel, 1, sizeof(Rgb), inFile) != sizeof(Rgb) ) {
                printf( "Error reading pixel!\n" );
                return -1;
            }
            read += sizeof(Rgb);
            printf( "Pixel %d: %3d %3d %3d\n", i+1, pixel->red, pixel->green, pixel->blue );
        }
        if( read % 4 != 0 ) {
            read = 4 - (read%4);
            printf( "Padding: %d bytes\n", read );
            fread( pixel, read, 1, inFile );
        }
    }

    printf( "Done.\n" );
    fclose(inFile);
    fclose(outFile);

    printf( "\nBMP-Info:\n" );
    printf( "Width x Height: %i x %i\n", info.width, info.height );
    printf( "Depth: %i\n", (int)info.bitDepth );

    return 0;

}

이 프로그램은 파일에 저장된 픽셀 정보를 읽습니다. 패딩을 고려하지만 픽셀 색상 깊이 당 24 비트로 BMP 와만 작동합니다 (다른 깊이가 필요한 경우 RGB 구조물을 사용자 정의해야 함). 이것이 당신에게 도움이되기를 바랍니다. 그러나 내가 말했듯이, 그것은 단지 Patrice 코드의 확장 일뿐입니다.

다음은 TestFile의 샘플 출력입니다.

$ ./a.out test.bmp out.txt
Opening file test.bmp for reading.
Opening file out.txt for writing.
------ Row 1
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3:   0   0   0
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 2
Pixel 1:   0   0   0
Pixel 2: 232  33  33
Pixel 3:   0   0   0
Pixel 4: 232  33  33
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 3
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3: 232  33  33
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 4
Pixel 1:   0   0   0
Pixel 2: 232  33  33
Pixel 3:   0   0   0
Pixel 4: 232  33  33
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 5
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3:   0   0   0
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
Done.

BMP-Info:
Width x Height: 5 x 5
Depth: 24

편집 : 예, 내 이미지가 적십자사를 표시하고 있습니다. 이미지가 거꾸로 저장되므로 파일의 행 1은 실제로 이미지의 행 5 행입니다. d 'oh 코드를 제출하기 위해 무언가를 쓰는 것을 잊어 버렸지 만 이것은 당신에게 운동을하는 것으로 남아 있습니다.).

압축되지 않은 24bpp 비트 맵이고 너비가 4로 나눌 수 있음을 보장한다면 비교적 간단합니다.

  1. 읽다 BmpHeader 파일의 시작시.
  2. 찾지 않고 읽으십시오 BmpImageInfo.
  3. 추구하십시오 BmpHeader'에스 offset 바이트 파일의 시작. 24 비트 비트 맵에는 팔레트가 없습니다 (적어도 우리가 관심을 갖지는 않습니다)!
  4. bgr triplets를 읽고 (순서대로, reserved 여기에 사용되지 않은 회원). 있을 것입니다.BmpImageInfo멤버) width * abs(height) 트리플렛. 내가 기억하는 것처럼 height 긍정적 (표준 케이스), 당신이 읽는 첫 번째 색상은 다음과 같습니다. 맨 아래 이미지의 줄, 거기에서 올라갑니다. 만약에 height 그러나 부정적이지만 파일의 첫 번째 색상은 맨 위 이미지에서, 거기에서 내려갑니다.

그러한 보증을 할 수 없다면 상황이 더 복잡해집니다.

면책 조항 : 나는 여기서 내 자신의 경적을 잊어 버린다. 몇 년 전 저는 휴대용 (100% ANSI) 방식으로 말하는 것을 정확하게 수행하기 위해 작은 (하나의 소스 파일) 유틸리티를 작성했습니다. glbmp libbmpread. 그 소스는 당신의 문제에 대해 약간의 빛을 비출 수 있습니다. 그것은 비트 깊이의 끊임없는 (rle) 비트 맵을 처리하고 GBA에서 잘 작동해야합니다.

파일 구조에 대한 많은 정보를 제공하는 .BMP 파일 형식의 Wikipedia 페이지를 참조하고 파일을 구문 분석하는 데 도움이됩니다.

http://en.wikipedia.org/wiki/bmp_file_format

코드에서 먼저 데이터의 시작 주소 (파일 헤더에 지정 됨)와 이미지의 높이를 읽어야합니다. 그런 다음이 위치를 찾으십시오. 그 후 당신은 픽셀로 한 행 픽셀로 읽고 (헤더는 픽셀 당 비트의 수를 지정) 끝에 32 비트 패딩을 관리해야합니다. 24 비트 이미지 (RGB)에서 정보는 BGR 순서로 저장됩니다. 또한 높이 값이 음수가 아닌 경우 이미지가 거꾸로 저장됩니다.

BMP 파일 형식에 익숙하지 않지만 먼저 헤더 정보를 읽을 필요가 없습니까? 같은 것 :

BmpHeader header;
fread(&header,sizeof(BmpHeader),1,inFile);

자세한 이미지 정보로 읽으십시오.

BmpImageInfo info;
fread(&info,sizeof(BmpImageInfo),1,inFile);

팔레트 정보도 읽으십시오.

일단 있으면 파일 크기와 데이터 오프셋을 알 수 있습니다. 충분한 공간을 사전 할당하고 한 번에 읽을 수 있습니다. 가장 간단 할 수 있습니다. 또는 당신은 당신이 갈 때 덩어리를 읽고 구문 분석 할 수 있습니다 (메모리가 충분하지 않을 가능성을 줄이지 만 구문 분석은 더 복잡합니다).

압축이 활성화 된 경우 정보 섹션에서도 알 수 있습니다. 이미지 치수 등.

한 번에 읽고 있다면 데이터 오프셋으로 이동하여 다음과 같은 작업을 수행하십시오.

Rgb* rgb = offset;
blueVal = rgb->blue;
greenVal = rgb->green;
redVal = rgb->red;
rgb += sizeof( Rgb );

등등. 분명히 코드는 오류, 버퍼 끝 등을 확인하지 않으므로 그렇게해야합니다. 이미지 데이터를 이해하려면 팔레트 정보를 읽어야 할 수도 있습니다.

또는 다른 사람이 말했듯이 Wikipedia의 형식 사양을보십시오.

BMP 파일에 팔레트가있는 경우 아래 코드가 있습니다. ~해야 한다 일하다:

  FILE *inFile, *outFile;
  inFile = fopen("C:/in.bmp", "rb");
  Rgb Palette[256];
  if ( inFile ) {
    // Bypass headers
    fseek(inFile, sizeof(BmpHeader) + sizeof(BmpImageInfo), SEEK_SET);
    // Load the whole palette
    fread(Palette, sizeof(Palette), 1, inFile);
    fclose(inFile);
  }

몇 년 전에 BMP 파일을 읽고 쓰기 위해 몇 년 전에 작성한 일부 C 코드를 보는 것이 유용 할 수 있습니다.

http://david.tribble.com/src/bmp/bmp.html

나는 그것이 다양한 픽셀 비트 크기 (1/2/4/8/24)와 RLE 압축을 처리한다고 생각합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top