상세 컨텐츠

본문 제목

[정보] TGA 파일 포맷[RLE 포함] (bmp로 풀어서 로드)

프로그래밍 관련/게임프로그래밍

by AlrepondTech 2020. 9. 19. 03:35

본문

반응형

 

 

 

 

=================================

=================================

=================================

 

 

 

 



tga2bmp(1).rar
2.87MB

 

기본 헤더

typedef struct tgaTARGAFILEHEADER {
    unsigned char imageIDLength; // 식별 필드의 길이    // 0이면 식별 필드가 포함되지 않은 것이다.         
    unsigned char colorMapType; // 색상 맵의 종류 : 항상 0임        
    unsigned char imageTypeCode; //  2  이면 압축되지 않은 RGB
                                 //  3  이면 압축되지 않은 그레이 스케일       
    short int colorMapOrigin; // 색상 맵의 시작 위치( 하위-상위) ; 항상 0임   
    short int colorMapLength; // 색상 맵의 길이 ( 하위 - 상위) : 항상 0임     
    unsigned char colorMapEntrySize; // 색상 맵의 항목 크기( 하위 - 상위) : 항상 0임       
    short int imageXOrigin; // 이미지 우측 하단 x 좌표 (하위 - 상위) : 항상 0임      
    short int imageYOrigin; // 이미지의 좌측 하단 x좌표 (하위-상위) : 항상 0임      
    short int imageWidth; //  이미지의 픽셀 단위 너비( 하위 - 상위)            
    short int imageHeight; //   이미지의 픽셀 단위 높이( 하위 - 상위)           
    unsigned char bitCount; // 색상 비트 수 : 16, 24, 32             
    unsigned char imageDescriptor; // 24비트 : 0x00   ;  32비트 : 0x08

}
TARGAFILEHEADER;

 

 

 

=================================

=================================

=================================

 

 

 

 

기본 구조는  bmp 구조랑 같습니다

-

------------

-     헤더    -

------------

-    이미지  -

-               -

------------

 

읽어 들이기~  거짐 bmp랑 같습니다 ~

unsigned char ucharBad = 0; // 임시용 unsigned char data 필요없는 정보 넘기기용
short int sintBad = 0; // 임시용 short int data 필요없는 정보 넘기기용

// ucharBad,sintBad 는 저는 불필요해서 뛰어서 넘어 갔습니다. 필요하신분은 읽어서 사용~

TARGAFILEHEADER temp_TgaFileHeader; // 구조체로 저장이 안되어 있기때문에 일일이 읽어야한다(제 생각^^;)

//구조 사이즈로 읽을라 했으나 크기가 않맞아서 이렇게 일일이 로드해야 하더라구요 ~

file.Read( & ucharBad, sizeof(unsigned char));
file.Read( & ucharBad, sizeof(unsigned char));
file.Read( & temp_TgaFileHeader.imageTypeCode, sizeof(unsigned char));

file.Read( & sintBad, sizeof(short int));
file.Read( & sintBad, sizeof(short int));
file.Read( & ucharBad, sizeof(unsigned char));
file.Read( & sintBad, sizeof(short int));
file.Read( & sintBad, sizeof(short int));
file.Read( & temp_TgaFileHeader.imageWidth, sizeof(short int));
file.Read( & temp_TgaFileHeader.imageHeight, sizeof(short int));
file.Read( & temp_TgaFileHeader.bitCount, sizeof(unsigned char));

file.Read( & ucharBad, sizeof(unsigned char));

// colorMode -> 3 = BGR, 4 = BGRA
colorMode = temp_TgaFileHeader.bitCount / 8; //32비트는 4, 24비트는 3이됩니다

//미리 3을 곱하고 4의 배수를 구함으로서 최소의 4의 배수를 구한다. 가로가 657이면 657*3의 4의배수니 1972가 나온다.
tmpWidthBytes = (temp_TgaFileHeader.imageWidth) * colorMode; // 필요한 줄의 바이트 수....
tmpWidthBytes = (tmpWidthBytes + 3) & ~3; // 4의 배수화 시킴.

