Zamiana 8 bitowej bitmapy na 32 bitowa.

0

Dla wlasnorecznie zrobionej bitmapy w hexeditorze dziala , ma ona 3 pixele , ale dla duzego obrazka psuje sie niemilosiernie. Wygenerowany obraz jest po prostu zbiorem roznobarwnych plam. W strukturze table trzymam tablice kolorow. W strukturze data trzymam poszczegolne pixele. W pointer5->pixel_data[] chce zapisywac pixele dla bitmapy 32 bitowej. Liczylem tez wlasnorecznie na kartce co sie dzieje w tym kodze dla bitmapy 3x2 i wyglada dobrze.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#pragma pack(push)
#pragma pack(1)

typedef struct Header{
  uint16_t type;
  uint32_t file_size;
  uint32_t reserved;
  uint32_t data_offset;
} Header;
typedef struct InfoHeader{
  uint32_t Info_Header_Size;
  int32_t width;
  int32_t height;
  uint16_t planes;
  uint16_t bits_per_pixel;
  uint32_t compression;
  uint32_t image_size;
  int32_t resolution_x;
  int32_t resolution_y;
  uint32_t colors_used;
  uint32_t important_colors;
}InfoHeader;

typedef struct data{
 unsigned char *pixel_data;
}data;

typedef struct table{
uint32_t *array;
}table;

#pragma pack(pop)
void grey_16(struct InfoHeader *pointer2,struct data*pointer3,struct data*pointer4);
int what_padding(struct InfoHeader *pointer2,int bits);
int  main(int argc , char *argv[])
{
Header *pointer;
     pointer = malloc(sizeof(Header));
FILE *fp = fopen( argv[1], "rb");
fread(pointer, sizeof(Header),1,fp);
InfoHeader * pointer2;
    pointer2 = malloc(sizeof(InfoHeader));
    fread(pointer2,sizeof(InfoHeader),1,fp);
table* pointer3;
    pointer3 = malloc(sizeof(table));
    pointer3->array = malloc(pointer2->colors_used);
    fread(pointer3->array,pointer2->colors_used*4,1 ,fp);
data* pointer4;
    pointer4 = malloc(sizeof(data));
    pointer4->pixel_data = malloc(pointer2->image_size);
    fread(pointer4->pixel_data,pointer2->image_size,1 ,fp);

    int padding =  what_padding(pointer2 , 1);

    int a = pointer2->width;
    int b = pointer2->height;
    data* pointer5;    pointer5 = malloc(sizeof(data));
    pointer5->pixel_data = malloc( (pointer2->image_size - pointer2->height*padding)*4);
    printf("%d, %d , %d, %d\n",pointer->type,pointer->file_size,pointer->reserved,pointer->data_offset);
    printf("%d, %d , %d\n",pointer2->Info_Header_Size,pointer2->image_size,pointer2->colors_used);

    for(int j = 0 ; j<b;j++)
    {
        for(int i =j*(a+padding);i< j*(a+padding)+a ; i++)
        {
            int pixel1 = pointer4->pixel_data[i];
            uint32_t value = pointer3->array[pixel1];
            int R = ((value&0xFF0000)>>16);
            int G = ((value&0xFF00)>>8);
            int B = (value&0xFF);
            pointer5->pixel_data[0+i*4-j*4]=B;
            pointer5->pixel_data[1+i*4-j*4]=G;
            pointer5->pixel_data[2+i*4-j*4]=R;
            pointer5->pixel_data[3+i*4-j*4]=0x0;
            printf("%d, %d, %d\n",B,G,R);
        }
    }

    pointer->file_size = 54 + 4*(pointer2->image_size-pointer2->height*padding);
    pointer->data_offset =54;
    pointer2->bits_per_pixel = 32;
    pointer2->image_size = 4*(pointer2->image_size-pointer2->height*padding);
    pointer2->colors_used = 0;

    FILE *fw = fopen(argv[2], "wb");
    fwrite(pointer, sizeof(Header),1,fw);
    fwrite(pointer2,sizeof(InfoHeader),1,fw);
    fwrite(pointer5->pixel_data,pointer2->image_size,1 ,fw);

    free(pointer);
    free(pointer2);
    free(pointer3->array);
    free(pointer3);
    free(pointer4->pixel_data);
    free(pointer4);
    free(pointer5->pixel_data);
    free(pointer5);
    fclose(fp);
    fclose (fw);
return 0;
}
int what_padding(struct InfoHeader *pointer2,int bits)
{
    int a = pointer2->width;
    int c = a*bits;
    int padding=0; 
    if (c%4==0)
        padding =0;
    if (c%4==1)
        padding =3;
    if (c%4==2)
        padding =2;
    if (c%4==3)
        padding =1;
    return padding;
}
1

Trochę zracjonalizowałem tę twoją funkcję, bo był kompletny bajzel (za te nazwy typu pointer1/2/3/4 nie powinienem nawet tykać tego):

