2012-02-01 9 views
20

Instrukcje dla libjpeg-turbo here opisują interfejs TurboJPEG API w ten sposób: "Ten interfejs API otacza libjpeg-turbo i zapewnia łatwy w użyciu interfejs do kompresji i dekompresji obrazów JPEG w pamięci" . Świetnie, ale czy są jakieś solidne przykłady wykorzystania tego API? Po prostu staram się rozpakować w pamięci całkiem waniliowy jpeg.Przykłady lub samouczki dotyczące korzystania z libjpeg-turbo TurboJPEG

Znalazłem kilka bitów, takich jak https://github.com/erlyvideo/jpeg/blob/master/c_src/jpeg.c, który wydaje się być za pomocą TurboJPEG API, ale czy istnieją bardziej solidne/różnorodne przykłady?

Źródło libjpeg-turbo jest dobrze udokumentowane, więc pomaga.

Odpowiedz

4

Na końcu używa się kombinacji losowy kod znaleźć na stronie internetowej (np https://github.com/erlyvideo/jpeg/blob/master/c_src/jpeg.c) i pliki .c i kolektor do libjeg-turbo, które są dobrze udokumentowane. This oficjalny interfejs API jest dobrym źródłem informacji.

+0

Jeśli kod jest mały, możesz udostępnić go tutaj, aby poprawić swoją odpowiedź;) –

+0

Będę go szukać w pewnym momencie i dodać do odpowiedzi. – occulus

1

Oto fragment kodu, za pomocą którego ładuję jpeg z pamięci. Może będzie to wymagało trochę naprawy, ponieważ wyodrębniłem je z różnych plików w moim projekcie. Załaduje zarówno obrazy w skali szarości, jak i rgb (bpp zostanie ustawione na 1 lub 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

Przepraszam unaccept swoją odpowiedź, ale patrząc uważnie teraz ja faktycznie realizacji może to widzę, nie jesteś nawet wywoływanie funkcji TJ w kodzie pisał (np tjDecompress). – occulus

+0

Korzystanie z interfejsu API TurboJpeg nie jest obowiązkowe, aby uzyskać korzyści prędkości z biblioteki libjpeg-turbo. W moim przykładzie używam tylko standardowego API libjpeg. Dlaczego nie chcesz korzystać z interfejsu API libjpeg? –

+2

Moje pytanie dość jasno pyta o interfejs TurboJPEG API. Używam go ze względu na jego prostotę w porównaniu do standardowego interfejsu libjpeg. – occulus

43

Ok, wiem, że już rozwiązałeś swój problem, ale jak niektórzy ludzie, tak jak ja, mogliby szukać jakiegoś prostego przykładu, podzielę się tym, co stworzyłem. Jest to przykład kompresji i dekompresji obrazu RGB. W przeciwnym razie uważam, że dokumentacja API TurboJPEG jest dość łatwa do zrozumienia!

Kompresja:

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

Po że masz obraz skompresowany w _compressedImage. Aby rozpakować trzeba wykonać następujące czynności:

Dekompresja:

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

Niektóre losowe myśli:

Właśnie wróciłem nad tym co piszę moje pracy licencjackiej, a Zauważyłem, że jeśli uruchomisz kompresję w pętli, najlepiej jest zapisać największy rozmiar bufora JPEG, aby nie trzeba było przydzielać nowego w każdej turze. Zasadniczo, zamiast robić:

long unsigned int _jpegSize = 0; 

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

chcielibyśmy dodać zmienną obiektu, trzymając wielkość przydzielonej pamięci long unsigned int _jpegBufferSize = 0; i przed każdym rundzie kompresji chcielibyśmy ustawić jpegSize z powrotem do tej wartości:

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; 

po kompresji można porównać rozmiar pamięci z faktycznym jpegSize i ustawić go na jpegSize, jeśli jest on wyższy niż poprzedni rozmiar pamięci.

+1

To jest cudowne! Dzięki! – mousomer

+0

Spróbuję. Dokumentacja turbbojpeg mówi, że powinna to być długość rzędu. Nie rozumiem wyjścia ani wejścia. Tak czy inaczej, myliłem się. Rozmiary są rozsądne. Przy okazji - aktualnie ładuję (dekompresuję) jpeg i przycinam regiony do plików. Czy istnieje 2-liniowa turbojpeg do przycinania obrazu i wysyłania wyników do pliku? – mousomer

+0

Zrobiłem to - zapamiętywałem obszar przycięty linia po linii w buforze (pętla 2 liniowa), kompresowanie jpeg (1 linia) i zapisywanie do fstream (4 linie). Pomyślałem, może już istnieje funkcja biblioteczna. – mousomer

1

Skończyło się na użyciu poniższego kodu jako przykładu dla kodowania i dekodowania JPEG. Najlepszym przykładem, jaki mogę znaleźć, jest samowystarczalny, który inicjuje fałszywy obraz i wysyła zakodowany obraz do lokalnego pliku.

Poniżej znajduje się NOT własne, kredyt trafia do https://sourceforge.net/p/libjpeg-turbo/discussion/1086868/thread/e402d36f/#8722. Publikuj tutaj ponownie, aby pomóc każdemu w znalezieniu trudności w uruchomieniu libjpeg turbo.

#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; 
} 
Powiązane problemy