La position actuelle:Accueil du site>Expérience II Yuv

Expérience II Yuv

2022-07-23 07:57:57Myster Kid

TGA to YUV Conversion de fichiers et instances

Un.、TGAStructure du fichier

NomOffset(Byte)Longueur(Byte)Description
ID Length01Longueur du champ d'information de l'image:Pour0Quand indique qu'il n'y a pas de champ d'information d'image
Colour Map Type11Type de palette: 0:Pas de palette 1:Il y a une palette de couleurs
Image Type Code21
Colour Map Offset32Index d'entrée de la table des couleurs
Colour Map Length52Tableau des couleurs totalentryNombre
Colour Map Depth71Chaque tableau de couleursentryNombre de chiffres: 16:Targa 16 24:Targa 24 32:Targa 32
X Origin82En bas à gauche de l'imagexCoordonnées
Y Origin102En bas à gauche de l'imageyCoordonnées
Width122Largeur de l'image
Height142Image haute
Bits Per Pixel161Nombre de bits occupés par pixel de l'image
Image Descriptor1710:Pas de données d'image

1:Pas de compression、 Image avec Palette
2:Pas de compression、 Sans Palette RGBImages
3: Image en noir et blanc non compressée
9: Image codée en cours de route avec Palette
10: Code de course RGBImages
11: Image compressée en noir et blanc
32:UtiliserHuffman、Delta、 Compression d'images codées avec Palette
33:UtiliserHuffman、Delta、 Compression d'images codées avec Palette ,4 Traitement de type Quadtree
Image Identification Field18Variable La longueur du champ est déterminée par ID LengthDésignation des champs. Généralement ignoré . Stocker plus d'informations si nécessaire , Peut être placé après les données d'image
Colour Map DataVariableVariableSiColour Map TypePour 0, Le champ n'existe pas . Chaque Palette entry La longueur peut être 4(RGBA)、3(RGB)Ou2Octets(No1OctetsGGBBBBB,No2OctetsARRRRRGG)
Image Data FieldVariableVariableAttention!,TGA Les fichiers sont stockés à petite échelle ,RGB Composant à B、G、RStockage séquentiel, Les données d'image sont stockées à partir du coin inférieur gauche

2.、Idées expérimentales

  1. PourTGA Le fichier crée la structure de l'en - tête du fichier , Lire le contenu de l'en - tête de fichier dans ;
  2. Selon les informations de l'en - tête du fichier ,Calculer le décalage, Localiser le point de départ des données d'image ;
  3. Lire les données d'image,C'est exact.RLE L'image compressée est décodée ,Et selonBits Per PixelLa différence entre,SéparationR、G、BComposante;
  4. Inverser l'image vers le haut et vers le bas ,Lire comme suit:RGBComment les fichiers sont stockés
  5. Utiliserrgb2yuvFonctions, C'est terminé. YUVConversion de fichiers

Trois、Code

declarations.h

#pragma once
#include <iostream>

typedef struct
{
    
    char  idLength = 0;         // Length of identification field (length = 1B, offset = 0B)
    char  colourMapType = 0;    // Colour map type (length = 1B, offset = 1B): 0 for no colour map included, 1 for colour map included
    char  imageTypeCode = 0;    // Image type code (length = 1B, offset = 2B): 2 for uncompressed & unmapped RGB image, 10 for run length encoded & unmapped RGB image

    /* Colour map specification (all set to 0 if colour map type is 0) */
    short colourMapOffset = 0;  // Colour map origin (length = 2B, offset = 3B): index of first colour map entry
    short colourMapLength = 0;  // Colour map length (length = 2B, offset = 5B): number of colour map entries
    char  colourMapDepth = 0;   // Colour map depth (length = 1B, offfset = 7B): number of bits in each entry. 16 for the Targa 16, 24 for the Targa 24, 32 for the Targa 32

    /* Image specification */
    short x_origin = 0;         // X coordinate of the lower left corner (length = 2B, offset = 8B)
    short y_origin = 0;         // Y coordinate of the lower left corner (length = 2B, offset = 10B)
    short width = 0;            // Width of image (length = 2B, offset = 12B)
    short height = 0;           // Height of image (length = 2B, offset = 14B)
    char  bitsPerPixel = 0;     // Number of bits in each pixel (length = 1B, offset = 16B)
    char  imageDescriptor = 0;  // Image descripter byte (length = 1B, offset = 17B)
} HEADER;

typedef struct
{
    
    unsigned char r, g, b, a;
} PIXEL;

void ReadTgaHeader(HEADER* tgaHdPtr, FILE* tgaPtr);
void ReadColourData(HEADER* tgaHdPtr, PIXEL* colourData, FILE* tgaPtr);
void Trans2RgbFormat(PIXEL* colourData, unsigned char* rgbBuff, HEADER* tgaHdPtr);
void rgb2yuv(FILE* yuvPtr, int width, int height, unsigned char* rgbBuff);


ReadTgaHeader.cpp

#include <iostream>
#include "declarations.h"
using namespace std;

void ReadTgaHeader(HEADER* tgaHdPtr, FILE* tgaPtr)
{
    
    /* Read data in TGA file header fields */
    tgaHdPtr->idLength = fgetc(tgaPtr);
    tgaHdPtr->colourMapType = fgetc(tgaPtr);
    tgaHdPtr->imageTypeCode = fgetc(tgaPtr);
    fread(&tgaHdPtr->colourMapOffset, 2, 1, tgaPtr);
    fread(&tgaHdPtr->colourMapLength, 2, 1, tgaPtr);
    tgaHdPtr->colourMapDepth = fgetc(tgaPtr);
    fread(&tgaHdPtr->x_origin, 2, 1, tgaPtr);
    fread(&tgaHdPtr->y_origin, 2, 1, tgaPtr);
    fread(&tgaHdPtr->width, 2, 1, tgaPtr);
    fread(&tgaHdPtr->height, 2, 1, tgaPtr);
    tgaHdPtr->bitsPerPixel = fgetc(tgaPtr);
    tgaHdPtr->imageDescriptor = fgetc(tgaPtr);

    /* Display header info on screen */
    cout << "\nTGA file header information:\n";
    printf("ID length: %d\n", tgaHdPtr->idLength);
    printf("Colour Map type: %d\n", tgaHdPtr->colourMapType);
    printf("Image type code: %d\n", tgaHdPtr->imageTypeCode);
    printf("Colour map offset: %d\n", tgaHdPtr->colourMapOffset);
    printf("Colour map length: %d\n", tgaHdPtr->colourMapLength);
    printf("Colour map depth: %d\n", tgaHdPtr->colourMapDepth);
    printf("X origin: %d\n", tgaHdPtr->x_origin);
    printf("Y origin: %d\n", tgaHdPtr->y_origin);
    printf("Width: %d\n", tgaHdPtr->width);
    printf("Height: %d\n", tgaHdPtr->height);
    printf("Image pixel size: %d\n", tgaHdPtr->bitsPerPixel);
    printf("Descriptor: %d\n\n", tgaHdPtr->imageDescriptor);
}


ReadColourData.cpp

#include "declarations.h"

void SeparateRGBA(PIXEL* pixel, unsigned char* rgba, int bytesPerPixel)
{
    
    switch (bytesPerPixel)
    {
    
    case 4:
        pixel->r = rgba[2];
        pixel->g = rgba[1];
        pixel->b = rgba[0];
        pixel->a = rgba[3];
        break;

    case 3:
        pixel->r = rgba[2];
        pixel->g = rgba[1];
        pixel->b = rgba[0];
        pixel->a = 255;
        break;

    case 2:
        pixel->r = (rgba[1] & 0b01111100) << 1;
        pixel->g = ((rgba[1] & 0b00000011) << 6) | ((rgba[0] & 0b11100000) >> 2);
        pixel->b = (rgba[0] & 0b00011111) << 3;
        pixel->a = (rgba[1] & 0b10000000);
        break;

    default:
        break;
    }
}

void ReadColourData(HEADER* tgaHdPtr, PIXEL* colourData, FILE* tgaPtr)
{
    
    int bytesPerPx = tgaHdPtr->bitsPerPixel / 8;    // Bytes per pixel
    unsigned char tempRGBA[4];  // Temporary buffer for the RGBA data of 1 pixel

    int n = 0;  // nth pixel
    while (n < tgaHdPtr->width * tgaHdPtr->height)
    {
    
        switch (tgaHdPtr->imageTypeCode)
        {
    
        /* Uncompressed, unmapped RGB image */
        case 2:
        {
    
            /* Read the colour data of 1 pixel */
            if (fread(tempRGBA, 1, bytesPerPx, tgaPtr) != bytesPerPx)
            {
    
                printf("ERROR!!! Unexpected end of file at pixel %d.\n", n);
                exit(-1);
            }

            SeparateRGBA(&(colourData[n]), tempRGBA, bytesPerPx);
            //printf("%-4x%-4x%-4x\n", colourData[n].b, colourData[n].g, colourData[n].r); // Check
            n++;
            break;
        }


        /* Run length encoded, unmapped RGB image */
        case 10:
        {
    
            unsigned char tempPktHeader;    // Temporary buffer for the packet header
            int pktHdID = 0;    // Determines if it's an RL packet or a raw packet 
            int pktRunSize = 0;    // Run size (the number of pixels in this packet)

            /* Read the packet header */
            if (fread(&tempPktHeader, 1, 1, tgaPtr) != 1)
            {
    
                printf("ERROR!!! Unexpected end of file at pixel %d.\n", n);
                exit(-1);
            }
            pktHdID = (tempPktHeader & 0x80) >> 7;
            pktRunSize = (tempPktHeader & 0x7F) + 1;

            /* Raw packet */
            if (pktHdID == 0)
            {
    
                for (int i = 0; i < pktRunSize; i++)
                {
    
                    if (fread(tempRGBA, 1, bytesPerPx, tgaPtr) != bytesPerPx)
                    {
    
                        printf("ERROR!!! Unexpected end of file at pixel %d.\n", n);
                        exit(-1);
                    }
                    SeparateRGBA(&(colourData[n]), tempRGBA, bytesPerPx);
                    n++;
                }
            }
            /* RL packet */
            else if (pktHdID == 1)
            {
    
                if (fread(tempRGBA, 1, bytesPerPx, tgaPtr) != bytesPerPx)
                {
    
                    printf("ERROR!!! Unexpected end of file at pixel %d.\n", n);
                    exit(-1);
                }
                for (int i = 0; i < pktRunSize; i++)
                {
    
                    SeparateRGBA(&(colourData[n]), tempRGBA, bytesPerPx);
                    n++;
                }
            }
            else
            {
    
                printf("ERROR!!! Unexpected invalid value of packet header ID.\n");
                exit(-1);
            }

            break;
        }


        default:
            break;
        }
    }
}


Trans2RgbFormat.cpp

#include "declarations.h"

void Trans2RgbFormat(PIXEL* colourData, unsigned char* rgbBuff, HEADER* tgaHdPtr)
{
    
    /* Write RGB data in .rgb format into rgbBuff */
    int w = tgaHdPtr->width;
    int h = tgaHdPtr->height;

    for (int i = 0; i < h; i++)   // i for row of image
    {
    
        for (int j = 0; j < w; j++) // j for column of image
        {
    
            int rgbPxNum = (h - 1 - i) * w + j; // Pixel number in RGB file
            int tgaPxNum = i * w + j;   // Pixel number in TGA file

            rgbBuff[3 * rgbPxNum + 2] = colourData[tgaPxNum].r;
            rgbBuff[3 * rgbPxNum + 1] = colourData[tgaPxNum].g;
            rgbBuff[3 * rgbPxNum] = colourData[tgaPxNum].b;
        }
    }
}

rgb2yuv.cpp

#include <iostream>
#include "declarations.h"

int rgb66[256], rgb129[256], rgb25[256];
int rgb38[256], rgb74[256], rgb112[256];
int rgb94[256], rgb18[256];

void rgbLookupTable()
{
    
	for (int i = 0; i < 256; i++)
	{
    
		rgb66[i] = 66 * i;
		rgb129[i] = 129 * i;
		rgb25[i] = 25 * i;
		rgb38[i] = 38 * i;
		rgb74[i] = 74 * i;
		rgb112[i] = 112 * i;
		rgb94[i] = 94 * i;
		rgb18[i] = 18 * i;
	}
}

void rgb2yuv(FILE* yuvPtr, int width, int height, unsigned char* rgbBuff)
{
    
	int pxCount = width * height;
	unsigned char* yBuff = new unsigned char[pxCount];		// Buffer for Y component
	unsigned char* uBuff = new unsigned char[pxCount / 4];	// Buffer for U component
	unsigned char* vBuff = new unsigned char[pxCount / 4];	// Buffer for V component
	unsigned char* uBuff444 = new unsigned char[pxCount];	// Buffer for U component in 4:4:4 format
	unsigned char* vBuff444 = new unsigned char[pxCount];	// Buffer for V component in 4:4:4 format

	// RGB to YUV (4:4:4)
	for (int i = 0; i < pxCount; i++)	// i for pixel number
	{
    
		unsigned char r = rgbBuff[3 * i + 2];	// R component of the ith pixel
		unsigned char g = rgbBuff[3 * i + 1];	// G component of the ith pixel
		unsigned char b = rgbBuff[3 * i];		// B component of the ith pixel
		rgbLookupTable();
		yBuff[i] = ((rgb66[r] + rgb129[g] + rgb25[b]) >> 8) + 16;
		uBuff444[i] = ((-rgb38[r] - rgb74[g] + rgb112[b]) >> 8) + 128;
		vBuff444[i] = ((rgb112[r] - rgb94[g] - rgb18[b]) >> 8) + 128;
	}

	// 4:4:4 to 4:2:0
	for (int i = 0; i < height; i += 2)
	{
    
		for (int j = 0; j < width; j += 2)
		{
    
			uBuff[i / 2 * width / 2 + j / 2] = uBuff444[i * width + j];
			vBuff[i / 2 * width / 2 + j / 2] = vBuff444[i * width + j];
		}
	}
	delete[]uBuff444;
	delete[]vBuff444;

	fwrite(yBuff, sizeof(unsigned char), pxCount, yuvPtr);
	fwrite(uBuff, sizeof(unsigned char), pxCount / 4, yuvPtr);
	fwrite(vBuff, sizeof(unsigned char), pxCount / 4, yuvPtr);
}



main.cpp

#include <iostream>
#include "declarations.h"
using namespace std;

int main(int argc, char* argv[])
{
    
    /* Declarations */
    FILE* tgaFilePtr, * yuvFilePtr;
    //FILE* rgbFilePtr;
    HEADER hd;  // Structure variable for TGA file header
    int w, h, pxCount;
    const char* tgaFileName = "snow32RLE.tga";
    const char* yuvFileName = "snow32RLE.yuv";
    //const char* rgbFileName = "snow32RLE.rgb";
    PIXEL* rgbaData = NULL;  // Entire RGBA data of TGA file; used for future funtions
    unsigned char* rgbBuffer = NULL; // RGB data of TGA file (in .rgb format); extracted from rgbaData; used for tga2yuv
    int offset = 0;

    /* Open the files */
    if (fopen_s(&tgaFilePtr, tgaFileName, "rb") == 0)
    {
    
        cout << "Successfully opened \"" << tgaFileName << "\".\n";
    }
    else
    {
    
        cout << "Failed to open \"" << tgaFileName << "\".\n";
        exit(-1);
    }
    if (fopen_s(&yuvFilePtr, yuvFileName, "wb") == 0)
    {
    
        cout << "Successfully opened \"" << yuvFileName << "\".\n";
    }
    else
    {
    
        cout << "Failed to open \"" << yuvFileName << "\".\n";
        exit(-1);
    }
    //if (fopen_s(&rgbFilePtr, rgbFileName, "wb") == 0)
    //{
    
    // cout << "Successfully opened \"" << rgbFileName << "\".\n";
    //}
    //else
    //{
    
    // cout << "Failed to open \"" << rgbFileName << "\".\n";
    // exit(-1);
    //}



    /* Read and display the header fields */
    ReadTgaHeader(&hd, tgaFilePtr);
    w = hd.height;
    h = hd.width;
    pxCount = w * h;

    /* Space allocation */
    rgbaData = new PIXEL[hd.width * hd.height];
    memset(rgbaData, 0, hd.height * hd.width);   // Initialisation
    rgbBuffer = new unsigned char[hd.width * hd.height * 3];
    memset(rgbBuffer, 0, hd.height * hd.width * 3);   // Initialisation

    /* Developed function check & invalidation check */
    if (hd.imageTypeCode != 2 && hd.imageTypeCode != 10)
    {
    
        cout << "Can only handle image type 2 (uncompressed, unmapped RGB) & image type 10 (run length encoded, unmapped RGB).\nOther options being developed.\n";
        exit(-1);
    }
    if (hd.bitsPerPixel != 16 && hd.bitsPerPixel != 24 && hd.bitsPerPixel != 32)
    {
    
        cout << "Invalid value of image pixel size!\nCan only handle pixel depths of 16, 24, and 32.\n";
        exit(-1);
    }
    if (hd.colourMapType != 0 && hd.colourMapType != 1)
    {
    
        cout << "Invalid value of colour map type!\nCan only handle colour map types of 0 and 1.\n";
        exit(-1);
    }

    /* Skip over unnecessary chunks */
    offset += hd.idLength;
    offset += hd.colourMapType * hd.colourMapLength * hd.colourMapDepth;
    cout << offset << " byte(s) skipped over.\n\n";
    fseek(tgaFilePtr, offset, SEEK_CUR);  // Skip 'offset' bytes from the end of header

    /* Read the image RGB (A, if exists) data */
    ReadColourData(&hd, rgbaData, tgaFilePtr);

    /* Transform .tga formatted RGB data into .rgb format */
    Trans2RgbFormat(rgbaData, rgbBuffer, &hd);
    //fwrite(rgbBuffer, 3, pxCount, rgbFilePtr);

    /* Transform RGB into YUV */
    rgb2yuv(yuvFilePtr, w, h, rgbBuffer);

    delete[]rgbaData;
    delete[]rgbBuffer;
    //fclose(rgbFilePtr);
    fclose(tgaFilePtr);
    fclose(yuvFilePtr);
}


Quatre、Résultats des opérations

Les images d'essai utilisées dans l'expérience sont les suivantes: “snow.jpeg”AdoptionAdobe PhotoshopDe la transformation“snow16.tga”“snow24.tga”Et“snow32.tga”.
L'image originale est la suivante: :
Insérer la description de l'image ici
ParRLECompriméTarga 32Exemple d'image,Le résultat est:

Insérer la description de l'image ici

Targa 32 (Image Type Code = 10) Résultats de sortie de la console de débogage

Utiliser l'image convertie avec YUV Viewer PlusOuvre.,Les résultats sont les suivants::
Insérer la description de l'image ici
Après conversionYUVImages(Image Type Code = 2)

Insérer la description de l'image ici

Après conversionYUVImages(Image Type Code = 10)

Mentions de copyright
Auteur de cet article [Myster Kid],Réimpression s’il vous plaît apporter le lien vers l’original, merci
https://fra.chowdera.com/2022/204/202207222136291414.html

Recommandé au hasard