Конвертер из 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
.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д