if (temp_TgaFileHeader.bitCount == 24) {

    int imgsize = temp_TgaFileHeader.imageWidth * colorMode;
    imgsize = (imgsize + colorMode) & ~colorMode;
    imageSize = imgsize * temp_TgaFileHeader.imageHeight;

} else if (temp_TgaFileHeader.bitCount == 32)
    imageSize = (temp_TgaFileHeader.imageWidth * 
    temp_TgaFileHeader.imageHeight * colorMode);

int bitsize = 0;

int nSize = sizeof(BITMAPINFOHEADER) +
    (4 * (temp_TgaFileHeader.imageWidth * 
    temp_TgaFileHeader.imageHeight)) + sizeof(RGBQUAD);
    

 

 

 

 

=================================

=================================

=================================

 

 

 

 

반응형

 

 

728x90

 

 

 

//tga 헤더 내용을 Bmp에 맡게 변경해 줍니다

 

temp_BmpFileHeader.bfType = 0x4d42;
  temp_BmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER)+nSize;
  temp_BmpFileHeader.bfReserved1 =0;
  temp_BmpFileHeader.bfReserved2 =0;

  // -2를 하지 않으면 에러 남  // bfOffBits 를 설정해주어서 얼마만큼이 bitmap인지 알려준다.
  temp_BmpFileHeader.bfOffBits   = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+  sizeof(RGBQUAD); 
          

  temp_BmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
  temp_BmpInfoHeader.biWidth  = temp_TgaFileHeader.imageWidth;
  temp_BmpInfoHeader.biHeight = temp_TgaFileHeader.imageHeight;
  temp_BmpInfoHeader.biPlanes = 1;
  temp_BmpInfoHeader.biBitCount = temp_TgaFileHeader.bitCount;
  temp_BmpInfoHeader.biCompression = 0;
  temp_BmpInfoHeader.biSizeImage = temp_TgaFileHeader.imageWidth*temp_TgaFileHeader.imageHeight;
  temp_BmpInfoHeader.biXPelsPerMeter = 0;
  temp_BmpInfoHeader.biYPelsPerMeter = 0;
  temp_BmpInfoHeader.biClrUsed = 0;
  temp_BmpInfoHeader.biClrImportant = 0;

  temp_RGBQUAD.rgbBlue =0;
  temp_RGBQUAD.rgbGreen =0;
  temp_RGBQUAD.rgbRed   =0;
  temp_RGBQUAD.rgbReserved =0;

  m_TgaImgSize = imageSize; //타가의 이미지 사이즈를 헤더타가이미지 사이즈에 저장.
  m_pImageTga = new BYTE[imageSize];
  tmpImg      = new BYTE[imageSize];

  

  BYTE* tmpImg2 ; 
  BYTE* tmpM_pImageTga ; //멤버헤더타가의 임시 포인터 
 

   tmpImg2 = tmpImg;
  tmpM_pImageTga = m_pImageTga;

  
  int headSize = sizeof(TARGAFILEHEADER);
  
  file.Read(m_pImageTga,imageSize);

  
  int nTargetWidth = (tmpWidthBytes-(temp_BmpInfoHeader.biWidth*colorMode)) ;
  

  //-----------------------------------------------------
  //TGA RLE 압축!!  tga의 RLE 압축 이미지를 로드 합니다
 //압축 포인트

 //다른점일때는 0 ~ 127 까지의 숫자를 사용합니다.
 //같은점일때에는 128+0 ~ 128+127 의 숫자를 사용합니다. 
 //width로 하나씩 Height와 비교하면서 그려나가야 한다.
 //--------------------------------------------------------

  

/*

128+0 ~ 128+127 같은 점일때

----------------------

| 점의정보 | 점하나     |

----------------------

 

0~127 다른 점일때

--------------------------------------

| 점의정보 | 점의 정보갯수만큼 점들     |

--------------------------------------

*/

//예로 들어 설명하겠습니다
//처음 바이트를 읽을때 값이 56 이라면 다른점의 0~127의 안에 들어오니깐
//56개의 다른점을 찍습니다...그리고 다음 점의 정보를 읽습니다
//다음값의 정보가 200이라면 128+0 ~ 128+127 의 범위안에 들어 옵니다
//여기서 200-127의 즉 73개만큼 다른 점을 찍는다고 보시면 됩니다.
//이런방식으로 계속 읽어나가 width와 height를 비교하고 압축을 풀면 됩니다

 