int  main(int argc , char *argv[])
{
    Header      bmp_header;
    InfoHeader  bmp_info;

    FILE *fp = fopen( argv[1], "rb");
    fread(&bmp_header, sizeof(Header), 1, fp);
    fread(&bmp_info,sizeof(InfoHeader), 1, fp);

    uint32_t* color_table = malloc(bmp_info.colors_used * 4);
    fread(color_table, bmp_info.colors_used * 4, 1, fp);

    unsigned char* pixel_data = malloc(bmp_info.image_size);
    fread(pixel_data, bmp_info.image_size, 1, fp);

    int bmp_width = bmp_info.width;
    int bmp_height = bmp_info.height;

    unsigned char* pixel_data2 = malloc(bmp_height * bmp_width * 4);

    //printf("%d, %d , %d, %d\n",bmp_header.type,bmp_header.file_size,bmp_header.reserved,bmp_header.data_offset);
    //printf("%d, %d , %d\n",bmp_info.Info_Header_Size,bmp_info.image_size,bmp_info.colors_used);

    size_t scanline_size = bmp_width % 4;
    if(scanline_size) scanline_size = 4 - scanline_size;
    scanline_size += bmp_width;

    unsigned char* src_line = pixel_data;
    unsigned char* dst_ptr = pixel_data2;

    for(int j = 0; j < bmp_height; j++)
    {
        for(int i = 0; i < bmp_width; i++)
        {
            uint32_t value = color_table[src_line[i]];
            unsigned char R = ((value & 0xFF0000) >> 16);
            unsigned char G = ((value & 0xFF00) >> 8);
            unsigned char B = (value & 0xFF);
            *dst_ptr++ = B;
            *dst_ptr++ = G;
            *dst_ptr++ = R;
            *dst_ptr++ = 0x0;
        }

        src_line += scanline_size;
    }

    bmp_info.image_size = 4 * bmp_width * bmp_height;
    bmp_header.file_size = 54 + bmp_info.image_size;
    bmp_header.data_offset = 54;
    bmp_info.bits_per_pixel = 32;
    bmp_info.colors_used = 0;

    FILE *fw = fopen(argv[2], "wb");
    fwrite(&bmp_header, sizeof(Header), 1, fw);
    fwrite(&bmp_info, sizeof(InfoHeader), 1, fw);
    fwrite(pixel_data2, bmp_info.image_size, 1 ,fw);

    free(color_table);
    free(pixel_data);
    free(pixel_data2);

    fclose(fp);
    fclose (fw);
    return 0;
}

Nie wiem, czy to naprawi twój kod, ale na pewno nieco go uporządkuje.

0

Dzieki, nawet to troche pomogla. Juz widac na obrazie co to bylo wczesniej ,ale ma naprzyklad troche kolory zniekrztalcone i jest jakgdyby przesuniety w prawo o 1/8.

1

Być może piksele czyta od niewłaściwego offsetu. Przed czytaniem pikseli, przesuń wskaźnik odczytu o bmp_header.data_offset bajtów względem początku pliku.

Tak na dobrą sprawę pętlę można zredukować do:

unsigned char* src_line = pixel_data;
uint32_t* dst_ptr = (uint32_t*) pixel_data2;

for(int j = 0; j < bmp_height; j++)
{
    for(int i = 0; i < bmp_width; i++)
    {
        *dst_ptr++ = color_table[src_line[i]];
    }
    src_line += scanline_size;
}
0

Dodalem fseek(fp, bmp_header.data_offset, SEEK_SET); , przed unsigned char* pixel_data = malloc(bmp_info.image_size);
. Obraz nie jest przesuniety, ale teraz jakgdyby traci caly kolor. W zalacznikach screeny. Jakby teraz zle kolory byly czytane.

Na zrobionej przed chwila bitmapie 3 na 3 pixele dziala dobrze. Kolory sa zachowane.

0

Sprawdź też, czy bitmapa wyjściowa ma poprawnie ustawiony data_offset.

0
int main(int argc, char** argv)
{
    Header      bmp_header;
    InfoHeader  bmp_info;

    FILE *fp = fopen(argv[1], "rb");
    fread(&bmp_header, sizeof(Header), 1, fp);
    fread(&bmp_info,sizeof(InfoHeader), 1, fp);

    fseek(fp, bmp_info.Info_Header_Size - sizeof(bmp_info) , SEEK_CUR);

    uint32_t* color_table = (uint32_t*) malloc(bmp_info.colors_used * 4);
    fread(color_table, bmp_info.colors_used * 4, 1, fp);

    fseek(fp, bmp_header.data_offset, SEEK_SET);

    unsigned char* pixel_data = (unsigned char*) malloc(bmp_info.image_size);
    fread(pixel_data, bmp_info.image_size, 1, fp);

    int bmp_width = bmp_info.width;
    int bmp_height = bmp_info.height;

    unsigned char* pixel_data2 = (unsigned char*) malloc(bmp_height * bmp_width * 4);

    size_t scanline_size = ((bmp_info.bits_per_pixel * bmp_width + 31) / 32) * 4;

    unsigned char* src_line = pixel_data;
    unsigned char* dst_ptr = pixel_data2;

    for(int j = 0; j < bmp_height; j++)
    {
        for(int i = 0; i < bmp_width; i++)
        {
            uint32_t value = color_table[src_line[i]];
            unsigned char R = ((value & 0xFF0000) >> 16);
            unsigned char G = ((value & 0xFF00) >> 8);
            unsigned char B =  (value & 0xFF);
            *dst_ptr++ = B;
            *dst_ptr++ = G;
            *dst_ptr++ = R;
            *dst_ptr++ = 0x0;
        }

        src_line += scanline_size;
    }

    bmp_info.image_size = 4 * bmp_width * bmp_height;
    bmp_info.Info_Header_Size = sizeof(bmp_info);
    bmp_info.bits_per_pixel = 32;
    bmp_info.colors_used = 0;
    bmp_info.compression = 0;
    bmp_header.data_offset = sizeof(bmp_header) + sizeof(bmp_info);
    bmp_header.file_size = bmp_header.data_offset + bmp_info.image_size;

    FILE *fw = fopen(argv[2], "wb");
    fwrite(&bmp_header, sizeof(Header), 1, fw);
    fwrite(&bmp_info, sizeof(InfoHeader), 1, fw);
    fwrite(pixel_data2, bmp_info.image_size, 1 ,fw);

    free(color_table);
    free(pixel_data);
    free(pixel_data2);

    fclose(fp);
    fclose (fw);
    return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0