This code converts RAW10 image data to YUV420 format using C++. RAW10 format uses 5 bytes for every 4 pixels, while YUV420 uses 1.5 bytes per pixel, requiring a conversion for efficient storage and processing. This implementation provides a detailed explanation of the conversion process and offers a practical example for image processing.

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

struct Pixel {
    unsigned short R;
    unsigned short G;
    unsigned short B;
};

void raw10_to_pixel(const unsigned char* data, vector<Pixel>& pixels, int width, int height) {
    pixels.resize(width * height);
    int i = 0, j = 0;
    for (int pos = 0; pos < width * height * 5 / 4; pos += 5) {
        unsigned char b0 = data[pos];
        unsigned char b1 = data[pos + 1];
        unsigned char b2 = data[pos + 2];
        unsigned char b3 = data[pos + 3];
        unsigned char b4 = data[pos + 4];

        pixels[i * width + j].R = (b0 << 2) | (b1 >> 6);
        pixels[i * width + j].G = ((b1 & 0x3F) << 4) | (b2 >> 4);
        pixels[i * width + j].B = ((b2 & 0x0F) << 6) | (b3 >> 2);
        i += (j + 1) / width;
        j = (j + 1) % width;
        pixels[i * width + j].R = ((b3 & 0x03) << 8) | b4;
        i += (j + 1) / width;
        j = (j + 1) % width;
    }
}

void pixel_to_yuv420(const vector<Pixel>& pixels, unsigned char* yuv, int width, int height) {
    int y_size = width * height;
    int uv_size = y_size / 4;
    int i, j;

    // Y component
    for (i = 0; i < height; ++i) {
        for (j = 0; j < width; ++j) {
            int pos = i * width + j;
            yuv[pos] = (unsigned char)(0.299 * pixels[pos].R + 0.587 * pixels[pos].G + 0.114 * pixels[pos].B);
        }
    }

    // U and V components
    for (i = 0; i < height; i += 2) {
        for (j = 0; j < width; j += 2) {
            int pos = y_size + (i / 2) * (width / 2) + (j / 2);
            int pos1 = i * width + j;
            int pos2 = pos1 + 1;
            int pos3 = pos1 + width;
            int pos4 = pos3 + 1;
            yuv[pos] = (unsigned char)(-0.169 * pixels[pos1].R - 0.331 * pixels[pos1].G + 0.5 * pixels[pos1].B
                - 0.169 * pixels[pos2].R - 0.331 * pixels[pos2].G + 0.5 * pixels[pos2].B
                - 0.169 * pixels[pos3].R - 0.331 * pixels[pos3].G + 0.5 * pixels[pos3].B
                - 0.169 * pixels[pos4].R - 0.331 * pixels[pos4].G + 0.5 * pixels[pos4].B + 128);
            pos++;
            yuv[pos] = (unsigned char)(0.5 * pixels[pos1].R - 0.419 * pixels[pos1].G - 0.081 * pixels[pos1].B
                + 0.5 * pixels[pos2].R - 0.419 * pixels[pos2].G - 0.081 * pixels[pos2].B
                + 0.5 * pixels[pos3].R - 0.419 * pixels[pos3].G - 0.081 * pixels[pos3].B
                + 0.5 * pixels[pos4].R - 0.419 * pixels[pos4].G - 0.081 * pixels[pos4].B + 128);
        }
    }
}

int main(int argc, char** argv) {
    if (argc < 3) {
        cout << 'Usage: raw10_to_yuv420 input.raw output.yuv' << endl;
        return -1;
    }

    char* input_file = argv[1];
    char* output_file = argv[2];

    ifstream fin(input_file, ios::binary);
    if (!fin) {
        cout << 'Failed to open input file ' << input_file << endl;
        return -1;
    }

    fin.seekg(0, ios::end);
    int file_size = fin.tellg();
    fin.seekg(0, ios::beg);

    vector<unsigned char> data(file_size);
    fin.read((char*)data.data(), file_size);
    fin.close();

    int width = 640;
    int height = 480;
    vector<Pixel> pixels;
    raw10_to_pixel(data.data(), pixels, width, height);

    vector<unsigned char> yuv(width * height * 3 / 2);
    pixel_to_yuv420(pixels, yuv.data(), width, height);

    ofstream fout(output_file, ios::binary);
    if (!fout) {
        cout << 'Failed to open output file ' << output_file << endl;
        return -1;
    }
    fout.write((char*)yuv.data(), yuv.size());
    fout.close();

    return 0;
}

This code can be compiled and run with input and output file paths, for example:

$ ./raw10_to_yuv420 input.raw output.yuv

The 'input.raw' is the RAW10 format input file, and 'output.yuv' is the converted YUV420 format output file. This code utilizes C++11 standard 'vector' and 'fstream' libraries for efficient memory management and file operations.

C++ RAW10 to YUV420 Conversion Code: Efficient Image Format Transformation

原文地址: https://www.cveoy.top/t/topic/lC8W 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录