2010-12-30 41 views
21

Tôi đã tìm thấy chức năng này trong đó sử dụng libjpeg để viết thư cho một tập tin:Ghi vào bộ nhớ đệm thay vì tệp bằng 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; 
} 

tôi sẽ thực sự cần phải viết hình ảnh jpeg nén chỉ vào bộ nhớ đệm, mà không lưu nó vào một tập tin, để tiết kiệm thời gian. Ai đó có thể cho tôi một ví dụ làm thế nào để làm điều đó?

Tôi đã tìm kiếm trên web trong một thời gian nhưng tài liệu rất hiếm khi có bất kỳ ví dụ nào cũng gặp khó khăn.

Trả lời

15

Bạn có thể xác định trình quản lý đích của riêng bạn khá dễ dàng. Các jpeg_compress_struct chứa một con trỏ đến một jpeg_destination_mgr, trong đó có một con trỏ đến một bộ đệm, một số không gian còn lại trong bộ đệm, và 3 con trỏ đến chức năng:

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

Bạn cần phải điền vào các chức năng gợi ý trước khi bạn thực hiện cuộc gọi đầu tiên vào thư viện jpeg và để các hàm đó xử lý bộ đệm. Nếu bạn tạo một bộ đệm lớn hơn sản lượng lớn nhất có thể mà bạn mong đợi, điều này trở nên tầm thường; init_destination chỉ điền vào con trỏ đệm và đếm, và empty_output_bufferterm_destination không làm gì cả.

Dưới đây là một số mẫu mã:

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

Tôi tưởng tượng rằng các con trỏ hàm này là những gì 'jpeg_stdio_dest' ảnh hưởng đến? –

+0

@Ben Voigt, nhìn vào nguồn của 'jpeg_stdio_dest' chính xác là nó làm gì. Nó phân bổ một cấu trúc và đặt nó thành 'cinfo-> dest', sau đó đặt con trỏ.Tôi đang suy nghĩ mã mẫu của riêng tôi có thể là một chút không đầy đủ vì nó không tạo ra một cấu trúc 'jpeg_destination_mgr', nhưng tôi sẽ xem xét nó sau. –

+0

Ồ, tất nhiên rồi. Bạn có thể [lưu trữ dữ liệu của riêng bạn ('std :: vector') ngay sau các con trỏ hàm và không cần biến toàn cục] (http://blogs.msdn.com/b/oldnewthing/archive/2010/12/20/ 10107027.aspx). –

0

Tất cả những gì bạn cần làm là chuyển một đối tượng FILE giống như jpeg_stdio_dest().

9

Có một chức năng được xác định trước jpeg_mem_src quy định tại jdatasrc.c. Ví dụ sử dụng đơn giản nhất:

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 

Đừng quên deallocate bộ đệm của bạn.

+0

Không có trong' jdatasrc.c' (libjpeg-6b) của tôi. –

+2

Phiên bản ổn định mới nhất của libjpeg là 9, bạn có thể tải nó ở đây http://www.ijg.org/files/jpegsr9.zip và nó chứa jpeg_mem_src. – dmitriykovalev

+0

Bạn có gọi miễn phí hoặc xóa trên bộ nhớ đệm không? Tôi gọi là xóa [] và valgrind đã cho tôi một cảnh báo xóa không khớp. Được sử dụng miễn phí() và cảnh báo biến mất. – shehzan

3

Tôi đã cố gắng giải pháp của Mark và trên nền tảng của tôi nó luôn mang đến cho PHÂN ĐOẠN lỗi FALUT khi nó thực thi

cinfo->dest->term_destination = &my_term_destination; 

Và tôi quay sang mã nguồn jpeglib (jdatadst.c) và thấy điều này:

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

ngay bên dưới phương thức jpeg_stdio_dest(), và tôi đã thử nó bằng cách điền vào địa chỉ của bộ đệm (char *) và địa chỉ của kích thước bộ đệm (int). Trình quản lý đích tự động cấp phát bộ nhớ cho bộ đệm và chương trình cần giải phóng bộ nhớ sau khi sử dụng.

Nó chạy thành công trên nền tảng của tôi, Beaglebone Black với Angstrom Linux được cài đặt sẵn. Phiên bản libjpeg của tôi là 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; 

Đây là tất cả những gì bạn cần đọc.

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



           } 

Và đây là tất cả những gì bạn cần để viết.

+8

** Cảnh báo ** - vui lòng không sử dụng những lời tục tĩu trong bài đăng của bạn. Tôi đã xóa nó cho bạn. Lưu ý rằng những người dùng khác có thể đã gắn cờ bài đăng của bạn là "thô lỗ hoặc lạm dụng" dẫn đến mất hoặc tạm ngưng có thể có. Vui lòng đọc [Be Nice] (http://superuser.com/help/be-nice): "Tránh những từ ngữ thô tục và bất cứ điều gì khêu gợi tình dục" – DavidPostill

Các vấn đề liên quan