djpeg.c

来自「JPEG解压源码」· C语言 代码 · 共 751 行 · 第 1/2 页

C
751
字号
    } else {      usage();			/* bogus switch */    }  }  return argn;			/* return index of next arg (file name) */}/* * Marker processor for COM and interesting APPn markers. * This replaces the library's built-in processor, which just skips the marker. * We want to print out the marker as text, to the extent possible. * Note this code relies on a non-suspending data source. */LOCAL(unsigned int)jpeg_getc (j_decompress_ptr cinfo)/* Read next byte */{  struct jpeg_source_mgr * datasrc = cinfo->src;  if (datasrc->bytes_in_buffer == 0) {    if (! (*datasrc->fill_input_buffer) (cinfo))      ERREXIT(cinfo, JERR_CANT_SUSPEND);  }  datasrc->bytes_in_buffer--;  return GETJOCTET(*datasrc->next_input_byte++);}METHODDEF(boolean)print_text_marker (j_decompress_ptr cinfo){  boolean traceit = (cinfo->err->trace_level >= 1);  INT32 length;  unsigned int ch;  unsigned int lastch = 0;  length = jpeg_getc(cinfo) << 8;  length += jpeg_getc(cinfo);  length -= 2;			/* discount the length word itself */  if (traceit) {    if (cinfo->unread_marker == JPEG_COM)      fprintf(stderr, "Comment, length %ld:\n", (long) length);    else			/* assume it is an APPn otherwise */      fprintf(stderr, "APP%d, length %ld:\n",	      cinfo->unread_marker - JPEG_APP0, (long) length);  }  while (--length >= 0) {    ch = jpeg_getc(cinfo);    if (traceit) {      /* Emit the character in a readable form.       * Nonprintables are converted to \nnn form,       * while \ is converted to \\.       * Newlines in CR, CR/LF, or LF form will be printed as one newline.       */      if (ch == '\r') {	fprintf(stderr, "\n");      } else if (ch == '\n') {	if (lastch != '\r')	  fprintf(stderr, "\n");      } else if (ch == '\\') {	fprintf(stderr, "\\\\");      } else if (isprint(ch)) {	putc(ch, stderr);      } else {	fprintf(stderr, "\\%03o", ch);      }      lastch = ch;    }  }  if (traceit)    fprintf(stderr, "\n");  return TRUE;}/* * Check for overwrite of an existing file; clear it with user */#ifndef NO_OVERWRITE_CHECKLOCAL(boolean)is_write_ok (char * outfname){  FILE * ofile;  int ch;  ofile = fopen(outfname, READ_BINARY);  if (ofile == NULL)    return TRUE;		/* not present */  fclose(ofile);		/* oops, it is present */  for (;;) {    fprintf(stderr, "%s already exists, overwrite it? [y/n] ",	    outfname);    fflush(stderr);    ch = getc(stdin);    if (ch != '\n')		/* flush rest of line */      while (getc(stdin) != '\n')	/* nothing */;    switch (ch) {    case 'Y':    case 'y':      return TRUE;    case 'N':    case 'n':      return FALSE;    /* otherwise, ask again */    }  }}#endif/* * Process a single input file name, and return its index in argv[]. * File names at or to left of old_file_index have been processed already. */LOCAL(int)process_one_file (int argc, char **argv, int old_file_index){  struct jpeg_decompress_struct cinfo;  struct jpeg_error_mgr jerr;  char *infilename;  char workfilename[PATH_MAX];  const char *default_extension = NULL;#ifdef PROGRESS_REPORT  struct cdjpeg_progress_mgr progress;#endif  int file_index;  djpeg_dest_ptr dest_mgr = NULL;  FILE * input_file = NULL;  FILE * output_file = NULL;  JDIMENSION num_scanlines;  /* Initialize the JPEG decompression object with default error handling. */  cinfo.err = jpeg_std_error(&jerr);  jpeg_create_decompress(&cinfo);  /* Add some application-specific error messages (from cderror.h) */  jerr.addon_message_table = cdjpeg_message_table;  jerr.first_addon_message = JMSG_FIRSTADDONCODE;  jerr.last_addon_message = JMSG_LASTADDONCODE;  /* Insert custom marker processor for COM and APP12.   * APP12 is used by some digital camera makers for textual info,   * so we provide the ability to display it as text.   * If you like, additional APPn marker types can be selected for display,   * but don't try to override APP0 or APP14 this way (see libjpeg.doc).   */  jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);  jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);  /* Now safe to enable signal catcher. */#ifdef NEED_SIGNAL_CATCHER  enable_signal_catcher((j_common_ptr) &cinfo);#endif  /* Scan command line to find next file name.   * It is convenient to use just one switch-parsing routine, but the switch   * values read here are ignored; we will rescan the switches after opening   * the input file.   * (Exception: tracing level set here controls verbosity for COM markers   * found during jpeg_read_header...)   */  file_index = parse_switches(&cinfo, argc, argv, old_file_index, FALSE);  if (file_index >= argc) {    fprintf(stderr, "%s: missing input file name\n", progname);    usage();  }  /* Open the input file. */  infilename = argv[file_index];  if ((input_file = fopen(infilename, READ_BINARY)) == NULL) {    fprintf(stderr, "%s: can't open %s\n", progname, infilename);    goto fail;  }#ifdef PROGRESS_REPORT  start_progress_monitor((j_common_ptr) &cinfo, &progress);#endif  /* Specify data source for decompression */  jpeg_stdio_src(&cinfo, input_file);  /* Read file header, set default decompression parameters */  (void) jpeg_read_header(&cinfo, TRUE);  /* Adjust default decompression parameters by re-parsing the options */  file_index = parse_switches(&cinfo, argc, argv, old_file_index, TRUE);  /* Initialize the output module now to let it override any crucial   * option settings (for instance, GIF wants to force color quantization).   */  switch (requested_fmt) {#ifdef BMP_SUPPORTED  case FMT_BMP:    dest_mgr = jinit_write_bmp(&cinfo, FALSE);    default_extension = ".bmp";    break;  case FMT_OS2:    dest_mgr = jinit_write_bmp(&cinfo, TRUE);    default_extension = ".bmp";    break;#endif#ifdef GIF_SUPPORTED  case FMT_GIF:    dest_mgr = jinit_write_gif(&cinfo);    default_extension = ".gif";    break;#endif#ifdef PPM_SUPPORTED  case FMT_PPM:    dest_mgr = jinit_write_ppm(&cinfo);    default_extension = ".ppm";    break;#endif#ifdef RLE_SUPPORTED  case FMT_RLE:    dest_mgr = jinit_write_rle(&cinfo);    default_extension = ".rle";    break;#endif#ifdef TARGA_SUPPORTED  case FMT_TARGA:    dest_mgr = jinit_write_targa(&cinfo);    default_extension = ".tga";    break;#endif  default:    ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);    break;  }  /* If user didn't supply -outfile switch, select output file name. */  if (outfilename == NULL) {    int i;    outfilename = workfilename;    /* Make outfilename be infilename with appropriate extension */    strcpy(outfilename, infilename);    for (i = strlen(outfilename)-1; i >= 0; i--) {      switch (outfilename[i]) {      case ':':      case '/':      case '\\':	i = 0;			/* stop scanning */	break;      case '.':	outfilename[i] = '\0';	/* lop off existing extension */	i = 0;			/* stop scanning */	break;      default:	break;			/* keep scanning */      }    }    strcat(outfilename, default_extension);  }  fprintf(stderr, "Decompressing %s => %s\n", infilename, outfilename);#ifndef NO_OVERWRITE_CHECK  if (! is_write_ok(outfilename))    goto fail;#endif  /* Open the output file. */  if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {    fprintf(stderr, "%s: can't create %s\n", progname, outfilename);    goto fail;  }  dest_mgr->output_file = output_file;  /* Start decompressor */  (void) jpeg_start_decompress(&cinfo);  /* Write output file header */  (*dest_mgr->start_output) (&cinfo, dest_mgr);  /* Process data */  while (cinfo.output_scanline < cinfo.output_height) {    num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,					dest_mgr->buffer_height);    (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);  }#ifdef PROGRESS_REPORT  /* Hack: count final pass as done in case finish_output does an extra pass.   * The library won't have updated completed_passes.   */  progress.pub.completed_passes = progress.pub.total_passes;#endif  /* Finish decompression and release memory.   * I must do it in this order because output module has allocated memory   * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.   */  (*dest_mgr->finish_output) (&cinfo, dest_mgr);  (void) jpeg_finish_decompress(&cinfo);  /* Clean up and exit */fail:  jpeg_destroy_decompress(&cinfo);  if (input_file != NULL) fclose(input_file);  if (output_file != NULL) fclose(output_file);#ifdef PROGRESS_REPORT  end_progress_monitor((j_common_ptr) &cinfo);#endif  /* Disable signal catcher. */#ifdef NEED_SIGNAL_CATCHER  enable_signal_catcher((j_common_ptr) NULL);#endif  return file_index;}/* * The main program. */intmain (int argc, char **argv){  int file_index;  /* On Mac, fetch a command line. */#ifdef USE_CCOMMAND  argc = ccommand(&argv);#endif#ifdef MSDOS  progname = "djpeg";		/* DOS tends to be too verbose about argv[0] */#else  progname = argv[0];  if (progname == NULL || progname[0] == 0)    progname = "djpeg";		/* in case C library doesn't provide it */#endif  /* The default maxmem must be computed only once at program startup,   * since releasing memory with free() won't give it back to the OS.   */#ifdef FREE_MEM_ESTIMATE  default_maxmem = FREE_MEM_ESTIMATE;#else  default_maxmem = 0;#endif  /* Scan command line, parse switches and locate input file names */  if (argc < 2)    usage();			/* nothing on the command line?? */  file_index = 0;  while (file_index < argc-1)    file_index = process_one_file(argc, argv, file_index);  /* All done. */  exit(EXIT_SUCCESS);  return 0;			/* suppress no-return-value warnings */}

⌨️ 快捷键说明

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