2010-12-30 2 views
21

내가 파일에 쓸 libjpeg을 사용하여이 기능을 발견했다 :libjpeg로 파일 대신 메모리 버퍼에 씁니까?

int write_jpeg_file(char *filename) 
{ 
    struct jpeg_compress_struct cinfo; 
    struct jpeg_error_mgr jerr; 

    /* this is a pointer to one row of image data */ 
    JSAMPROW row_pointer[1]; 
    FILE *outfile = fopen(filename, "wb"); 

    if (!outfile) 
    { 
     printf("Error opening output jpeg file %s\n!", filename); 
     return -1; 
    } 
    cinfo.err = jpeg_std_error(&jerr); 
    jpeg_create_compress(&cinfo); 
    jpeg_stdio_dest(&cinfo, outfile); 

    /* Setting the parameters of the output file here */ 
    cinfo.image_width = width; 
    cinfo.image_height = height; 
    cinfo.input_components = bytes_per_pixel; 
    cinfo.in_color_space = color_space; 
    /* default compression parameters, we shouldn't be worried about these */ 
    jpeg_set_defaults(&cinfo); 
    /* Now do the compression .. */ 
    jpeg_start_compress(&cinfo, TRUE); 
    /* like reading a file, this time write one row at a time */ 
    while(cinfo.next_scanline < cinfo.image_height) 
    { 
     row_pointer[0] = &raw_image[ cinfo.next_scanline * cinfo.image_width * cinfo.input_components]; 
     jpeg_write_scanlines(&cinfo, row_pointer, 1); 
    } 
    /* similar to read file, clean up after we're done compressing */ 
    jpeg_finish_compress(&cinfo); 
    jpeg_destroy_compress(&cinfo); 
    fclose(outfile); 
    /* success code is 1! */ 
    return 1; 
} 

실제로 파일에 저장하지 않고, 단지 메모리 버퍼에 JPEG 압축 된 이미지를 작성해야 시간을 절약하는 것입니다. 누군가 그것을 어떻게 할 수 있는지 예를 들어 줄 수 있습니까?

나는 잠시 동안 웹을 검색해 왔지만, 문서가 매우 희귀하고 어떤 예제도 나오기가 어렵다면 매우 드뭅니다.

답변

15

아주 쉽게 자신 만의 대상 관리자를 정의 할 수 있습니다.

init_destination (j_compress_ptr cinfo) 
empty_output_buffer (j_compress_ptr cinfo) 
term_destination (j_compress_ptr cinfo) 

당신은 당신이하기 전에 함수 포인터를 입력 할 필요가 다음 jpeg_compress_struct 함수에, 버퍼에 버퍼에 남아있는 공간의 수를 포인터를 포함 jpeg_destination_mgr, 3 포인터에 대한 포인터를 포함합니다 jpeg 라이브러리에 대한 첫 번째 호출을 수행하고 해당 함수가 버퍼를 처리하도록합니다. 가능한 가장 큰 출력보다 큰 버퍼를 생성하면 이는 사소한 것이됩니다. init_destination은 버퍼 포인터를 채우고 카운트하며 empty_output_bufferterm_destination은 아무 작업도 수행하지 않습니다.

std::vector<JOCTET> my_buffer; 
#define BLOCK_SIZE 16384 

void my_init_destination(j_compress_ptr cinfo) 
{ 
    my_buffer.resize(BLOCK_SIZE); 
    cinfo->dest->next_output_byte = &my_buffer[0]; 
    cinfo->dest->free_in_buffer = my_buffer.size(); 
} 

boolean my_empty_output_buffer(j_compress_ptr cinfo) 
{ 
    size_t oldsize = my_buffer.size(); 
    my_buffer.resize(oldsize + BLOCK_SIZE); 
    cinfo->dest->next_output_byte = &my_buffer[oldsize]; 
    cinfo->dest->free_in_buffer = my_buffer.size() - oldsize; 
    return true; 
} 

void my_term_destination(j_compress_ptr cinfo) 
{ 
    my_buffer.resize(my_buffer.size() - cinfo->dest->free_in_buffer); 
} 

cinfo->dest->init_destination = &my_init_destination; 
cinfo->dest->empty_output_buffer = &my_empty_output_buffer; 
cinfo->dest->term_destination = &my_term_destination; 
+0

