usage:

unsigned char rgb[1920*1080*3];
// covert yuv420sp after resizing to bmp
vuy420sp_to_rgb(buf, buf+offsetH*offsetV, rgb, offsetH, offsetV);
// save as bmp file
bmp_write(rgb, offsetH, offsetV, "/tmp/img.bmp");

#ifndef bmp_h
#define bmp_h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void vuy420sp_to_rgb(const unsigned char* y, const unsigned char* uv, unsigned char* rgb, unsigned int width, unsigned int height)
{
    unsigned int halfwidth = width >> 1;
    int yy, uu, vv, ug_plus_vg, ub, vr;
    int r, g, b;
    unsigned int i, j;
    for (i = 0; i < height; ++i)
    {
        for (j = 0; j < halfwidth; ++j)
        {
            yy = y[0] << 8;
            vv = *(uv++) - 128;
            uu = *(uv++) - 128;
            ug_plus_vg = uu * 88 + vv * 183;
            ub = uu * 454;
            vr = vv * 359;
            r = (yy + vr) >> 8;
            g = (yy - ug_plus_vg) >> 8;
            b = (yy + ub) >> 8;
            rgb[0] = r < 0 ? 0 : (r > 255 ? 255 : (unsigned char)r);
            rgb[1] = g < 0 ? 0 : (g > 255 ? 255 : (unsigned char)g);
            rgb[2] = b < 0 ? 0 : (b > 255 ? 255 : (unsigned char)b);
            yy = y[1] << 8;
            r = (yy + vr) >> 8;
            g = (yy - ug_plus_vg) >> 8;
            b = (yy + ub) >> 8;
            rgb[3] = r < 0 ? 0 : (r > 255 ? 255 : (unsigned char)r);
            rgb[4] = g < 0 ? 0 : (g > 255 ? 255 : (unsigned char)g);
            rgb[5] = b < 0 ? 0 : (b > 255 ? 255 : (unsigned char)b);
            y += 2;
            rgb += 6;
        }
        if ((i & 1) == 0)
        {
            uv -= halfwidth * 2;
        }
    }
}

static inline void yuv420p_to_rgb_c(const unsigned char* y, const unsigned char* u, const unsigned char* v, unsigned char* rgb, unsigned int width, unsigned int height)
{
    unsigned int halfwidth = width >> 1;
    int yy, uu, vv, ug_plus_vg, ub, vr;
    int r, g, b;
    unsigned int i, j;
    for (i = 0; i < height; ++i)
    {
        for (j = 0; j < halfwidth; ++j)
        {
            yy = y[0] << 8;
            uu = *(u++) - 128;
            vv = *(v++) - 128;
            ug_plus_vg = uu * 88 + vv * 183;
            ub = uu * 454;
            vr = vv * 359;
            r = (yy + vr) >> 8;
            g = (yy - ug_plus_vg) >> 8;
            b = (yy + ub) >> 8;
            rgb[0] = r < 0 ? 0 : (r > 255 ? 255 : (unsigned char)r);
            rgb[1] = g < 0 ? 0 : (g > 255 ? 255 : (unsigned char)g);
            rgb[2] = b < 0 ? 0 : (b > 255 ? 255 : (unsigned char)b);
            yy = y[1] << 8;
            r = (yy + vr) >> 8;
            g = (yy - ug_plus_vg) >> 8;
            b = (yy + ub) >> 8;
            rgb[3] = r < 0 ? 0 : (r > 255 ? 255 : (unsigned char)r);
            rgb[4] = g < 0 ? 0 : (g > 255 ? 255 : (unsigned char)g);
            rgb[5] = b < 0 ? 0 : (b > 255 ? 255 : (unsigned char)b);
            y += 2;
            rgb += 6;
        }
        if ((i & 1) == 0)
        {
            u -= halfwidth;
            v -= halfwidth;
        }
    }
}

