Exemples ou tutoriels d'utilisation de libjpeg-TurboJPEG de turbo

les instructions pour libjpeg-turbo ici décrit ainsi L'API TurboJPEG:"cette API enroule libjpeg-turbo et fournit une interface facile à utiliser pour compresser et décompresser les images JPEG en mémoire". Super, mais y a-t-il de bons exemples d'utilisation de cette API? Je cherche juste à décompresser un jpeg assez vanille en mémoire.

j'ai trouvé quelques morceaux tels que https://github.com/erlyvideo/jpeg/blob/master/c_src/jpeg.c/" class="blnk">c, qui semble être en utilisant L'API TurboJPEG, mais y a-t-il d'autres exemples solides/variés?

la source de libjpeg-turbo est bien documentée, donc cela aide.

22
demandé sur Theolodis 2012-02-01 15:01:47

4 réponses

Ok, je sais que vous avez déjà résolu votre problème, mais comme certaines personnes, tout comme moi, pourraient être à la recherche d'un exemple simple, je vais partager ce que j'ai créé. Il s'agit d'un exemple de compression et de décompression d'une image RVB. Sinon, je pense que la documentation API de TurboJPEG est assez facile à comprendre!

Compression:

#include <turbojpeg.h>

const int JPEG_QUALITY = 75;
const int COLOR_COMPONENTS = 3;
int _width = 1920;
int _height = 1080;
long unsigned int _jpegSize = 0;
unsigned char* _compressedImage = NULL; //!< Memory is allocated by tjCompress2 if _jpegSize == 0
unsigned char buffer[_width*_height*COLOR_COMPONENTS]; //!< Contains the uncompressed image

tjhandle _jpegCompressor = tjInitCompress();

tjCompress2(_jpegCompressor, buffer, _width, 0, _height, TJPF_RGB,
          &_compressedImage, &_jpegSize, TJSAMP_444, JPEG_QUALITY,
          TJFLAG_FASTDCT);

tjDestroy(_jpegCompressor);

//to free the memory allocated by TurboJPEG (either by tjAlloc(), 
//or by the Compress/Decompress) after you are done working on it:
tjFree(&_compressedImage);

après cela, vous avez l'image compressée dans _compressedImage. Pour décompresser vous devez faire le suivantes:

Décompression:

#include <turbojpeg.h>

long unsigned int _jpegSize; //!< _jpegSize from above
unsigned char* _compressedImage; //!< _compressedImage from above

int jpegSubsamp, width, height;
unsigned char buffer[width*height*COLOR_COMPONENTS]; //!< will contain the decompressed image

tjhandle _jpegDecompressor = tjInitDecompress();

tjDecompressHeader2(_jpegDecompressor, _compressedImage, _jpegSize, &width, &height, &jpegSubsamp);

tjDecompress2(_jpegDecompressor, _compressedImage, _jpegSize, buffer, width, 0/*pitch*/, height, TJPF_RGB, TJFLAG_FASTDCT);

tjDestroy(_jpegDecompressor);

Quelques pensées éparses:

je viens de revenir sur ce que je suis en train d'écrire ma thèse de baccalauréat, et j'ai remarqué que si vous exécutez la compression dans une boucle, il est préférable de stocker la plus grande taille du tampon JPEG pour ne pas avoir à allouer un nouveau à chaque tour. En gros, au lieu de faire:

long unsigned int _jpegSize = 0;

tjCompress2(_jpegCompressor, buffer, _width, 0, _height, TJPF_RGB,
          &_compressedImage, &_jpegSize, TJSAMP_444, JPEG_QUALITY,
          TJFLAG_FASTDCT);

nous ajouterions une variable objet, en maintenant la taille de l'attribut de mémoire long unsigned int _jpegBufferSize = 0; et avant chaque round de compression, nous ramenions le jpegSize à cette valeur:

long unsigned int jpegSize = _jpegBufferSize;

tjCompress2(_jpegCompressor, buffer, _width, 0, _height, TJPF_RGB,
          &_compressedImage, &jpegSize, TJSAMP_444, JPEG_QUALITY,
          TJFLAG_FASTDCT);

_jpegBufferSize = _jpegBufferSize >= jpegSize? _jpegBufferSize : jpegSize;

après la compression, on comparera la taille de la mémoire avec la taille réelle jpegSize et on la réglera sur la taille jpegSize si elle est supérieure à la taille de la mémoire précédente.

50
répondu Theolodis 2018-03-04 15:25:34

a la fin j'ai utilisé une combinaison de code aléatoire trouvé sur internet (par exemple https://github.com/erlyvideo/jpeg/blob/master/c_src/jpeg.c) et le .c et les fichiers d'en-tête pour libjeg-turbo, qui sont bien documentés. L'API officielle est également une bonne source d'information.

4
répondu occulus 2013-09-11 12:02:42

j'ai fini par utiliser le code ci-dessous comme exemple de travail pour l'encodage JPEG et le décodage. Le meilleur exemple que je puisse trouver, c'est l'Auto-contenu qui initialise une image factice et affiche l'image encodée dans un fichier local.

