TGA格式转YUV

TGA扩展文件结构由五部分组成:文件头、图像/颜色表数据、开发者自定义区域、扩展区域和文件尾。TGA格式转YUV_第1张图片
由头文件中的二三字节00 02可以看出是未压缩的真彩色图像,00 00 00 00 18说明一个像素是24位,所以与RGB的格式非常相似,借鉴了之前RGB转YUV的方法。
代码如下:

#include
#include
const int width = 256;
const int height = 256;
int main(int argc,char *argv[])
{
    unsigned char* buffer_tga = new unsigned char[3 * width * height + 18];
    unsigned char* buffer_rgb = new unsigned char[ 3 * width * height];
    unsigned char* buffer_y = new unsigned char[width * height];
    unsigned char* buffer_u = new unsigned char[width * height / 4];
    unsigned char* buffer_v = new unsigned char[width * height / 4];
    FILE* rgb=NULL;
    FILE* yuv=NULL;
    fopen_s(&rgb,argv[1], "rb");
    if (rgb == NULL)
        printf("cannot find rgb file\n");
    fread(buffer_tga, sizeof(unsigned char), 3 * width * height+18,rgb);
    for (int i = 0; i < 3 * width * height; i++)
    {
        buffer_rgb[i] = buffer_tga[i + 18];
    }
    fopen_s(&yuv,argv[2], "wb+");
    if (yuv == NULL)
        printf("cannot find yuv file\n");
    for (int i = 0; i < width * height; i++)
    {
        buffer_y[i] = 0.299 * buffer_rgb[3 * i + 2] + 0.587 * buffer_rgb[3 * i + 1] + 0.114 * buffer_rgb[3 * i];
        if (buffer_y[i] > 235)
            buffer_y[i] = 235;
        else if (buffer_y[i] < 16)
            buffer_y[i] = 16;
    }//y
    int u = 0 , v = 0;
    for (int i = 0; i < height ; i++)
        for (int j = 0; j < width; j++)
        {
            if (i % 2 == 0 && j % 2 == 0)
            {
                buffer_u[u] = -0.1684 * ( buffer_rgb[3 * (i * width + j) + 2] + buffer_rgb[3 * (i * width + j + 1) + 2] + buffer_rgb[3 * (i * width + j + width) + 2] + buffer_rgb[3 * (i * width + j + width + 1) + 2])/4
                    - 0.3316 * (buffer_rgb[3 * (i * width + j) + 1] + buffer_rgb[3 * (i * width + j + 1) + 1] + buffer_rgb[3 * (i * width + j + width) + 1] + buffer_rgb[3 * (i * width + j + width + 1) + 1]) / 4
                    + 0.5 * (buffer_rgb[3 * (i * width + j)] + buffer_rgb[3 * (i * width + j + 1)] + buffer_rgb[3 * (i * width + j + width)] + buffer_rgb[3 * (i * width + j + width + 1)]) / 4 +128;
                if (buffer_u[u] > 240)
                    buffer_u[u] = 240;
                else if (buffer_u[u] < 16)
                    buffer_u[u] = 16;
                u++;
                buffer_v[v] = 0.5 * (buffer_rgb[3 * (i * width + j) + 2] + buffer_rgb[3 * (i * width + j + 1) + 2] + buffer_rgb[3 * (i * width + j + width) + 2] + buffer_rgb[3 * (i * width + j + width + 1) + 2]) / 4
                    - 0.4187 * (buffer_rgb[3 * (i * width + j) + 1] + buffer_rgb[3 * (i * width + j + 1) + 1] + buffer_rgb[3 * (i * width + j + width) + 1] + buffer_rgb[3 * (i * width + j + width + 1) + 1]) / 4
                    - 0.0813 * (buffer_rgb[3 * (i * width + j)] + buffer_rgb[3 * (i * width + j + 1)] + buffer_rgb[3 * (i * width + j + width)] + buffer_rgb[3 * (i * width + j + width + 1)]) / 4 + 128;
                if (buffer_v[v] > 240)
                    buffer_v[v] = 240;
                else if (buffer_v[v] < 16)
                    buffer_v[v] = 16;
                v++;
            }
        }//u和v
    fwrite(buffer_y, sizeof(unsigned char), width * height, yuv);
    fwrite(buffer_u, sizeof(unsigned char), width * height / 4, yuv);
    fwrite(buffer_v, sizeof(unsigned char), width * height / 4, yuv); 
    if (buffer_tga != NULL)
        free(buffer_tga);
    if (buffer_rgb != NULL)
        free(buffer_rgb);
    if (buffer_y != NULL)
        free(buffer_y);
    if (buffer_u != NULL)
        free(buffer_u);
    if (buffer_v != NULL)
        free(buffer_v);
    fclose(rgb);
    fclose(yuv);
    return 0;
}

argv设置为 test.tga test.yuv 256 256

结果图:
TGA格式转YUV_第2张图片
看似没有什么问题,可经过查资料发现TGA格式的像素是从左下角为原点开始排练,可在实验中的TGA明显是从左上角开始的,并且除了头文件,其他内容与RGB文件完全一致。这一情况显然与实际不符。这一疑点仍在研究中。
ps:这个TGA文件是原BMP文件经过ACDsee20另存为得到的。

你可能感兴趣的:(TGA格式转YUV)