linux 下 libjpeg 生成 jpg图片

非自己写的,而是前辈写的,希望借此可以提示到别人

jpegenc.c


#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "jpeglib.h"
#include "jerror.h"
#include "stddef.h"
#include "setjmp.h"

struct JPEG_Enc
{
    struct jpeg_destination_mgr		dst;        // A data destination manager provides three methods: https://raw.githubusercontent.com/libjpeg-turbo/libjpeg-turbo/master/libjpeg.txt
	struct jpeg_compress_struct		cinfo;
	struct jpeg_error_mgr			jerr;       // Use standard error mgr

    int                             quality;    // 1-100
    int                             jpeg_w;
    int                             jpeg_h;
    int                             jpeg_ch;
    // Raw buffer
    unsigned char                   *buffer;    // G, RGB, or RGBA format
    // Output
    FILE                            *fp;
    unsigned char                   *jpegOutput;
    unsigned long                   jpegOutputSize;
};

#define kBufferSize (4096)
#define kMaxLines   (8)

void jpegenc_init_destination(j_compress_ptr cinfo);

unsigned char *jpegenc_get_enc_buf(struct JPEG_Enc *jpeg_enc )
{
    return (unsigned char *)jpeg_enc->jpegOutput;
}

unsigned long jpegenc_get_enc_size(struct JPEG_Enc *jpeg_enc )
{
    return (unsigned long)jpeg_enc->jpegOutputSize;
}

int jpegenc_compress( struct JPEG_Enc *jpeg_enc, unsigned char *bytes, int quality, int ch )
{
	struct jpeg_compress_struct *cinfo = &jpeg_enc->cinfo;
	JSAMPROW row_pointer[kMaxLines];
	int rowBytes;
    unsigned char *srcScan = NULL;

	if (bytes == NULL)
        goto bail;
    if((ch > jpeg_enc->jpeg_ch) || ( ch != 1 && ch != 3 ) )
        goto bail;

    cinfo->input_components = ch;
    rowBytes = cinfo->image_width * cinfo->input_components;
    jpeg_enc->cinfo.in_color_space = (ch == 1)? JCS_GRAYSCALE : JCS_RGB;

    // Reset output buffer
    jpeg_enc->jpegOutputSize = 0;
	cinfo->dct_method = JDCT_IFAST;
    jpeg_set_defaults(cinfo);

    if(quality < 0)
        quality = 0;
    else if (quality > 100 )
        quality = 100;
    jpeg_enc->quality = quality;
	jpeg_set_quality(cinfo, jpeg_enc->quality, (boolean)1);

    // Set scan lines, which used by jpeglib
	jpeg_start_compress(cinfo, 1);

	while (cinfo->next_scanline < cinfo->image_height) {
        JDIMENSION lines = kMaxLines, i;
        if (lines > (cinfo->image_height - cinfo->next_scanline))
            lines = cinfo->image_height - cinfo->next_scanline;
        
        srcScan = bytes + rowBytes * cinfo->next_scanline;
        for (i = 0; i < lines; i++) {
            row_pointer[i] = srcScan;
            srcScan += rowBytes;
        }
	    jpeg_write_scanlines(cinfo, row_pointer, lines);
    }

    jpeg_finish_compress(cinfo);
    
    return 0;
bail:
	return 1;
}

void jpegenc_init_destination(j_compress_ptr cinfo)
{
	struct JPEG_Enc *jpeg_enc = (struct JPEG_Enc *)cinfo->dest;
	jpeg_enc->dst.next_output_byte = jpeg_enc->buffer;
    jpeg_enc->dst.free_in_buffer   = kBufferSize;
}

boolean jpegenc_empty_output_buffer(j_compress_ptr cinfo)
{
	struct JPEG_Enc *jpeg_enc = (struct JPEG_Enc *)cinfo->dest;

	if (NULL != jpeg_enc->fp)
		fwrite(jpeg_enc->buffer, 1, kBufferSize, jpeg_enc->fp);
	else {
		memmove(jpeg_enc->jpegOutput + jpeg_enc->jpegOutputSize, jpeg_enc->buffer, kBufferSize);
		jpeg_enc->jpegOutputSize  += kBufferSize;
	}

	jpeg_enc->dst.next_output_byte = jpeg_enc->buffer;
	jpeg_enc->dst.free_in_buffer = kBufferSize;

	return 1;
}

