jpeg.c

来自「ANFY特效」· C语言 代码 · 共 243 行

C
243
字号
#include <stdio.h>/* * These macros are used to read the input file. * To reuse this code in another application, you might need to change these. */#define EXIT_FAILURE 0#define EXIT_SUCCESS 1unsigned int image_height, image_width;static FILE * infile;		/* input JPEG file *//* Error exit handler */#define ERREXIT(msg)  { fprintf(stderr, "%s\n", msg); return 0; }/* Read one byte, testing for EOF */static int read_1_byte (void) {  int c;  c = getc(infile);  if (c == EOF)    ERREXIT("Premature EOF in JPEG file");  return c;}/* Read 2 bytes, convert to unsigned int *//* All 2-byte quantities in JPEG markers are MSB first */static unsigned int read_2_bytes (void) {  int c1, c2;  c1 = getc(infile);  if (c1 == EOF) ERREXIT("Premature EOF in JPEG file");  c2 = getc(infile);  if (c2 == EOF) ERREXIT("Premature EOF in JPEG file");  return (((unsigned int) c1) << 8) + ((unsigned int) c2);}/* * JPEG markers consist of one or more 0xFF bytes, followed by a marker * code byte (which is not an FF).  Here are the marker codes of interest * in this program. */#define M_SOF0  0xC0		/* Start Of Frame N */#define M_SOF1  0xC1		/* N indicates which compression process */#define M_SOF2  0xC2		/* Only SOF0-SOF2 are now in common use */#define M_SOF3  0xC3#define M_SOF5  0xC5		/* NB: codes C4 and CC are NOT SOF markers */#define M_SOF6  0xC6#define M_SOF7  0xC7#define M_SOF9  0xC9#define M_SOF10 0xCA#define M_SOF11 0xCB#define M_SOF13 0xCD#define M_SOF14 0xCE#define M_SOF15 0xCF#define M_SOI   0xD8		/* Start Of Image (beginning of datastream) *//* * Find the next JPEG marker and return its marker code. * We expect at least one FF byte, possibly more if the compressor used FFs * to pad the file. * There could also be non-FF garbage between markers.  The treatment of such * garbage is unspecified; we choose to skip over it but emit a warning msg. * NB: this routine must not be used after seeing SOS marker, since it will * not deal correctly with FF/00 sequences in the compressed image data... */static int next_marker (void) {  int c;  int discarded_bytes = 0;  /* Find 0xFF byte; count and skip any non-FFs. */  c = read_1_byte();  while (c != 0xFF) {    discarded_bytes++;    c = read_1_byte();  }  /* Get marker code byte, swallowing any duplicate FF bytes.  Extra FFs   * are legal as pad bytes, so don't count them in discarded_bytes.   */  do {    c = read_1_byte();  } while (c == 0xFF);  if (discarded_bytes != 0) {    fprintf(stderr, "Warning: garbage data found in JPEG file\n");  }  return c;}/* * Read the initial marker, which should be SOI. * For a JFIF file, the first two bytes of the file should be literally * 0xFF M_SOI.  To be more general, we could use next_marker, but if the * input file weren't actually JPEG at all, next_marker might read the whole * file and then return a misleading error message... */static int first_marker (void) {  int c1, c2;  c1 = getc(infile);  c2 = getc(infile);  if (c1 != 0xFF || c2 != M_SOI) ERREXIT("Not a JPEG file");  return c2;}/* * Most types of marker are followed by a variable-length parameter segment. * This routine skips over the parameters for any marker we don't otherwise * want to process. * Note that we MUST skip the parameter segment explicitly in order not to * be fooled by 0xFF bytes that might appear within the parameter segment; * such bytes do NOT introduce new markers. *//* Skip over an unknown or uninteresting variable-length marker */static void skip_variable (void) {  unsigned int length;  /* Get the marker parameter length count */  length = read_2_bytes();  /* Length includes itself, so must be at least 2 */  //if (length < 2) ERREXIT("Erroneous JPEG marker length");  if (length < 2) return;  length -= 2;  /* Skip over the remaining bytes */  while (length > 0) {    (void) read_1_byte();    length--;  }}/* * We are only interested in the image dimensions, so we stop at SOFn. */static int scan_JPEG_header(void) {  int marker = 0;// Expect SOI at start of file  if (first_marker() != M_SOI) ERREXIT("Expected SOI marker first");// Scan miscellaneous markers until we reach SOFn.  for (;;) {    marker = next_marker();    switch (marker) {// Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be,// treated as SOFn.  C4 in particular is actually DHT.    case M_SOF0:	/* Baseline */    case M_SOF1:	/* Extended sequential, Huffman */    case M_SOF2:	/* Progressive, Huffman */    case M_SOF3:	/* Lossless, Huffman */    case M_SOF5:	/* Differential sequential, Huffman */    case M_SOF6:	/* Differential progressive, Huffman */    case M_SOF7:	/* Differential lossless, Huffman */    case M_SOF9:	/* Extended sequential, arithmetic */    case M_SOF10:	/* Progressive, arithmetic */    case M_SOF11:	/* Lossless, arithmetic */    case M_SOF13:	/* Differential sequential, arithmetic */    case M_SOF14:	/* Differential progressive, arithmetic */    case M_SOF15:	/* Differential lossless, arithmetic */    // Process SOFn         (void) read_2_bytes();  /* usual parameter length count */         (void) read_1_byte();         image_height = read_2_bytes();         image_width = read_2_bytes();         return marker;      break;    default:			/* Anything else just gets skipped */      skip_variable();		/* we assume it has a parameter count... */      break;    }  } /* end loop */}int GetJPEGSize(char* cszJpegFile, unsigned int* iWidth, unsigned int* iHeight ){	// Open the input file.	if ((infile = fopen(cszJpegFile, "rb")) == NULL) {		fprintf(stderr, "can't open %s\n", cszJpegFile);		return EXIT_FAILURE;	}	// Clear high word of 32 bit int (the size is only 16 bit)	// (to be sure no trash is present...) 	image_height=0;	image_width=0;	// Scan the JPEG headers to get size	// (saved in global vars image_width and image_height)	if( scan_JPEG_header() == EXIT_FAILURE )		return EXIT_FAILURE;	*iWidth = image_width;	*iHeight = image_height;  	// All done, exit	fclose(infile);	return EXIT_SUCCESS;		/* suppress no-return-value warnings */}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?