#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <sys/stat.h>
#include <string>
#include <string.h>
using namespace std;
extern "C" {
#include <jpeglib.h>
#include <setjmp.h>
#include <jerror.h>
}
#define WIDTH 320
#define HEIGHT 240
#define QUALITY 80
#define BUFFER_SZIE (WIDTH*HEIGHT*3/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, char **argv )
{
FILE *fyuv=NULL;
FILE *fyuvjpg=NULL;
unsigned char *pSrc =NULL ;
unsigned char *pDst =NULL;
int lSize = 0;
std::string input_yuv_name="";
if (NULL!=argv[1])
{
input_yuv_name = argv[1];
}
else
{
std::cout<<"Input YUV is NULL!!"<<std::endl;
return -1;
}
fyuv = fopen(input_yuv_name.c_str(),"r");
pSrc = (unsigned char *)malloc (BUFFER_SZIE);
pDst = (unsigned char *)malloc (BUFFER_SZIE);
memset(pSrc,BUFFER_SZIE, 0 );
memset(pDst,BUFFER_SZIE, 0 );
if( fread(pSrc, BUFFER_SZIE,1 ,fyuv) >1)
{
std::cerr<<"Error occur in stat function !!"<<std::endl;
}
lSize = put_jpeg_yuv420p_memory(pDst, pSrc , WIDTH ,HEIGHT);
std::string output_yuv_name="Encoded.jpeg";
fyuvjpg =fopen(output_yuv_name.c_str(),"w");
fwrite(pDst,BUFFER_SZIE, 1 ,fyuvjpg);
if (NULL != pSrc)
{
free(pSrc);
pSrc=NULL;
}
if (NULL != pDst)
{
free(pDst);
pDst=NULL;
}
fclose(fyuv);
fclose(fyuvjpg);
return 0;
}
linux make file:
#Make file for JPEG encoder
#target type and test program directory
TARGET_TYPE = EXECUTABLE
#compiler
COMPILER = g++
PRJ_PATH = /home/dahu/development/libjpeg/SourceCode/dev-code/encoder
test := encode420
#flags
LIBS:= -lpthread -lm -lgcc -lstdc++ -L/usr/local/lib/ -ljpeg
INCLS := -I/usr/local/include/
CFLAGS := -g -O0 -Wall -DDEBUG_ONLY
#files
#target control
ifeq ($(TARGET_TYPE),EXECUTABLE)
TARGET = Jpeg420Encoder
CLIENT_SOURCES := $(test).cpp
CLIENT_OBJS := $(CLIENT_SOURCES:.cpp=.o)
TARGETCMD = $(COMPILER) $(INCLS) $(CFLAGS) -o $@ $^ $(LIBS)
else
@echo "ERROR !! You have to assign right TARGET_TYPE= EXECUTABLE!"
endif
.PHONY: all
all: $(TARGET)
$(TARGET):$(CLIENT_OBJS)
$(TARGETCMD)
#clean
clean:
@rm -rfv Jpeg420Encoder *.o
运行:
./Jpeg420Encoder jpeg_320_240_420.0.yuv
可在当前目录下找到编好的jpeg文件