static void vuy422_to_rgb(const unsigned char* yuv, unsigned char* rgb, unsigned int width, unsigned int height)
{
    int yy, uu, vv, ug_plus_vg, ub, vr;
    int r, g, b;
    unsigned int total = width * height;
    total /= 2;
    while (total--)
    {
        yy = yuv[1] << 8;
        uu = yuv[0] - 128;
        vv = yuv[2] - 128;
        ug_plus_vg = uu * 88 + vv * 183;
        ub = uu * 454;
        vr = vv * 359;
        r = (yy + vr) >> 8;
        g = (yy - ug_plus_vg) >> 8;
        b = (yy + ub) >> 8;
        rgb[0] = r < 0 ? 0 : (r > 255 ? 255 : (unsigned char)r);
        rgb[1] = g < 0 ? 0 : (g > 255 ? 255 : (unsigned char)g);
        rgb[2] = b < 0 ? 0 : (b > 255 ? 255 : (unsigned char)b);
        yy = yuv[3] << 8;
        r = (yy + vr) >> 8;
        g = (yy - ug_plus_vg) >> 8;
        b = (yy + ub) >> 8;
        rgb[3] = r < 0 ? 0 : (r > 255 ? 255 : (unsigned char)r);
        rgb[4] = g < 0 ? 0 : (g > 255 ? 255 : (unsigned char)g);
        rgb[5] = b < 0 ? 0 : (b > 255 ? 255 : (unsigned char)b);
        yuv += 4;
        rgb += 6;
    }
}

// Ecrit un short dans un fichier
static void putshort(FILE *file, int i)
{
    int c, c1;

    c = ((unsigned int ) i) & 0xff;
    c1 = (((unsigned int) i) >> 8) & 0xff;
    putc(c, file);
    putc(c1, file);
}


// Ecrit un int dans un fichier
static void putint(FILE *file, int i)
{
    int c, c1, c2, c3;
    c  = ((unsigned int ) i)      & 0xff;
    c1 = (((unsigned int) i) >> 8)  & 0xff;
    c2 = (((unsigned int) i) >> 16) & 0xff;
    c3 = (((unsigned int) i) >> 24) & 0xff;

    putc(c, file);
    putc(c1, file);
    putc(c2, file);
    putc(c3, file);
}

// write bmp 24 bits in file
static void bmp_write24(FILE *file, unsigned char *pic24, int w, int h)
{
    int   i, j, pad_bytes;
    unsigned char *pp;

    pad_bytes = (4 - ((w * 3) % 4)) & 0x03; // # of pad bytes to write at EOscanline

    for (i = h - 1; i >= 0; i--)
    {
        pp = pic24 + (i * w * 3);
        fwrite(pp, 3, w, file);
        if( pad_bytes )
            fwrite("\0\0\0", 1, pad_bytes, file);
    }
}

// Ecriture d'un buffer image dans un fichier au format BMP
static int bmp_write(unsigned char *pic24,   // buffer image
                     int   w,  int h,           // resolution de l'image
                     char *filename)
{
    int i, nbits = 24, bperlin, cmaplen = 0;
    FILE *file;
    printf("write bmp %s, %dx%d\n", filename, w, h);
    file = fopen(filename, "wb");
    if( file == NULL )
        return -1;
    // nombre d'octets ecrits par ligne
    bperlin = ((w * nbits + 31) / 32) * 4;

    // BMP file magic number
    putc('B', file);
    putc('M', file);

    // calcul de la taille du fichier et ecriture
    i = 14 +        // taille du header bitmap
        40 +              // taille du header d'info
        bperlin * h;  // taille du buffer image

    putint(file, i);
    putshort(file, 0);        // reserve
    putshort(file, 0);        // reserve
    putint(file, 14 + 40);
    putint(file, 40);         // taille du header bitmap
    putint(file, w);          // largeur
    putint(file, h);          // hauteur
    putshort(file, 1);        // plans: doit etre 1'
    putshort(file, nbits);    // nombre de bits/pixel = 24
    putint(file, 0);          // Compression:  BI_RGB
    putint(file, bperlin * h); // taille du buffer image
    putint(file, 75 * 39);
    putint(file, 75 * 39);
    putint(file, 0);                      // nombre de couleurs used dans la colormap
    putint(file, 0);

    // Ecriture du buffer image dans un fichier
    bmp_write24(file, pic24, w, h);
    fclose(file);
    return 0;
}
#endif
arrow
arrow
    全站熱搜

    Person 發表在 痞客邦 留言(0) 人氣()