나는이 함수 포인터가'jpeg_stdio_dest'가 영향을 줄 것이라고 생각합니까? –

+0

@Ben Voigt, 정확히 무엇을하는지'jpeg_stdio_dest'에 대한 소스를보고 있습니다. 구조체를 할당하고'cinfo-> dest'에 설정 한 다음 포인터를 설정합니다.내 자신의 샘플 코드는'jpeg_destination_mgr' 구조체를 생성하지 않기 때문에 약간 불완전하다고 생각합니다.하지만 나중에 살펴 보겠습니다. –

+0

아 물론. 함수 포인터 바로 다음에 전역 변수가 필요없는 [자신의 데이터 ('std :: vector')를 저장할 수 있습니다.] (http://blogs.msdn.com/b/oldnewthing/archive/2010/12/20/ 10107027.aspx). –

0

FILE과 같은 객체를 jpeg_stdio_dest()으로 전달하면됩니다.

9

jdatasrc.c에 정의 된 미리 정의 된 함수 jpeg_mem_src 있습니다 :

는 여기에 몇 가지 예제 코드입니다. 가장 간단한 사용 예 :

unsigned char *mem = NULL; 
unsigned long mem_size = 0; 
struct jpeg_compress_struct cinfo; 
struct jpeg_error_mgr jerr; 
cinfo.err = jpeg_std_error(&jerr); 
jpeg_create_compress(&cinfo); 
jpeg_mem_dest(&cinfo, &mem, &mem_size); 

// do compression 

// use mem buffer 

버퍼를 할당하는 것을 잊지 마십시오.

jpeg_mem_dest (j_compress_ptr cinfo, unsigned char ** outbuffer, unsigned long * outsize) 
:
+0

내'jdatasrc.c' (libjpeg-6b)에 없습니다. –

+2

libjpeg의 최신 안정 릴리스는 9입니다. http://www.ijg.org/files/jpegsr9.zip에서 얻을 수 있으며 jpeg_mem_src가 포함되어 있습니다. – dmitriykovalev

+0

mem 버퍼를 무료 또는 삭제 하시겠습니까? 나는 delete []라고 불렀고, valgrind는 나에게 일치하지 않는 삭제 경고를주었습니다. 사용 된 무료()와 경고가 사라졌습니다. – shehzan

3

나는 마크의 솔루션을 시도하고

cinfo->dest->term_destination = &my_term_destination; 

을 실행하고 나는 jpeglib 소스 코드 (jdatadst.c)로 전환이를 발견했을 때 내 플랫폼에서 항상 분할의 FALUT 오류를 제공

방금 ​​jpeg_stdio_dest() 메소드 바로 아래에 버퍼의 주소 (char *)와 버퍼 크기 (int)를 채워 넣으 려했습니다. 대상 관리자는 자동으로 버퍼 메모리를 할당하고 프로그램은 사용 후 메모리를 비워야합니다.

사전 설치된 Angstrom Linux가있는 Beaglebone Black 플랫폼에서 성공적으로 실행됩니다. 내 libjpeg 버전은 8d입니다.

1
unsigned char ***image_ptr  
unsigned char* ptr; 
unsigned char** image_buf; 

for(int i=0;i<h;i++){ 
image_buf[i] = new unsigned char[w*o]; 
} 

ptr = image_buf[0]; 

    while (info.output_scanline < info.image_height) { 

    jpeg_read_scanlines(&info,&ptr,1); 

    ptr = image_buf[c]; 

    c++; 


    } 

    *image_ptr = image_buf; 

이 내용을 모두 읽어야합니다.

JSAMPROW row_pointer; 

     while (info.next_scanline < info.image_height) { 

     row_pointer = &image_buf[info.next_scanline][0]; 

      (void) jpeg_write_scanlines(&info, &row_pointer, 1); 



           } 

그리고이 모두를 작성해야합니다.

+8

** 경고 ** - 귀하의 게시물에 음담을 사용하지 마십시오. 나는 당신을 위해 그것을 제거했습니다. 다른 사용자가 귀하의 게시물을 "무례하거나 폭력적인"것으로 표시하여 파산이나 정지를 초래할 수 있습니다. [Be Nice] (http://superuser.com/help/be-nice)를 읽으십시오 : "저속한 용어 및 성적인 것을 암시하는 것은 피하십시오" – DavidPostill