使用libjpeg 压缩yuv420到jpg (内存方式)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用libjpeg 压缩yuv420到jpg (内存方式)相关的知识,希望对你有一定的参考价值。

#include <Windows.h> 
#include <stdio.h> 
     
extern  "C" { 
#include <jpeglib.h>  
} 
     
#define WIDTH 352 
#define HEIGHT 288 
#define QUALITY 80 
#define BUFFER_SZIE (WIDTH*HEIGHT*2) 
     
/* The following declarations and 5 functions are jpeg related 
 * functions used by put_jpeg_grey_memory and put_jpeg_yuv420p_memory
 */ 
typedef struct { 
    struct jpeg_destination_mgr pub; 
    JOCTET *buf; 
    size_t bufsize; 
    size_t jpegsize; 
} mem_destination_mgr; 
     
typedef mem_destination_mgr *mem_dest_ptr; 
     
     
METHODDEF(void) init_destination(j_compress_ptr cinfo) 
{ 
    mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; 
    dest->pub.next_output_byte = dest->buf; 
    dest->pub.free_in_buffer = dest->bufsize; 
    dest->jpegsize = 0; 
} 
     
METHODDEF(boolean) empty_output_buffer(j_compress_ptr cinfo) 
{ 
    mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; 
    dest->pub.next_output_byte = dest->buf; 
    dest->pub.free_in_buffer = dest->bufsize; 
     
    return FALSE; 
} 
     
METHODDEF(void) term_destination(j_compress_ptr cinfo) 
{ 
    mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; 
    dest->jpegsize = dest->bufsize - dest->pub.free_in_buffer; 
} 
     
static GLOBAL(void) jpeg_mem_dest(j_compress_ptr cinfo, JOCTET* buf, size_t bufsize) 
{ 
    mem_dest_ptr dest; 
     
    if (cinfo->dest == NULL) { 
        cinfo->dest = (struct jpeg_destination_mgr *) 
            (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT, 
            sizeof(mem_destination_mgr)); 
    } 
     
    dest = (mem_dest_ptr) cinfo->dest; 
     
    dest->pub.init_destination    = init_destination; 
    dest->pub.empty_output_buffer = empty_output_buffer; 
    dest->pub.term_destination    = term_destination; 
     
    dest->buf      = buf; 
    dest->bufsize  = bufsize; 
    dest->jpegsize = 0; 
} 
     
static GLOBAL(int) jpeg_mem_size(j_compress_ptr cinfo) 
{ 
    mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; 
    return dest->jpegsize; 
} 
     
     
     
/* put_jpeg_yuv420p_memory converts an input image in the YUV420P format into a jpeg image and puts
 * it in a memory buffer.
 * Inputs:
 * - input_image is the image in YUV420P format.
 * - width and height are the dimensions of the image
 * Output:
 * - dest_image is a pointer to the jpeg image buffer
 * Returns buffer size of jpeg image     
 */ 
static int put_jpeg_yuv420p_memory(unsigned char *dest_image, 
                                   unsigned char *input_image, int width, int height) 
{ 
    int i, j, jpeg_image_size; 
     
    JSAMPROW y[16],cb[16],cr[16]; // y[2][5] = color sample of row 2 and pixel column 5; (one plane) 
    JSAMPARRAY data[3]; // t[0][2][5] = color sample 0 of row 2 and column 5 
     
    struct jpeg_compress_struct cinfo; 
    struct jpeg_error_mgr jerr; 
     
    data[0] = y; 
    data[1] = cb; 
    data[2] = cr; 
     
    cinfo.err = jpeg_std_error(&jerr);  // errors get written to stderr  
         
    jpeg_create_compress(&cinfo); 
    cinfo.image_width = width; 
    cinfo.image_height = height; 
    cinfo.input_components = 3; 
    jpeg_set_defaults (&cinfo); 
     
    jpeg_set_colorspace(&cinfo, JCS_YCbCr); 
     
    cinfo.raw_data_in = TRUE;                  // supply downsampled data 
    cinfo.do_fancy_downsampling = FALSE;       // fix segfaulst with v7 
    cinfo.comp_info[0].h_samp_factor = 2; 
    cinfo.comp_info[0].v_samp_factor = 2; 
    cinfo.comp_info[1].h_samp_factor = 1; 
    cinfo.comp_info[1].v_samp_factor = 1; 
    cinfo.comp_info[2].h_samp_factor = 1; 
    cinfo.comp_info[2].v_samp_factor = 1; 
     
    jpeg_set_quality(&cinfo, QUALITY, TRUE); 
    cinfo.dct_method = JDCT_FASTEST; 
     
    jpeg_mem_dest(&cinfo, dest_image, BUFFER_SZIE);    // data written to mem 
         
    jpeg_start_compress (&cinfo, TRUE); 
     
    for (j = 0; j < height; j += 16) { 
        for (i = 0; i < 16; i++) { 
            y[i] = input_image + width * (i + j); 
            if (i%2 == 0) { 
                cb[i/2] = input_image + width * height + width / 2 * ((i + j) / 2); 
                cr[i/2] = input_image + width * height + width * height / 4 + width / 2 * ((i + j) / 2); 
            } 
        } 
        jpeg_write_raw_data(&cinfo, data, 16); 
    } 
     
    jpeg_finish_compress(&cinfo); 
    jpeg_image_size = jpeg_mem_size(&cinfo); 
    jpeg_destroy_compress(&cinfo); 
         
    return jpeg_image_size; 
} 
     
     
int main( int argc, TCHAR * argv[], TCHAR * envp[] ) 
{ 
    HANDLE fyuv,fyuvjpg; 
    BYTE *pSrc ,*pDst; 
    LONG  lSize = 0; 
    DWORD  readsize; 
    DWORD  writesize; 
     
    pSrc = new BYTE[BUFFER_SZIE]; 
    fyuv = CreateFile(L"cif.yuv", GENERIC_ALL, 0, NULL, OPEN_EXISTING, 0, NULL); 
    ReadFile(fyuv , pSrc ,BUFFER_SZIE ,&readsize,NULL); 
     
    pDst = new BYTE[BUFFER_SZIE]; 
    lSize = put_jpeg_yuv420p_memory(pDst,pSrc , WIDTH ,HEIGHT); 
    fyuvjpg = CreateFile(L"cif_yuv.jpg", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 
    WriteFile(fyuvjpg, pDst, lSize, &writesize, NULL); 
     
    CloseHandle(fyuv); 
    CloseHandle(fyuvjpg); 
    return 0; 
} 

 

以上是关于使用libjpeg 压缩yuv420到jpg (内存方式)的主要内容,如果未能解决你的问题,请参考以下文章

如何将yuv420p数据旋转90

ffmpeg yuv420保存jpg文件

yuv420p 转rgb计算

YUV420P的像素数据编码为H.264的压缩编码数据

YUV420P的像素数据编码为H.264的压缩编码数据

FFmpeg视频编码 YUV420P编码H264