C语言 从.EXE文件中提取BMP

a7qyws3x  于 2023-06-21  发布在  其他
关注(0)|答案(3)|浏览(129)

我有一个C代码,我可以找到BMP图像。它很好地选择了我的图像,例如,它有3992字节。我用资源调谐器程序检查了这个。如何将缓冲区中保存的内容保存为BMP文件?

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

struct BMPHeader
{
    char signature[2];
};

int main()
{
    FILE* file = fopen("C:\\Program Files\\...", "rb");

    if (!file)
    {
        printf("Nu s-a putut deschide fisierul.\n");
        return 1;
    }

    struct BMPHeader* bmpHeaders = NULL;
    int bmpCount = 0;

    fseek(file, 0, SEEK_END);
    long fileSize = ftell(file);
    fseek(file, 0, SEEK_SET);

    while (ftell(file) < fileSize)
    {
        struct BMPHeader header;
        fread(&header, sizeof(struct BMPHeader), 1, file);
        if (memcmp(header.signature, "BM", 2) == 0)
        {
            long int poz = ftell(file);
            int fileSizeBMP = 0;
            char buffer[3992];

            fread(&fileSizeBMP, 4, 1, file);
            fseek(file, 0, SEEK_CUR);

            size_t bytesread = fread(&buffer, sizeof(char), fileSizeBMP, file);
            printf("%i ", fileSizeBMP);
            if(fileSizeBMP == 3992)
            {
                for(size_t i=0; i<bytesread; i++)
                {
                    printf("%02x ", buffer[i]);
                }

                FILE* file = fopen("image1.bmp", "wb");

                fwrite(buffer, sizeof(buffer), 1, file);

                printf("%zu ", bytesread);
            }
        }
    }

    fclose(file);
    return 0;
}

我尝试了,因为它是现在,但文件已损坏,我认为是卡住了。我在想也许标题不完整

stszievb

stszievb1#

BMP文件以"BM"开始,然后具有文件大小。你读了那部分但没写。没有该标头的BMP文件将被损坏。它可以与这种改进工作。

....
//no changes here

#define BM_HEADER "BM" //Add to follow DRY in the changed code

void die(const char *msg) //Add this to handle errors
{
    perror(msg); 
    exit(1);
}

int main()
{
    ....
    //No changes at the opening of the file

    int bmpCount = 0;     // Remove this line. You don't use it.

    //Don't need file size, use the return value of fread() to detect
    // the end

    while(1) //use the return value of fread() to determine end of file
    {
        struct BMPHeader header;
        if(fread(&header, sizeof(struct BMPHeader), 1, file)<1)
        { 
            break; //End of file
        }
        if(memcmp(header.signature, BM_HEADER, strlen(BM_HEADER) ) == 0)
        {
            long int poz = ftell(file); //remove this line, you don't use poz
            //use a uint32_t to have the correct size regardless of archidekture
            uint32_t fileSizeBMP = 0;
            char buffer[3992];

            fread(&fileSizeBMP, sizeof fileSizeBMP, 1, file); //use sizeof instead of hardcoded values
            fseek(file, 0, SEEK_CUR); //remove this line, it does basically nothing (position doesn't change)

            //Note, BMP uses little endian integers, your CPU may or may not use little endian
            //Your code will break on a CPU that doesn't use little endian. 

            //a char has always the size of 1.
            size_t bytesread = fread(&buffer, 1, fileSizeBMP, file);
            if(!bytesread) //couldn't read the data
            {
                die("read error");
            }
            //changed type of fileSizeBMP, changed format string accordingly
            printf("%PRIu32\n ", fileSizeBMP);
            if(fileSizeBMP == sizeof buffer ) //use sizeof to follow DRY
            {
                for(size_t i=0; i<fileSizeBMP; i++)
                {
                    printf("%02x ", buffer[i]);
                }

                FILE* fileOut = fopen("image1.bmp", "wb"); //rename file to avoid confusion

                if(fputs(BM_HEADER, fileOut)<0) //You need the header "BM"
                {
                    die("write error");
                }
                if(!fwrite(fileSizeBMP, sizeof(fileSizeBMP), 1, fileOut)) //And the size
                {
                    die("write error");
                }
                if(!fwrite(buffer, sizeof(buffer), 1, fileOut)) //Don't forget to check for errors
                {
                    die("write error");
                }

                printf("%zu ", bytesread);
            }
        }
    }

    fclose(file);
    return 0;
}

我不确定fileSizeBMP是完整的文件大小还是fileSizeBMP之后的大小(你的文件可能太大了6个字节)。
我不知道你的规则是什么,在if/while/for()之间放置空格

nwlls2ji

nwlls2ji2#

您正在尝试使用fseek(file, 0, SEEK_CUR)返回到开头,将所有内容读取到buffer,并将buffer写入文件。
问题是您的fseek()调用将0添加到当前位置,因此没有任何更改。您写入的文件缺少文件头,因为您在fseek()调用之前读取了它。
如果文件只包含BMP数据,您可以简单地使用fseek(file, 0, SEEK_SET)将当前位置设置为0。但是由于BMP数据从文件中间开始,因此仍然必须使用SEEK_CUR。将当前位置移回BMP数据的开头:

fseek(file, -sizeof(struct BMPHeader) - 4, SEEK_CUR);
hi3rlvi2

hi3rlvi23#

我不确定你在尝试什么,但这段代码可能有用。它从一个RGBType数组创建一个BMP文件,指定像素信息、dpi以及宽度和高度,因此您可以使用它来确定标题,以便将正确的数据对齐方式传递给FILE

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

typedef struct RGBType {
    double r;
    double g;
    double b;
} RGBType;

void savebmp (const char *filename, int w, int h, int dpi, RGBType *data) {
    FILE *f;
    int k = w*h;
    int s = 4*k;
    int filesize = 54 + s;

    double factor = 39.375;
    int m = (int)(factor);

    int ppm = dpi*m;

    unsigned char bmpfileheader[14] = {'B','M', 0,0,0,0, 0,0,0,0, 54,0,0,0};
    unsigned char bmpinfoheader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,24,0};

    bmpfileheader[ 2] = (unsigned char)(filesize);
    bmpfileheader[ 3] = (unsigned char)(filesize>>8);
    bmpfileheader[ 4] = (unsigned char)(filesize>>16);
    bmpfileheader[ 5] = (unsigned char)(filesize>>24);

    bmpinfoheader[ 4] = (unsigned char)(w);
    bmpinfoheader[ 5] = (unsigned char)(w>>8);
    bmpinfoheader[ 6] = (unsigned char)(w>>16);
    bmpinfoheader[ 7] = (unsigned char)(w>>24);

    bmpinfoheader[ 8] = (unsigned char)(h);
    bmpinfoheader[ 9] = (unsigned char)(h>>8);
    bmpinfoheader[10] = (unsigned char)(h>>16);
    bmpinfoheader[11] = (unsigned char)(h>>24);

    bmpinfoheader[21] = (unsigned char)(s);
    bmpinfoheader[22] = (unsigned char)(s>>8);
    bmpinfoheader[23] = (unsigned char)(s>>16);
    bmpinfoheader[24] = (unsigned char)(s>>24);

    bmpinfoheader[25] = (unsigned char)(ppm);
    bmpinfoheader[26] = (unsigned char)(ppm>>8);
    bmpinfoheader[27] = (unsigned char)(ppm>>16);
    bmpinfoheader[28] = (unsigned char)(ppm>>24);

    bmpinfoheader[29] = (unsigned char)(ppm);
    bmpinfoheader[30] = (unsigned char)(ppm>>8);
    bmpinfoheader[31] = (unsigned char)(ppm>>16);
    bmpinfoheader[32] = (unsigned char)(ppm>>24);

    f = fopen(filename, "wb");

    fwrite(bmpfileheader,1,14,f);
    fwrite(bmpinfoheader,1,40,f);

    for (int i = 0; i < k; i++) {
        RGBType rgb = data[i];

        double red = (data[i].r)*255;
        double green = (data[i].g)*255;
        double blue = (data[i].b)*255;

        unsigned char color[3] = {(int)floor(blue), (int)floor(green), (int)floor(red)};

        fwrite(color,1,3,f);
    }

    fclose(f);

}

int thisone;

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

    int dpi = 72;

    int width = 640;
    int height = 480;
    int n = width*height;

    RGBType *pixels = (RGBType*) malloc(n * sizeof(RGBType));

    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            thisone = y*width + x;

            pixels[thisone].r = 23;
            pixels[thisone].g = 222;
            pixels[thisone].b = 10;
        }
    }

    savebmp("image.bmp",width,height,dpi,pixels);

    return 0;
}

相关问题