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