int pNum;
int imgWidth = 0;
int imgHeight = 0;

if (temp_TgaFileHeader.imageTypeCode == 10) // imageTypeCode 코드가 10이라면 압축된 코드 입니다
    while (temp_TgaFileHeader.imageHeight > imgHeight) {
        pNum = m_pImageTga[0];

        if (pNum > 127) //(128+0 ~ 128+127 ) 범위의 값

            for (int i = 0; i < pNum - 127; i++) // 127이 넘으면 같은 점이기에 여기서 127을 빼서 같은 점의 갯수를 구하고 그만큼 루프를 돌립니다.

        {
            for (int k = 1; k < colorMode + 1; k++) //처음 점의 정보(같은점,다른점)를 넘기기 위해 '1'부터 시작
                //여기서는 한점으로 여러번 점의 정보 갯수만큼 채웁니다( 같은 점이기에)
                tmpImg[k - 1] = m_pImageTga[k];
        }
        tmpImg += colorMode;
        imgWidth++;

    }
m_pImageTga = m_pImageTga + colorMode + 1;

}

//0~127 사이의 범위값 여기서는 점정보 만큼 점의 갯수를 읽고 넘겨줍니다 
else {
    m_pImageTga++;
    for (int i = 0; i <= pNum; i++) { //127까지니깐 i<=pNum크기만큼 끈어주면 된다. 127포함까지
        for (int k = 0; k < colorMode; k++) {
            tmpImg[k] = m_pImageTga[k]; //점의 정보만큼 넘겨줍니다
        }
        m_pImageTga += colorMode;
        tmpImg += colorMode;
        imgWidth++;

    }

}

if (imgWidth == temp_TgaFileHeader.imageWidth) {
    if (temp_BmpInfoHeader.biBitCount == 24) //24비트일떄만 해준다.
        tmpImg = tmpImg + nTargetWidth; //24비트일때는 4자리를 못채우므로 width길이를 맞추어 줍니다
    imgWidth = 0;
    imgHeight++;
}
}


  //------------------------------------------------------------------------------
  //TGA 보통 그림 풀기
  //그대로 그림의 리소스를 받아 옮겨주기만 하면 됩니다
  //
  //-------------------------------------------------------------------------------
  

 //psj 고쳐야 할곳
  if(temp_TgaFileHeader.imageTypeCode != 10) // 압축이 아닐때
  for(int i=0;i<temp_BmpInfoHeader.biHeight;i++)
  {
  
   for(int k=0;k<temp_BmpInfoHeader.biWidth;k++)
   {
   
    // rgba,argb <=>BGRA 
  
    //TGA: 0-blue , 1-green, 2-red , 3-alpha
    //BMP: 0-blue , 1-green, 2-red , 3-alpha

      if(temp_TgaFileHeader.bitCount==32)
      {
       tmpImg[0]=m_pImageTga[0]; //a
       tmpImg[1]=m_pImageTga[1]; //r
       tmpImg[2]=m_pImageTga[2]; //g
       tmpImg[3]=m_pImageTga[3]; //b
      }
    
      if(temp_TgaFileHeader.bitCount==24)
      {
       tmpImg[0]=m_pImageTga[0]; //r
       tmpImg[1]=m_pImageTga[1]; //a   
       tmpImg[2]=m_pImageTga[2]; //b
      }
    tmpImg     +=colorMode;
    m_pImageTga+=colorMode;
    
   
   }
    if(temp_BmpInfoHeader.biBitCount==24) //24비트일떄만 해준다.
    tmpImg=tmpImg+nTargetWidth;           //24비트일때는 4자리를 못채우므로 width길이를 맞추어 줍니다

  }
   
  tmpImg= tmpImg2;

 

 

=================================

=================================

=================================

 

 

 

// 오늘도 오크 코딩~~~~

// 이 tga로딩을 리소스를 빼서 그대로 이용해두 되고 bmp로 로드해서 mfc에 뿌려 주어두 되고 여러가지로 응용~

// 좋은 방법 있으신 분들 언제나 충언 해주세요 +.+ (오크 코딩 이해해 주세요 ㅠㅠ)

 

 

=================================

=================================

=================================

 

 

 

 

반응형


관련글 더보기

댓글 영역