void jpegenc_term_destination(j_compress_ptr cinfo)
{
	struct JPEG_Enc * jpeg_enc = (struct JPEG_Enc *)cinfo->dest;
	int size = (int)(kBufferSize - jpeg_enc->dst.free_in_buffer);

    if (NULL != jpeg_enc->fp)
        fwrite(jpeg_enc->buffer, 1, size, jpeg_enc->fp);
	else {
		memmove(jpeg_enc->jpegOutput + jpeg_enc->jpegOutputSize, jpeg_enc->buffer, size);
		jpeg_enc->jpegOutputSize  += size;
	}
}

struct JPEG_Enc *new_jpegenc( int w, int h, int ch )
{
    struct JPEG_Enc * jpeg_enc = (struct JPEG_Enc *) malloc(sizeof(struct JPEG_Enc));
    if( jpeg_enc == NULL )
        goto fail;
    memset(jpeg_enc, 0, sizeof(struct JPEG_Enc));

    if(ch != 1 && ch != 3)
        goto fail;

    jpeg_enc->jpeg_w  = w;
    jpeg_enc->jpeg_h  = h;
    jpeg_enc->jpeg_ch = ch;

    // TODO: Just to elimnate reallocate buffer
    // Buffer for encoded bytes for one image/frame
    jpeg_enc->jpegOutput = (unsigned char*)malloc(jpeg_enc->jpeg_w * jpeg_enc->jpeg_h * ch);  
	if (jpeg_enc->jpegOutput == NULL)
	{
		goto fail;
    }

    // Used by scan lines - temp buffer for encoded bytes
    jpeg_enc->buffer = (unsigned char*)malloc(kBufferSize);
	if (jpeg_enc->buffer == NULL)
	{
		goto fail;
    }

    // Allocate and initialize JPEG compression object
    // Error manager
    jpeg_enc->cinfo.err = jpeg_std_error(&jpeg_enc->jerr);
	//jpeg_enc->cinfo.err->error_exit = ???;

    jpeg_create_compress(&jpeg_enc->cinfo);

    // destination manager
    jpeg_enc->cinfo.dest = &jpeg_enc->dst;
	jpeg_enc->dst.init_destination = jpegenc_init_destination;
	jpeg_enc->dst.empty_output_buffer = jpegenc_empty_output_buffer;
	jpeg_enc->dst.term_destination = jpegenc_term_destination;

    jpeg_enc->quality = 60;

    jpeg_enc->cinfo.image_width = w;
	jpeg_enc->cinfo.image_height = h;
	jpeg_enc->cinfo.input_components = ch;
	jpeg_enc->cinfo.in_color_space = (ch == 1)? JCS_GRAYSCALE : JCS_RGB;

	jpeg_enc->cinfo.dct_method = JDCT_IFAST;

    return jpeg_enc;

fail:
    if(jpeg_enc)
    {
        if(jpeg_enc->buffer)
            free(jpeg_enc->buffer);
        if(jpeg_enc->jpegOutput)
            free(jpeg_enc->jpegOutput);

        free(jpeg_enc);
    }
    return NULL;
}

void dispose_jpegenc( struct JPEG_Enc *jpeg_enc )
{
    if(jpeg_enc)
    {
        if(jpeg_enc->buffer)
            free(jpeg_enc->buffer);
        if(jpeg_enc->jpegOutput)
            free(jpeg_enc->jpegOutput);

        if(jpeg_enc->fp)
            fclose(jpeg_enc->fp);

        jpeg_destroy_compress(&jpeg_enc->cinfo);
        free(jpeg_enc);
    }
}

jepgenc.h

#ifndef __JPEGENCODERH__
#define __JPEGENCODERH__


struct JPEG_Enc;

/*
    Notes:
        1. New a jpegenc with image features: width, height, and channel (1,3 are valid)
        2. Prepare image raw bytes buffer (for example rawbuf), which should have format Gray or RGB
        3. execute jpegenc_compress
        4. Then get result from jpegenc_get_enc_size(...) and jpegenc_get_enc_buf(...)
*/

int jpegenc_compress( struct JPEG_Enc *jpeg_enc, unsigned char *bytes, int quality, int ch );
unsigned long jpegenc_get_enc_size(struct JPEG_Enc *jpeg_enc );
unsigned char *jpegenc_get_enc_buf(struct JPEG_Enc *jpeg_enc );

//unsigned char *jpegenc_get_raw_buf(struct JPEG_Enc *jpeg_enc );

struct JPEG_Enc *new_jpegenc( int w, int h, int ch );
void dispose_jpegenc( struct JPEG_Enc *jpeg_enc );

#endif //__JPEGENCODERH__

test_jpeg.c

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#include "jpeglib.h"
#include "jpegenc.h"

void get_now_ms( unsigned long *ms)
{
    struct timeval now;
    gettimeofday(&now, NULL);
    *ms = now.tv_sec * 1000 + now.tv_usec/1000;
}

// Creates a test image for saving. Creates a Mandelbrot Set fractal of size width x height
float *createMandelbrotImage(int width, int height, float xS, float yS, float rad, int maxIteration);

// This takes the float value 'val', converts it to red, green & blue values, then 
// sets those values into the image memory buffer location pointed to by 'ptr'
void setRGB(unsigned char *ptr, float val);

void convertBuffer(unsigned char *buf_b, float *buf_f, int w, int h, int has_alpha);

void makeGrayImg(unsigned char *buf, int w, int h, int sz) {
	unsigned char val = 0;
	// Do not check sz can be dived by w
	unsigned char *p = buf;
	for(int i=0; i< h; i+=sz) {
		memset(p, val, w*sz);
		p += w*sz;
		val = ~val;
	}
}

void test_jpeg_file()
{
    struct JPEG_Enc  *jpeg_enc;
    FILE *fp = NULL;
	int  ch = 3;
	int  has_alpha = 0;

	// Specify an output image size
	int width = 640;
	int height = 480;

	// Create a test image
	printf("Creating Image\n");
	float *buffer_f = createMandelbrotImage(width, height, -0.802, -0.177, 0.011, 110);
	if (buffer_f == NULL) {
		return;
	}
	// Then convert to bytes
	unsigned char *buffer_b = (unsigned char *) malloc((3 + (has_alpha?1:0)) * width * height * sizeof(unsigned char));
	if (buffer_b == NULL) {
		return;
	}
	convertBuffer(buffer_b, buffer_f, width, height, (3 + has_alpha));

	unsigned char *buffer_g = (unsigned char *) malloc( width * height * sizeof(unsigned char));
	if (buffer_g == NULL) {
		return;
	}
	convertBuffer(buffer_g, buffer_f, width, height,  1);

    // JPEG encoding for RGB image
    jpeg_enc = new_jpegenc(width, height, ch);
    if(jpeg_enc == NULL) {
        return;
    }
	// Encoding
	unsigned long t0, t1;
	get_now_ms(&t0);
	jpegenc_compress(jpeg_enc, buffer_b,  60, ch);
	get_now_ms(&t1);
	printf("Compress RGB image to JPEG using %ldms\n", t1-t0);

    printf("Saving JPEG\n");
	fp = fopen("test_rgb.jpg", "wb");
	if (fp == NULL) {
		fprintf(stderr, "Could not open file for writing\n");
		return;
	}
    fwrite(jpegenc_get_enc_buf(jpeg_enc), 1, jpegenc_get_enc_size(jpeg_enc), fp);
	//dispose_jpegenc(jpeg_enc);
    if (fp != NULL)
		fclose(fp);

    // JPEG encoding for Gray image
	// Encoding
	get_now_ms(&t0);
	jpegenc_compress(jpeg_enc, buffer_g,  60, 1);
	get_now_ms(&t1);
	printf("Compress Gray image to JPEG using %ldms\n", t1-t0);

    printf("Saving JPEG\n");
	fp = fopen("test_gray.jpg", "wb");
	if (fp == NULL) {
		fprintf(stderr, "Could not open file for writing\n");
		return;
	}
    fwrite(jpegenc_get_enc_buf(jpeg_enc), 1, jpegenc_get_enc_size(jpeg_enc), fp);
	//dispose_jpegenc(jpeg_enc);
    if (fp != NULL)
		fclose(fp);

	// Free up the memorty used to store the image
	free(buffer_f);
	free(buffer_b);
	free(buffer_g);
	
	
	// Added another example: 20190603
	unsigned char *grayBuf = malloc(640*480 * sizeof(char));
	makeGrayImg(grayBuf, 640, 480, 16);
	
	get_now_ms(&t0);
	jpegenc_compress(jpeg_enc, grayBuf,  60, 1);
	get_now_ms(&t1);
	printf("Compress Gray image to JPEG using %ldms\n", t1-t0);

    printf("Saving JPEG\n");
	fp = fopen("test_gray1.jpg", "wb");
	if (fp == NULL) {
		fprintf(stderr, "Could not open file for writing\n");
		return;
	}
    fwrite(jpegenc_get_enc_buf(jpeg_enc), 1, jpegenc_get_enc_size(jpeg_enc), fp);
	dispose_jpegenc(jpeg_enc);
    if (fp != NULL)
		fclose(fp);
	
}

void setGray(unsigned char *ptr, float val)
{
	int v = (int)(val * 767);
	if (v < 0) v = 0;
	if (v > 767) v = 767;
	int offset = v % 256;

	if (v<256) {
		ptr[0] = offset;
	}
	else if (v<512) {
		ptr[0] = 255-offset;
	}
	else {
		ptr[0] = 0;
	}
}

// ch can be '1', '3', '4'
void convertBuffer(unsigned char *buf_b, float *buf_f, int w, int h, int ch) 
{
	int x, y;
	int line_sz = w*(ch);
	int pixel_sz = (ch);
	int has_alpha = (ch == 4);
	if(ch == 1) {
		for (y=0 ; y<h ; y++) {
			//printf("%d\n", y);
			for (x=0 ; x<w ; x++) 
			{
				setGray(&(buf_b[y*line_sz + x*pixel_sz ]), buf_f[y*w + x]);
			}
		}
	}
	else {
		for (y=0 ; y<h ; y++) {
			//printf("%d\n", y);
			for (x=0 ; x<w ; x++) 
			{
				setRGB(&(buf_b[y*line_sz + x*pixel_sz ]), buf_f[y*w + x]);
				if(has_alpha)
					buf_b[y*line_sz + x*pixel_sz +3] = 255;
			}
		}
	}

}

void setRGB(unsigned char *ptr, float val)
{
	int v = (int)(val * 767);
	if (v < 0) v = 0;
	if (v > 767) v = 767;
	int offset = v % 256;

	if (v<256) {
		ptr[0] = 0; ptr[1] = 0; ptr[2] = offset;
	}
	else if (v<512) {
		ptr[0] = 0; ptr[1] = offset; ptr[2] = 255-offset;
	}
	else {
		ptr[0] = offset; ptr[1] = 255-offset; ptr[2] = 0;
	}
}

float *createMandelbrotImage(int width, int height, float xS, float yS, float rad, int maxIteration)
{
	float *buffer = (float *) malloc(width * height * sizeof(float));
	if (buffer == NULL) {
		fprintf(stderr, "Could not create image buffer\n");
		return NULL;
	}

	// Create Mandelbrot set image

	int xPos, yPos;
	float minMu = maxIteration;
	float maxMu = 0;

	for (yPos=0 ; yPos<height ; yPos++)
	{
		float yP = (yS-rad) + (2.0f*rad/height)*yPos;

		for (xPos=0 ; xPos<width ; xPos++)
		{
			float xP = (xS-rad) + (2.0f*rad/width)*xPos;

			int iteration = 0;
			float x = 0;
			float y = 0;

			while (x*x + y*y <= 4 && iteration < maxIteration)
			{
				float tmp = x*x - y*y + xP;
				y = 2*x*y + yP;
				x = tmp;
				iteration++;
			}

			if (iteration < maxIteration) {
				float modZ = sqrt(x*x + y*y);
				float mu = iteration - (log(log(modZ))) / log(2);
				if (mu > maxMu) maxMu = mu;
				if (mu < minMu) minMu = mu;
				buffer[yPos * width + xPos] = mu;
			}
			else {
				buffer[yPos * width + xPos] = 0;
			}
		}
	}

	// Scale buffer values between 0 and 1
	int count = width * height;
	while (count) {
		count --;
		buffer[count] = (buffer[count] - minMu) / (maxMu - minMu);
	}

	return buffer;
}

int main(void)
{
    test_jpeg_file();
 }

编译需链接 -ljpeg

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值