Конвертер из Bmp в Tga - C (СИ)
Формулировка задачи:
Доброго времени суток.
Возникла проблема с конвертером изображений (Bmp->Tga). Дело в том, что изображение, получившееся в результате кодирования, наклонено вбок (можете удостовериться сами, запустив программу). Третьи сутки борюсь с этой проблемой, совсем отчаялся, прошу помощи. Уж не покиньте, пожалуйста
Вот код (пока написал исключительно для преобразования 24-битного бмп в несжатый тга):
#include <stdio.h> #include <string.h> #include <locale.h> #include "stdlib.h" #include "math.h" // Структура BITMAP FILE HEADER --------------------------------------------------------------------------------------------------------- #pragma pack(push) #pragma pack(1) typedef struct { unsigned char b1, b2; unsigned long bfSize; //Размер файла в байтах (Смещение 2, длина 4) unsigned short bfReserved1; //Бесполезно (Смещение 6, длина 2) unsigned short bfReserved2; //Бесполезно (Смещение 8, длина 2) unsigned long bfOffBits; //Смещение до самого изображения (Смещение 10, длина 4) } BmpHeader; #pragma pack(pop) // Структура BITMAP INFO HEADER --------------------------------------------------------------------------------------------------------- typedef struct { unsigned long biSize; //Размер данной структуры в байтах. Опред. версия формата unsigned long biWidth; //Ширина изображения в пикселях. unsigned long biHeight; //Высота изображения в пикселях. unsigned short biPlanes; //Количество цветовых плоскостей и в формате BMP содержит единицу. unsigned short biBitCount; //Количество бит на пиксель. unsigned short biCompression; //Тип сжатия для сжатых изображений unsigned short biSizeImage; //Размер изображения в байтах. Может содержать ноль для BI_RGB-изображений. unsigned long biXPelsPerMeter; //Горизонтальное разрешение в пикселях на метр для целевого устройства. unsigned long biYPelsPerMeter; //Вертикальное разрешение в пикселях на метр для целевого устройства. unsigned short biClrUsed; //Количество используемых цветовых индексов в палитре. unsigned short biClrImportant; //Количество элементов палитры, необходимых для отображения изображения. } BmpImageInfo; // Структура TGA INFO HEADER --------------------------------------------------------------------------------------------------------- typedef struct { char idlength; char colourmaptype; char datatypecode; short int colourmaporigin; short int colourmaplength; char colourmapdepth; short int x_origin; short int y_origin; short width; short height; char bitsperpixel; char imagedescriptor; } TgaImageInfo; typedef struct { unsigned char r; unsigned char g; unsigned char b; // unsigned char a; } RGB; void MergeBytes(RGB *,unsigned char *,int); int main(int argc, char *argv[]) { int n=0, i,j; BmpHeader bmpheader; BmpImageInfo bmpimageinfo; TgaImageInfo tgaimageinfo; RGB *pixels, *outpixels; unsigned char tmp[5]; //int massR[i][j], massG[i][j], massB[i][j]; int pad, size; int bytes2read; FILE *BmpImage = fopen("E:/Jazblki programmirovanija/Kursovaya_Revchenko_10-IT-3/example.bmp","rb"); FILE *BmpCode = fopen("E:/Jazblki programmirovanija/Kursovaya_Revchenko_10-IT-3/BmpCode.txt","w"); FILE *TgaCode = fopen("E:/Jazblki programmirovanija/Kursovaya_Revchenko_10-IT-3/TgaCode.txt","w"); FILE *TgaImage = fopen("E:/Jazblki programmirovanija/Kursovaya_Revchenko_10-IT-3/TgaImage.tga","wb"); setlocale(LC_ALL, ""); if (!BmpImage ) { printf("Ошибка чтения BMP-файла.\n"); return 1; } //Выравнивание структуры-------------------------------------------------- pad = sizeof(BmpHeader); printf("BmpHeader до выравнивания: %d\n", pad); if (pad > 14) { while (pad != 14) { pad -= 1; } } printf("BmpHeader после выравнивания: %d\n", pad); //--------------------------------------------------------------------------------------- if (fread(&bmpheader, pad, 1, BmpImage) != 1){ printf("Ошибка чтения заголовка Bmp-изображения\n"); return 2; } if (fread (&bmpimageinfo, sizeof(BmpImageInfo), 1, BmpImage) != 1 ){ printf("Ошибка чтения информации Bmp-изображения.\n"); return 3; } printf("sizeof(BmpImageInfo) = %d\n", sizeof(BmpImageInfo)); printf("_______Данные_о_BITMAP_FILE_HEADER_______\n"); printf("Тип файла : %c%c\n", bmpheader.b1, bmpheader.b2); printf("Размер файла : %d bytes\n", bmpheader.bfSize); printf("Резервный слот 1 : %d\n", bmpheader.bfReserved1); printf("Резервный слот 2 : %d\n", bmpheader.bfReserved2); printf("Смешение до изображения : %d bytes\n\n", bmpheader.bfOffBits); printf("_______Данные_о_BITMAP_INFO_HEADER_______\n"); printf("Размер структ. в байтах : %d bytes\n", bmpimageinfo.biSize); printf("Ширина изображения : %d px\n", bmpimageinfo.biWidth); printf("Высота изображения : %d px\n", bmpimageinfo.biHeight); printf("Кол. цветовых плоск. : %d\n", bmpimageinfo.biPlanes); printf("Кол. бит на пиксель : %d-bit\n", bmpimageinfo.biBitCount); printf("Тип сжатия : %d\n", bmpimageinfo.biCompression); bmpimageinfo.biSizeImage = bmpimageinfo.biXPelsPerMeter; bmpimageinfo.biXPelsPerMeter = bmpimageinfo.biYPelsPerMeter; bmpimageinfo.biYPelsPerMeter = bmpimageinfo.biClrUsed; bmpimageinfo.biClrUsed = 0; printf("Размер изобр. в байтах : %d bytes\n", bmpimageinfo.biSizeImage); printf("Горизонт. разрешение : %d px\n", bmpimageinfo.biXPelsPerMeter); printf("Вертикальное разрешение : %d px\n", bmpimageinfo.biYPelsPerMeter); printf("Кол. цветов. инд. в пал.: %d\n", bmpimageinfo.biClrUsed); printf("Кол. элементов палитры : %d\n\n", bmpimageinfo.biClrImportant); size = bmpimageinfo.biHeight * bmpimageinfo.biWidth; printf("size * sizeof(RGB) = %d\n", size * sizeof(RGB)); if ((pixels = malloc(size * sizeof(RGB))) == NULL){ printf("Malloc error\n"); } for (int i=0;i<size;i++) { pixels[i].r = 0; pixels[i].g = 0; pixels[i].b = 0; //pixels[i].a = 0; } // Считываем Цветовые индексы------------------------------------------------------------------------------------------------------------------- fseek(BmpImage, bmpheader.bfOffBits, 0); //смещение на bmpheader.bfOffBits = 54 символа (пропускаем данные о BmpHeader и BmpImageInfo) bytes2read = bmpimageinfo.biBitCount / 8; if (bmpimageinfo.biBitCount == 24){ printf("Считывание\n"); if(size > 0){ for (int i=0; i<size; i++) { fread(tmp, 1, bytes2read, BmpImage); MergeBytes(&(pixels[i]),tmp,bytes2read); } printf("Цветовые индексы считаны\n"); for(int i=0; i<size; i++){ fprintf(BmpCode,"%d %d %d\n",pixels[i].r, pixels[i].g, pixels[i].b); //printf("%d\n",i); //if((pixels[i].r==0)&&(pixels[i].g==0)&&(pixels[i].b==0)) { printf("%d\n",i); return 10;} //tmp[0] = pixels[i].r; //tmp[1] = pixels[i].g; //tmp[2] = pixels[i].b; //printf("%d %d %d\n",tmp[0],tmp[1],tmp[2]); //MergeBytes(&(outpixels[i]),tmp,bytes2read); fprintf(TgaCode, "%d %d %d\n", pixels[i].r, pixels[i].g, pixels[i].b); } } } putc(0,TgaImage); putc(0,TgaImage); putc(2,TgaImage); /* uncompressed RGB */ putc(0,TgaImage); putc(0,TgaImage); putc(0,TgaImage); putc(0,TgaImage); putc(0,TgaImage); putc(0,TgaImage); putc(0,TgaImage); /* X origin */ putc(0,TgaImage); putc(0,TgaImage); /* y origin */ putc((bmpimageinfo.biWidth & 0x00FF),TgaImage); putc((bmpimageinfo.biWidth & 0xFF00) / 256,TgaImage); putc((bmpimageinfo.biHeight & 0x00FF),TgaImage); putc((bmpimageinfo.biHeight & 0xFF00) / 256,TgaImage); putc(24,TgaImage); /* 24 bit bitmap */ putc(0,TgaImage); for (int i=0;i<size;i++) { putc(pixels[i].b,TgaImage); putc(pixels[i].g,TgaImage); putc(pixels[i].r,TgaImage); //putc(pixels[i].a,TgaImage); } fclose(BmpImage); fclose(BmpCode); fclose(TgaImage); fclose(TgaCode); return 0; } void MergeBytes(RGB *pixel,unsigned char *p,int bytes) { if (bytes == 4) { pixel->r = p[2]; pixel->g = p[1]; pixel->b = p[0]; //pixel->a = p[3]; } else if (bytes == 3) { pixel->r = p[2]; pixel->g = p[1]; pixel->b = p[0]; //pixel->a = 0; } else if (bytes == 2) { pixel->r = (p[1] & 0x7c) << 1; pixel->g = ((p[1] & 0x03) << 6) | ((p[0] & 0xe0) >> 2); pixel->b = (p[0] & 0x1f) << 3; //pixel->a = (p[1] & 0x80); } }
Решение задачи: «Конвертер из Bmp в Tga»
textual
Листинг программы
//.... int sz = (size*bytes2read)+56; //размер putc(sz,BmpImage); putc(0,BmpImage); putc(0,BmpImage); putc(0,BmpImage); //....
Объяснение кода листинга программы
- В первой строке кода объявлена переменная
sz
, которая вычисляет размер изображения в байтах, учитывая размер изображения и количество байтов, которые необходимо прочитать. - Затем происходит запись значения переменной
sz
в файлBmpImage
. - После этого записываются 4 дополнительных байта со значением 0 в файл
BmpImage
.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д