Конвертер из 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); 
//....

Объяснение кода листинга программы

  1. В первой строке кода объявлена переменная sz, которая вычисляет размер изображения в байтах, учитывая размер изображения и количество байтов, которые необходимо прочитать.
  2. Затем происходит запись значения переменной sz в файл BmpImage.
  3. После этого записываются 4 дополнительных байта со значением 0 в файл BmpImage.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

6   голосов , оценка 4.333 из 5