en dessous du code est perso, crédit va à https://sourceforge.net/p/libjpeg-turbo/discussion/1086868/thread/e402d36f/#8722 . Le poster ici à nouveau pour aider quelqu'un trouve qu'il est difficile d'obtenir libjpeg turbo travailler.

#include "turbojpeg.h"
#include <iostream>
#include <string.h>
#include <errno.h>

using namespace std;

int main(void)
{
    unsigned char *srcBuf; //passed in as a param containing pixel data in RGB pixel interleaved format
    tjhandle handle = tjInitCompress();

    if(handle == NULL)
    {
        const char *err = (const char *) tjGetErrorStr();
        cerr << "TJ Error: " << err << " UNABLE TO INIT TJ Compressor Object\n";
        return -1;
    }
    int jpegQual =92;
    int width = 128;
    int height = 128;
    int nbands = 3;
    int flags = 0;
    unsigned char* jpegBuf = NULL;
    int pitch = width * nbands;
    int pixelFormat = TJPF_GRAY;
    int jpegSubsamp = TJSAMP_GRAY;
    if(nbands == 3)
    {
        pixelFormat = TJPF_RGB;
        jpegSubsamp = TJSAMP_411;
    }
    unsigned long jpegSize = 0;

    srcBuf = new unsigned char[width * height * nbands];
    for(int j = 0; j < height; j++)
    {
        for(int i = 0; i < width; i++)
        {
            srcBuf[(j * width + i) * nbands + 0] = (i) % 256;
            srcBuf[(j * width + i) * nbands + 1] = (j) % 256;
            srcBuf[(j * width + i) * nbands + 2] = (j + i) % 256;
        }
    }

    int tj_stat = tjCompress2( handle, srcBuf, width, pitch, height,
        pixelFormat, &(jpegBuf), &jpegSize, jpegSubsamp, jpegQual, flags);
    if(tj_stat != 0)
    {
        const char *err = (const char *) tjGetErrorStr();
        cerr << "TurboJPEG Error: " << err << " UNABLE TO COMPRESS JPEG IMAGE\n";
        tjDestroy(handle);
        handle = NULL;
        return -1;
    }

    FILE *file = fopen("out.jpg", "wb");
    if (!file) {
        cerr << "Could not open JPEG file: " << strerror(errno);
        return -1;
    }
    if (fwrite(jpegBuf, jpegSize, 1, file) < 1) {
        cerr << "Could not write JPEG file: " << strerror(errno);
        return -1;
    }
    fclose(file);

    //write out the compress date to the image file
    //cleanup
    int tjstat = tjDestroy(handle); //should deallocate data buffer
    handle = 0;
}
2
répondu Frank Chang 2018-03-07 00:40:38

voici un fragment de code que j'utilise pour charger les jpeg de mémoire. Peut-être qu'il faudra un peu de correction, parce que je l'ai extrait de différents fichiers dans mon projet. Il chargera à la fois les images-grayscale et rgb (bpp sera positionné soit à 1 soit à 3).

struct Image
{
    int bpp;
    int width;
    int height;
    unsigned char* data;
};

struct jerror_mgr
{
    jpeg_error_mgr base;
    jmp_buf        jmp;
};

METHODDEF(void) jerror_exit(j_common_ptr jinfo)
{
    jerror_mgr* err = (jerror_mgr*)jinfo->err;
    longjmp(err->jmp, 1);
}

METHODDEF(void) joutput_message(j_common_ptr)
{
}

bool Image_LoadJpeg(Image* image, unsigned char* img_data, unsigned int img_size)
{
    jpeg_decompress_struct jinfo;
    jerror_mgr jerr;

    jinfo.err = jpeg_std_error(&jerr.base);
    jerr.base.error_exit = jerror_exit;
    jerr.base.output_message = joutput_message;
    jpeg_create_decompress(&jinfo);

    image->data = NULL;

    if (setjmp(jerr.jmp)) goto bail;

    jpeg_mem_src(&jinfo, img_data, img_size);

    if (jpeg_read_header(&jinfo, TRUE) != JPEG_HEADER_OK) goto bail;

    jinfo.dct_method = JDCT_FLOAT; // change this to JDCT_ISLOW on Android/iOS

    if (!jpeg_start_decompress(&jinfo)) goto bail;

    if (jinfo.num_components != 1 && jinfo.num_components != 3) goto bail;

    image->data = new (std::nothrow) unsigned char [jinfo.output_width * jinfo.output_height * jinfo.output_components];
    if (!image->data) goto bail;

    {
        JSAMPROW ptr = image->data;
        while (jinfo.output_scanline < jinfo.output_height)
        {
            if (jpeg_read_scanlines(&jinfo, &ptr, 1) != 1) goto bail;

            ptr += jinfo.output_width * jinfo.output_components;
        }
    }

    if (!jpeg_finish_decompress(&jinfo)) goto bail;

    image->bpp = jinfo.output_components;
    image->width = jinfo.output_width;
    image->height = jinfo.output_height;

    jpeg_destroy_decompress(&jinfo);

    return true;

bail:
    jpeg_destroy_decompress(&jinfo);
    if (image->data) delete [] data;

    return false;
}
1
répondu Mārtiņš Možeiko 2012-02-01 19:48:09