Beispiele oder Tutorials zur Verwendung von TurboJPEG von libjpeg-turbo

Lesezeit: 7 Minuten

Benutzeravatar von occulus
occulus

Die Anleitung für libjpeg-turbo hier beschreibt die TurboJPEG-API folgendermaßen: “Diese API umschließt libjpeg-turbo und bietet eine einfach zu verwendende Schnittstelle zum Komprimieren und Dekomprimieren von JPEG-Bildern im Speicher”. Großartig, aber gibt es einige solide Beispiele für die Verwendung dieser API? Ich möchte nur ein ziemlich einfaches JPEG im Speicher dekomprimieren.

Ich habe ein paar Bits gefunden, wie z https://github.com/erlyvideo/jpeg/blob/master/c_src/jpeg.cdas anscheinend die TurboJPEG-API verwendet, aber gibt es solidere/variablere Beispiele?

Die Quelle für libjpeg-turbo ist gut dokumentiert, das hilft also.

Benutzeravatar von Theolodis
Theolodis

Ok, ich weiß, dass Sie Ihr Problem bereits gelöst haben, aber da einige Leute, genau wie ich, nach einem einfachen Beispiel suchen könnten, werde ich teilen, was ich erstellt habe. Es ist ein Beispiel für das Komprimieren und Dekomprimieren eines RGB-Bildes. Ansonsten denke ich, dass die API-Dokumentation von TurboJPEG ist ganz einfach zu verstehen!

Kompression:

#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);

Danach haben Sie das komprimierte Bild in _compressedImage. Zum Dekomprimieren müssen Sie Folgendes tun:

Dekompression:

#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);

Einige zufällige Gedanken:

Ich bin gerade beim Schreiben meiner Bachelorarbeit darauf zurückgekommen und habe festgestellt, dass es besser ist, wenn Sie die Komprimierung in einer Schleife ausführen, die größte Größe des JPEG-Puffers zu speichern, um nicht jede Runde einen neuen zuweisen zu müssen. Grundsätzlich, anstatt zu tun:

long unsigned int _jpegSize = 0;

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

Wir würden eine Objektvariable hinzufügen, die die Größe des zugewiesenen Speichers enthält long unsigned int _jpegBufferSize = 0; und vor jeder Komprimierungsrunde würden wir die jpegSize auf diesen Wert zurücksetzen:

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;

Nach der Komprimierung würde man die Speichergröße mit der tatsächlichen jpegSize vergleichen und auf die jpegSize setzen, wenn sie größer als die vorherige Speichergröße ist.

  • An die Downvotings: Ich behalte diese Antwort immer noch bei und würde mich freuen zu wissen, was Sie schlecht finden. Hinterlasse mir also bitte einen Kommentar!

    – Theolodis

    10. März 2015 um 10:29 Uhr

  • Die neue tj-Version (1.4) hat eine Dekomprimierung in YUV-Ebenen: tjDecompressToYUVPlanes(c_jpegDecompressor, c_jpeg_buffer, _jpegSize, m_planesYUV, 0, NULL, 0, m_accuracy);

    – Mausomer

    10. März 2015 um 14:32 Uhr


  • Der obige Dokumentationslink von Turbojpeg ist nicht mehr gültig, versuchen Sie es libjpeg-turbo.org/Documentation/Documentation

    – Alan Corey

    4. März 2018 um 15:23 Uhr

  • @jean-loup cdn.rawgit.com/libjpeg-turbo/libjpeg-turbo/master/doc/html/… haben Sie sich vielleicht die schnellere Implementierung der JPEG-Bibliothek angesehen? Weil libjpeg-turbo != Turbojpeg.

    – Theolodis

    15. Juni 2018 um 9:38 Uhr


  • @Theolodis, es gibt einige Verwirrung, weil der Header von libjpeg-turbo turbojpeg.h ist und libjpeg-turbo in Ubuntu nicht diese Bibliothek ist. Aber aus dem Git-Repo installiert, hat es perfekt funktioniert.

    – jean-loup

    15. Juni 2018 um 15:07 Uhr

Am Ende habe ich den folgenden Code als Arbeitsbeispiel für die JPEG-Codierung und -Decodierung verwendet. Das beste Beispiel, das ich finden kann, ist in sich geschlossen, das ein Dummy-Bild initialisiert und das codierte Bild in eine lokale Datei ausgibt.

Der folgende Code ist NICHT meine eigene, Kredit geht an https://sourceforge.net/p/libjpeg-turbo/discussion/1086868/thread/e402d36f/#8722 . Ich poste es hier noch einmal, um jemandem zu helfen, der findet, dass es schwierig ist, libjpeg turbo zum Laufen zu bringen.

#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;
}

Benutzeravatar von occulus
occulus

Am Ende habe ich eine Kombination aus zufälligem Code verwendet, der im Internet gefunden wurde (z https://github.com/erlyvideo/jpeg/blob/master/c_src/jpeg.c) und die .c- und Header-Dateien für libjeg-turbo, die gut dokumentiert sind.
Dies Die offizielle API ist ebenfalls eine gute Informationsquelle.

  • Wenn der Code klein ist, können Sie ihn hier teilen, um Ihre Antwort zu verbessern;)

    – Rui Marken

    27. September 2012 um 14:20 Uhr

Hier ist ein Codefragment, mit dem ich JPEGs aus dem Speicher lade. Vielleicht muss es ein wenig repariert werden, da ich es aus verschiedenen Dateien in meinem Projekt extrahiert habe. Es werden sowohl Graustufen- als auch RGB-Bilder geladen (bpp wird entweder auf 1 oder auf 3 gesetzt).

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;
}

1389980cookie-checkBeispiele oder Tutorials zur Verwendung von TurboJPEG von libjpeg-turbo

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy