📄 jpeg.c
字号:
/* jpeg.c - i/o routines for 'jpeg' format pictures */
/* based in part on 'example.c' from the IJG JPEG distribution */
/* based in part on 'xvjpeg.c' from the xv 3.10a */
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include "jpeglib.h"
#include "jerror.h"
#include "jpeg.h"
#ifndef size_t
#define size_t unsigned
#endif
#define SUCCESSED 0
#define FAILED 1
static void *mget_spc(int num,size_t size);
static void **get_img(int wd,int ht,size_t size);
static void free_img(void **pt);
struct my_error_mgr {
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
typedef struct my_error_mgr *my_error_ptr;
static void jpeg_error_exit(j_common_ptr cinfo) ;
static void jpeg_error_output(j_common_ptr cinfo) ;
/***************************************************************************/
/* JPEG INTERFACE ROUTINES *************************************************/
/***************************************************************************/
/**************************************************/
static void jpeg_error_exit(j_common_ptr cinfo)
{
my_error_ptr myerr;
myerr = (my_error_ptr) cinfo->err;
(*cinfo->err->output_message)(cinfo); /* display error message */
longjmp(myerr->setjmp_buffer, 1); /* return from error */
}
/**************************************************/
static void jpeg_error_output(j_common_ptr cinfo)
{
my_error_ptr myerr;
char buffer[JMSG_LENGTH_MAX];
myerr = (my_error_ptr) cinfo->err;
(*cinfo->err->format_message)(cinfo, buffer);
fprintf(stderr, "%s", buffer);
}
/***************************************************************************/
/* LOAD ROUTINES ***********************************************************/
/***************************************************************************/
/*******************************************/
int read_JPEG(FILE *infile, struct JPEG_img *jpeg_img)
{
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
JSAMPARRAY buffer;
int i, k, m, rowstride;
unsigned char magicno[3];
fseek(infile, 0, 0);
if ((i=fread(magicno, (size_t) 1, (size_t) 3, infile)) < 3) return(FAILED);
if (magicno[0]!=0xff||magicno[1]!=0xd8||magicno[2]!=0xff) return(FAILED);
fseek(infile, 0, 0);
/* Step 1: allocate and initialize JPEG compression object */
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpeg_error_exit;
jerr.pub.output_message = jpeg_error_output;
if (setjmp(jerr.setjmp_buffer)) {
/* if we're here, it blowed up... */
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return FAILED;
}
jpeg_create_decompress(&cinfo);
/* Step 2: specify data destination (eg, a file) */
jpeg_stdio_src(&cinfo, infile);
/* Step 3: read file parameters with jpeg_read_header() */
(void) jpeg_read_header(&cinfo, TRUE);
/* Step 4: set parameters for decompression */
/* do various cleverness regarding decompression parameters & such... */
jpeg_calc_output_dimensions(&cinfo);
jpeg_img->width = cinfo.output_width;
jpeg_img->height = cinfo.output_height;
if (cinfo.jpeg_color_space == JCS_GRAYSCALE) {
cinfo.out_color_space = JCS_GRAYSCALE;
cinfo.quantize_colors = FALSE;
} else {
cinfo.out_color_space = JCS_RGB;
cinfo.quantize_colors = FALSE; /* default: give 24-bit image to XV */
}
jpeg_calc_output_dimensions(&cinfo); /* note colorspace changes... */
rowstride = cinfo.output_width * cinfo.output_components;
if (cinfo.output_components != 1 && cinfo.output_components != 3) {
fprintf(stderr, "Can't read %d-plane JPEG file!", cinfo.output_components);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return FAILED;
}
if (cinfo.out_color_space == JCS_GRAYSCALE) {
jpeg_img->jpeg_type = 'g';
jpeg_img->mono = (unsigned char **)
get_img (jpeg_img->width, jpeg_img->height, sizeof (unsigned char));
} else {
jpeg_img->jpeg_type = 'c';
jpeg_img->color =(unsigned char ***) malloc (sizeof (unsigned char **) * 3);
for (i = 0; i < 3; i++)
jpeg_img->color[i] = (unsigned char **)
get_img (jpeg_img->width, jpeg_img->height, sizeof (unsigned char));
}
/* Step 5: Start decompressor */
jpeg_start_decompress(&cinfo);
/* Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
/* Make a one-row-high sample array that will go away when done with image */
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, rowstride, 1);
while (cinfo.output_scanline < cinfo.output_height) {
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
/* Assume put_scanline_someplace wants a pointer and sample count. */
if (cinfo.out_color_space == JCS_GRAYSCALE) {
for (i = 0; i < jpeg_img->width; i++)
jpeg_img->mono[cinfo.output_scanline-1][i] = buffer[0][i];
} else {
for (i= m = 0; i < jpeg_img->width; i++)
for (k = 0; k < 3; k++)
jpeg_img->color[k][cinfo.output_scanline-1][i] = buffer[0][m++];
}
}
/* Step 7: Finish decompression */
jpeg_finish_decompress(&cinfo);
/* Step 8: Release JPEG decompression object */
jpeg_destroy_decompress(&cinfo);
return SUCCESSED;
}
/***************************************************************************/
/* WRITE ROUTINES **********************************************************/
/***************************************************************************/
int write_JPEG(FILE *outfile, struct JPEG_img *jpeg_img,
int quality, int smooth)
{
struct jpeg_compress_struct cinfo;
struct my_error_mgr jerr;
JSAMPARRAY buffer;
int i, k, m, rowstride;
/* Step 1: allocate and initialize JPEG compression object */
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpeg_error_exit;
jerr.pub.output_message = jpeg_error_output;
if (setjmp(jerr.setjmp_buffer)) {
/* if we're here, it blowed up... */
jpeg_destroy_compress(&cinfo);
return FAILED;
}
jpeg_create_compress(&cinfo);
/* Step 2: specify data destination (eg, a file) */
jpeg_stdio_dest(&cinfo, outfile);
/* Step 3: set parameters for compression */
cinfo.image_width = jpeg_img->width;
cinfo.image_height = jpeg_img->height;
if (jpeg_img->jpeg_type == 'g') {
cinfo.input_components = 1;
cinfo.in_color_space = JCS_GRAYSCALE;
} else {
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
}
rowstride = cinfo.image_width * cinfo.input_components;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE);
cinfo.smoothing_factor = smooth;
/* Step 4: Start compressor */
jpeg_start_compress(&cinfo, TRUE);
/* Step 5: while (scan lines remain to be written) */
/* jpeg_write_scanlines(...); */
/* Make a one-row-high sample array that will go away when done with image */
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, rowstride, 1);
while (cinfo.next_scanline < cinfo.image_height) {
if (jpeg_img->jpeg_type == 'g') {
for (i = 0; i < jpeg_img->width; i++)
buffer[0][i] = jpeg_img->mono[cinfo.next_scanline][i];
} else {
for (i= m = 0; i < jpeg_img->width; i++)
for (k = 0; k < 3; k++)
buffer[0][m++] = jpeg_img->color[k][cinfo.next_scanline][i];
}
(void) jpeg_write_scanlines(&cinfo, buffer, (JDIMENSION) 1);
}
/* Step 6: Finish compression */
jpeg_finish_compress(&cinfo);
/* Step 7: release JPEG compression object */
jpeg_destroy_compress(&cinfo);
return SUCCESSED;
}
void free_JPEG (struct JPEG_img *img)
{
int i;
if (img->jpeg_type == 'g') {
free_img ((void **)img->mono);
}
else {
if (img->jpeg_type == 'c') {
for (i = 0; i < 3; i++) free_img ((void **)img->color[i]);
free((void *)img->color);
}
else
fprintf(stderr,"\nWarning: input structure to free routine is invalid\n");
}
}
void get_JPEG (struct JPEG_img *img, int height, int width, char jpeg_type)
{
int i;
img->height = height;
img->width = width;
img->jpeg_type = jpeg_type;
if (img->jpeg_type == 'g') {
img->mono =
(unsigned char **)get_img(img->width, img->height, sizeof(char));
}
else {
if (img->jpeg_type == 'c') {
img->color = mget_spc(3,sizeof(void *));
for (i = 0; i < 3; i++)
img->color[i] =
(unsigned char **)get_img(img->width, img->height, sizeof(char));
}
else
fprintf(stderr,"\nWarning: input structure to get_JPEG routine is invalid\n");
}
}
static void *mget_spc(int num,size_t size)
{
void *pt;
if( (pt=malloc((size_t)(num*size))) == NULL ) {
fprintf(stderr, "==> malloc() error\n");
exit(-1);
}
return(pt);
}
static void **get_img(int wd,int ht,size_t size)
{
int i;
void **ppt;
char *pt;
ppt = (void **)mget_spc(ht,sizeof(void *));
pt = (char *)mget_spc(wd*ht,size);
for(i=0; i<ht; i++) ppt[i] = pt + i*wd*size;
return(ppt);
}
static void free_img(void **pt)
{
free( (void *)pt[0]);
free( (void *)pt);
}
#ifdef TESTJPEG
int main(int argc, char **argv)
{
FILE *fin, *fout;
struct JPEG_img img_in, img_out;
int i,j,m,n;
if (argc != 3) {
fprintf(stderr, "\nUsage: %s infile outfile\n", argv[0]);
exit(-1);
}
if((fin = fopen(argv[1], "rb")) == NULL) {
fprintf(stderr, "\nError: can't read from %s\n", argv[1]);
exit(-1);
}
if (read_JPEG(fin, &img_in) == FAILED) {
fprintf(stderr, "\nError: JPEG read failed\n");
fclose(fin);
exit(-1);
}
fclose(fin);
if( img_in.jpeg_type == 'g') {
/* set up structure for output image */
get_JPEG ( &img_out, 2*img_in.height, 2*img_in.width, 'g' );
/* pixel replication */
for ( i = 0; i < img_in.height; i++ )
for ( j = 0; j < img_in.width; j++ )
for ( m = 0; m < 2; m++ )
for ( n = 0; n < 2; n++ ) {
img_out.mono[2*i+m][2*j+n] = img_in.mono[i][j];
}
} if( (img_in.jpeg_type == 'c') ) {
/* set up structure for output image */
get_JPEG ( &img_out, 2*img_in.height, 2*img_in.width, 'c' );
/* pixel replication */
for ( i = 0; i < img_in.height; i++ )
for ( j = 0; j < img_in.width; j++ )
for ( m = 0; m < 2; m++ )
for ( n = 0; n < 2; n++ ) {
img_out.color[0][2*i+m][2*j+n] = img_in.color[0][i][j];
img_out.color[1][2*i+m][2*j+n] = img_in.color[1][i][j];
img_out.color[2][2*i+m][2*j+n] = img_in.color[2][i][j];
}
} else {
fprintf(stderr, "\nUnknown Image type\n");
exit(-1);
}
if((fout = fopen(argv[2], "wb"))==NULL) {
fprintf(stderr,"\nError: can't write to %s\n", argv[2]);
exit(-1);
}
if( write_JPEG(fout, &img_out, 95, 0) == FAILED) { /* quality=95, smooth=0 */
fprintf(stderr,"\nError: can't write to JPEG image %s\n", argv[2]);
fclose(fout);
exit(-1);
}
fclose(fout);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -