Question

J'écris une visionneuse c ++ webcam en utilisant video4linux. J'ai besoin d'une sortie RGB24 (intercalés R8B8G8 ) pour l'affichage. Je suis en mesure d'obtenir une entrée vidéo pour presque toutes les webcam basse résolution, en utilisant YUYV, GREY8 ou RGB24. Mais je dois obtenir des commentaires aussi de webcams haute résolution, que l'utilisation MJPEG pour la compression quand élevée est nécessaire framerate.

Je suis en mesure d'obtenir le flux MJPEG en utilisant V4L2_PIX_FMT_MJPEG comme format de pixel, mais framebuffer reçu est comprimé.

Comment puis-je convertir rapidement à RGB24?

Puis-je utiliser libjpeg pour cela?

Était-ce utile?

La solution

La solution la plus rapide que j'ai trouvé est decode_jpeg_raw de mjpegtools qui décodage des données jpeg à YUV420 plane. Puis se fait par cette fonction de la conversion YUV420 à RGB24:

inline int clip(int value) {
    return (value > 255) ? 255 : (value < 0) ? 0 : value;
}

static void yuv420_to_rgb24(
/* luminance (source) */const uint8_t* const y
/* u chrominance (source) */, const uint8_t* u
/* v chrominance (source) */, const uint8_t* v
/* rgb interleaved (destination) */, uint8_t* const dst
/* jpeg size */, int const size
/* image width */, int const width) {

    const int lineSize = width * 3;

    uint8_t* r1 = dst;
    uint8_t* g1 = r1 + 1;
    uint8_t* b1 = r1 + 2;

    uint8_t* r2 = r1 + lineSize;
    uint8_t* g2 = r2 + 1;
    uint8_t* b2 = r2 + 2;

    const uint8_t* y1 = y;
    const uint8_t* y2 = y + width;

    uint8_t* const end = r1 + size;

    int c1 = 0;
    int c2 = 0;
    int e = 0;
    int d = 0;

    while (r1 != end) {
        uint8_t* const lineEnd = r2;
        /* line by line */
        while (r1 != lineEnd) {
            /* first pixel */
            c1 = *y1 - 16;
            c2 = *y2 - 16;
            d = *u - 128;
            e = *v - 128;

            *r1 = clip(c1 + ((454 * e) >> 8));
            *g1 = clip(c1 - ((88 * e + 183 * d) >> 8));
            *b1 = clip(c1 + ((359 * d) >> 8));

            *r2 = clip(c2 + ((454 * e) >> 8));
            *g2 = clip(c2 - ((88 * e + 183 * d) >> 8));
            *b2 = clip(c2 + ((359 * d) >> 8));

            r1 += 3;
            g1 += 3;
            b1 += 3;

            r2 += 3;
            g2 += 3;
            b2 += 3;

            ++y1;
            ++y2;

            /* second pixel */

            c1 = *y1 - 16;
            c2 = *y2 - 16;
            d = *u - 128;
            e = *v - 128;

            *r1 = clip(c1 + ((454 * e) >> 8));
            *g1 = clip(c1 - ((88 * e + 183 * d) >> 8));
            *b1 = clip(c1 + ((359 * d) >> 8));

            *r2 = clip(c2 + ((454 * e) >> 8));
            *g2 = clip(c2 - ((88 * e + 183 * d) >> 8));
            *b2 = clip(c2 + ((359 * d) >> 8));

            r1 += 3;
            g1 += 3;
            b1 += 3;

            r2 += 3;
            g2 += 3;
            b2 += 3;

            ++y1;
            ++y2;

            ++u;
            ++v;
        }
        r1 += lineSize;
        g1 += lineSize;
        b1 += lineSize;
        r2 += lineSize;
        g2 += lineSize;
        b2 += lineSize;
        y1 += width;
        y2 += width;
    }
}

Autres conseils

Oui, vous pouvez utiliser libjpeg pour cela, mais en général la sortie de libjpeg est en YUV420 ou YUV422. Vous pourriez plutôt utiliser ce code: http://mxhaard.free.fr/ spca50x / Télécharger / gspcav1-20071224.tar.gz (chèque de source de décodeur, il y a un petit décodeur jpeg qui fonctionne bien et traite de la conversion des couleurs directement de sorte que la sortie est en RGB888)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top