⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tinyjpeg.c

📁 M8手机图片查看器
💻 C
📖 第 1 页 / 共 4 页
字号:
     sampling_factor = *stream++;     Q_table = *stream++;     c = &priv->component_infos[i];#if SANITY_CHECK     c->cid = cid;     if (Q_table >= COMPONENTS)       error("Bad Quantization table index (got %d, max allowed %d)\n", Q_table, COMPONENTS-1);#endif     c->Vfactor = sampling_factor&0xf;     c->Hfactor = sampling_factor>>4;     c->Q_table = priv->Q_tables[Q_table];     trace("Component:%d  factor:%dx%d  Quantization table:%d\n",           cid, c->Hfactor, c->Hfactor, Q_table );  }  priv->width = width;  priv->height = height;  trace("< SOF marker\n");  return 0;}static int parse_SOS(struct jdec_private *priv, const unsigned char *stream){  unsigned int i, cid, table;  unsigned int nr_components = stream[2];  trace("> SOS marker\n");#if SANITY_CHECK  if (nr_components != 3)    error("We only support YCbCr image\n");#endif  stream += 3;  for (i=0;i<nr_components;i++) {     cid = *stream++;     table = *stream++;#if SANITY_CHECK     if ((table&0xf)>=4)	error("We do not support more than 2 AC Huffman table\n");     if ((table>>4)>=4)	error("We do not support more than 2 DC Huffman table\n");     if (cid != priv->component_infos[i].cid)        error("SOS cid order (%d:%d) isn't compatible with the SOF marker (%d:%d)\n",	      i, cid, i, priv->component_infos[i].cid);     trace("ComponentId:%d  tableAC:%d tableDC:%d\n", cid, table&0xf, table>>4);#endif     priv->component_infos[i].AC_table = &priv->HTAC[table&0xf];     priv->component_infos[i].DC_table = &priv->HTDC[table>>4];  }  priv->stream = stream+3;  trace("< SOS marker\n");  return 0;}static int parse_DHT(struct jdec_private *priv, const unsigned char *stream){  unsigned int count, i;  unsigned char huff_bits[17];  int length, index;  length = be16_to_cpu(stream) - 2;  stream += 2;	/* Skip length */  trace("> DHT marker (length=%d)\n", length);  while (length>0) {     index = *stream++;     /* We need to calculate the number of bytes 'vals' will takes */     huff_bits[0] = 0;     count = 0;     for (i=1; i<17; i++) {	huff_bits[i] = *stream++;	count += huff_bits[i];     }#if SANITY_CHECK     if (count >= HUFFMAN_BITS_SIZE)       error("No more than %d bytes is allowed to describe a huffman table", HUFFMAN_BITS_SIZE);     if ( (index &0xf) >= HUFFMAN_TABLES)       error("No more than %d Huffman tables is supported (got %d)\n", HUFFMAN_TABLES, index&0xf);     trace("Huffman table %s[%d] length=%d\n", (index&0xf0)?"AC":"DC", index&0xf, count);#endif     if (index & 0xf0 )       build_huffman_table(huff_bits, stream, &priv->HTAC[index&0xf]);     else       build_huffman_table(huff_bits, stream, &priv->HTDC[index&0xf]);     length -= 1;     length -= 16;     length -= count;     stream += count;  }  trace("< DHT marker\n");  return 0;}static int parse_DRI(struct jdec_private *priv, const unsigned char *stream){  unsigned int length;  trace("> DRI marker\n");  length = be16_to_cpu(stream);#if SANITY_CHECK  if (length != 4)    error("Length of DRI marker need to be 4\n");#endif  priv->restart_interval = be16_to_cpu(stream+2);#if DEBUG  trace("Restart interval = %d\n", priv->restart_interval);#endif  trace("< DRI marker\n");  return 0;}static void resync(struct jdec_private *priv){  int i;  /* Init DC coefficients */  for (i=0; i<COMPONENTS; i++)     priv->component_infos[i].previous_DC = 0;  priv->reservoir = 0;  priv->nbits_in_reservoir = 0;  if (priv->restart_interval > 0)    priv->restarts_to_go = priv->restart_interval;  else    priv->restarts_to_go = -1;}static int find_next_rst_marker(struct jdec_private *priv){  int rst_marker_found = 0;  int marker;  const unsigned char *stream = priv->stream;  /* Parse marker */  while (!rst_marker_found)   {     while (*stream++ != 0xff)      {	if (stream >= priv->stream_end)	  error("EOF while search for a RST marker.");      }     /* Skip any padding ff byte (this is normal) */     while (*stream == 0xff)       stream++;     marker = *stream++;     if ((RST+priv->last_rst_marker_seen) == marker)       rst_marker_found = 1;     else if (marker >= RST && marker <= RST7)       error("Wrong Reset marker found, abording");     else if (marker == EOI)       return 0;   }  trace("RST Marker %d found at offset %d\n", priv->last_rst_marker_seen, stream - priv->stream_begin);  priv->stream = stream;  priv->last_rst_marker_seen++;  priv->last_rst_marker_seen &= 7;  return 0;}static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream){  int chuck_len;  int marker;  int sos_marker_found = 0;  int dht_marker_found = 0;  const unsigned char *next_chunck;  /* Parse marker */  while (!sos_marker_found)   {     if (*stream++ != 0xff)       goto bogus_jpeg_format;     /* Skip any padding ff byte (this is normal) */     while (*stream == 0xff)       stream++;     marker = *stream++;     chuck_len = be16_to_cpu(stream);     next_chunck = stream + chuck_len;     switch (marker)      {       case SOF:	 if (parse_SOF(priv, stream) < 0)	   return -1;	 break;       case DQT:	 if (parse_DQT(priv, stream) < 0)	   return -1;	 break;       case SOS:	 if (parse_SOS(priv, stream) < 0)	   return -1;	 sos_marker_found = 1;	 break;       case DHT:	 if (parse_DHT(priv, stream) < 0)	   return -1;	 dht_marker_found = 1;	 break;       case DRI:	 if (parse_DRI(priv, stream) < 0)	   return -1;	 break;       default:	 trace("> Unknown marker %2.2x\n", marker);	 break;      }     stream = next_chunck;   }  if (!dht_marker_found) {    trace("No Huffman table loaded, using the default one\n");    build_default_huffman_tables(priv);  }#ifdef SANITY_CHECK  if (   (priv->component_infos[cY].Hfactor < priv->component_infos[cCb].Hfactor)      || (priv->component_infos[cY].Hfactor < priv->component_infos[cCr].Hfactor))    error("Horizontal sampling factor for Y should be greater than horitontal sampling factor for Cb or Cr\n");  if (   (priv->component_infos[cY].Vfactor < priv->component_infos[cCb].Vfactor)      || (priv->component_infos[cY].Vfactor < priv->component_infos[cCr].Vfactor))    error("Vertical sampling factor for Y should be greater than vertical sampling factor for Cb or Cr\n");  if (   (priv->component_infos[cCb].Hfactor!=1)       || (priv->component_infos[cCr].Hfactor!=1)      || (priv->component_infos[cCb].Vfactor!=1)      || (priv->component_infos[cCr].Vfactor!=1))    error("Sampling other than 1x1 for Cr and Cb is not supported");#endif  return 0;bogus_jpeg_format:  trace("Bogus jpeg format\n");  return -1;}/******************************************************************************* * * Functions exported of the library. * * Note: Some applications can access directly to internal pointer of the * structure. It's is not recommended, but if you have many images to * uncompress with the same parameters, some functions can be called to speedup * the decoding. * ******************************************************************************//** * Allocate a new tinyjpeg decoder object. * * Before calling any other functions, an object need to be called. */struct jdec_private *tinyjpeg_init(void){  struct jdec_private *priv;   priv = (struct jdec_private *)calloc(1, sizeof(struct jdec_private));  if (priv == NULL)    return NULL;  return priv;}/** * Free a tinyjpeg object. * * No others function can be called after this one. */void tinyjpeg_free(struct jdec_private *priv){  int i;  for (i=0; i<COMPONENTS; i++) {     if (priv->components[i])       free(priv->components[i]);     priv->components[i] = NULL;  }  free(priv);}/** * Initialize the tinyjpeg object and prepare the decoding of the stream. * * Check if the jpeg can be decoded with this jpeg decoder. * Fill some table used for preprocessing. */int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size){  int ret;  /* Identify the file */  if ((buf[0] != 0xFF) || (buf[1] != SOI))    error("Not a JPG file ?\n");  priv->stream_begin = buf+2;  priv->stream_length = size-2;  priv->stream_end = priv->stream_begin + priv->stream_length;  ret = parse_JFIF(priv, priv->stream_begin);  return ret;}static const decode_MCU_fct decode_mcu_3comp_table[4] = {   decode_MCU_1x1_3planes,   decode_MCU_1x2_3planes,   decode_MCU_2x1_3planes,   decode_MCU_2x2_3planes,};static const decode_MCU_fct decode_mcu_1comp_table[4] = {   decode_MCU_1x1_1plane,   decode_MCU_1x2_1plane,   decode_MCU_2x1_1plane,   decode_MCU_2x2_1plane,};static const convert_colorspace_fct convert_colorspace_yuv420p[4] = {   YCrCB_to_YUV420P_1x1,   YCrCB_to_YUV420P_1x2,   YCrCB_to_YUV420P_2x1,   YCrCB_to_YUV420P_2x2,};static const convert_colorspace_fct convert_colorspace_rgb24[4] = {   YCrCB_to_RGB24_1x1,   YCrCB_to_RGB24_1x2,   YCrCB_to_RGB24_2x1,   YCrCB_to_RGB24_2x2,};static const convert_colorspace_fct convert_colorspace_bgr24[4] = {   YCrCB_to_BGR24_1x1,   YCrCB_to_BGR24_1x2,   YCrCB_to_BGR24_2x1,   YCrCB_to_BGR24_2x2,};static const convert_colorspace_fct convert_colorspace_grey[4] = {   YCrCB_to_Grey_1x1,   YCrCB_to_Grey_1x2,   YCrCB_to_Grey_2x1,   YCrCB_to_Grey_2x2,};/** * Decode and convert the jpeg image into @pixfmt@ image * * Note: components will be automaticaly allocated if no memory is attached. */int tinyjpeg_decode(struct jdec_private *priv, int pixfmt){  unsigned int x, y, xstride_by_mcu, ystride_by_mcu;  unsigned int bytes_per_blocklines[3], bytes_per_mcu[3];  decode_MCU_fct decode_MCU;  const decode_MCU_fct *decode_mcu_table;  const convert_colorspace_fct *colorspace_array_conv;  convert_colorspace_fct convert_to_pixfmt;  if (setjmp(priv->jump_state))    return -1;  /* To keep gcc happy initialize some array */  bytes_per_mcu[1] = 0;  bytes_per_mcu[2] = 0;  bytes_per_blocklines[1] = 0;  bytes_per_blocklines[2] = 0;  decode_mcu_table = decode_mcu_3comp_table;  switch (pixfmt) {     case TINYJPEG_FMT_YUV420P:       colorspace_array_conv = convert_colorspace_yuv420p;       if (priv->components[0] == NULL)	 priv->components[0] = (uint8_t *)malloc(priv->width * priv->height);       if (priv->components[1] == NULL)	 priv->components[1] = (uint8_t *)malloc(priv->width * priv->height/4);       if (priv->components[2] == NULL)	 priv->components[2] = (uint8_t *)malloc(priv->width * priv->height/4);       bytes_per_blocklines[0] = priv->width;       bytes_per_blocklines[1] = priv->width/4;       bytes_per_blocklines[2] = priv->width/4;       bytes_per_mcu[0] = 8;       bytes_per_mcu[1] = 4;       bytes_per_mcu[2] = 4;       break;     case TINYJPEG_FMT_RGB24:       colorspace_array_conv = convert_colorspace_rgb24;       if (priv->components[0] == NULL)	 priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3);       bytes_per_blocklines[0] = priv->width * 3;       bytes_per_mcu[0] = 3*8;       break;     case TINYJPEG_FMT_BGR24:       colorspace_array_conv = convert_colorspace_bgr24;       if (priv->components[0] == NULL)	 priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3);       bytes_per_blocklines[0] = priv->width * 3;       bytes_per_mcu[0] = 3*8;       break;     case TINYJPEG_FMT_GREY:       decode_mcu_table = decode_mcu_1comp_table;       colorspace_array_conv = convert_colorspace_grey;       if (priv->components[0] == NULL)	 priv->components[0] = (uint8_t *)malloc(priv->width * priv->height);       bytes_per_blocklines[0] = priv->width;       bytes_per_mcu[0] = 8;       break;     default:       trace("Bad pixel format\n");       return -1;  }  xstride_by_mcu = ystride_by_mcu = 8;  if ((priv->component_infos[cY].Hfactor | priv->component_infos[cY].Vfactor) == 1) {     decode_MCU = decode_mcu_table[0];     convert_to_pixfmt = colorspace_array_conv[0];     trace("Use decode 1x1 sampling\n");  } else if (priv->component_infos[cY].Hfactor == 1) {     decode_MCU = decode_mcu_table[1];     convert_to_pixfmt = colorspace_array_conv[1];     ystride_by_mcu = 16;     trace("Use decode 1x2 sampling (not supported)\n");  } else if (priv->component_infos[cY].Vfactor == 2) {     decode_MCU = decode_mcu_table[3];     convert_to_pixfmt = colorspace_array_conv[3];     xstride_by_mcu = 16;     ystride_by_mcu = 16;     trace("Use decode 2x2 sampling\n");  } else {     decode_MCU = decode_mcu_table[2];     convert_to_pixfmt = colorspace_array_conv[2];     xstride_by_mcu = 16;     trace("Use decode 2x1 sampling\n");  }  resync(priv);  /* Don't forget to that block can be either 8 or 16 lines */  bytes_per_blocklines[0] *= ystride_by_mcu;  bytes_per_blocklines[1] *= ystride_by_mcu;  bytes_per_blocklines[2] *= ystride_by_mcu;  bytes_per_mcu[0] *= xstride_by_mcu/8;  bytes_per_mcu[1] *= xstride_by_mcu/8;  bytes_per_mcu[2] *= xstride_by_mcu/8;  /* Just the decode the image by macroblock (size is 8x8, 8x16, or 16x16) */  for (y=0; y < priv->height/ystride_by_mcu; y++)   {     //trace("Decoding row %d\n", y);     priv->plane[0] = priv->components[0] + (y * bytes_per_blocklines[0]);     priv->plane[1] = priv->components[1] + (y * bytes_per_blocklines[1]);     priv->plane[2] = priv->components[2] + (y * bytes_per_blocklines[2]);     for (x=0; x < priv->width; x+=xstride_by_mcu)      {	decode_MCU(priv);	convert_to_pixfmt(priv);	priv->plane[0] += bytes_per_mcu[0];	priv->plane[1] += bytes_per_mcu[1];	priv->plane[2] += bytes_per_mcu[2];	if (priv->restarts_to_go>0)	 {	   priv->restarts_to_go--;	   if (priv->restarts_to_go == 0)	    {	      priv->stream -= (priv->nbits_in_reservoir/8);	      resync(priv);	      if (find_next_rst_marker(priv) < 0)		return -1;	    }	 }      }   }  trace("Input file size: %d\n", priv->stream_length+2);  trace("Input bytes actually read: %d\n", priv->stream - priv->stream_begin + 2);  return 0;}const char *tinyjpeg_get_errorstring(struct jdec_private *priv){  /* FIXME: the error string must be store in the context */  priv = priv;  return error_string;}void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height){  *width = priv->width;  *height = priv->height;}int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components){  int i;  for (i=0; priv->components[i] && i<COMPONENTS; i++)    components[i] = priv->components[i];  return 0;}int tinyjpeg_set_components(struct jdec_private *priv, unsigned char **components, unsigned int ncomponents){  unsigned int i;  if (ncomponents > COMPONENTS)    ncomponents = COMPONENTS;  for (i=0; i<ncomponents; i++)    priv->components[i] = components[i];  return 0;}int tinyjpeg_set_flags(struct jdec_private *priv, int flags){  int oldflags = priv->flags;  priv->flags = flags;  return oldflags;}

⌨️ 快捷键说明

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