文档章节

Tiny Jpeg Decoder (JPEG解码程序) 源代码分析 2:解码数据

雷霄骅
 雷霄骅
发布于 2014/08/16 13:40
字数 979
阅读 94
收藏 0

注:分析Tiny Jpeg Decoder源代码的文章:

Tiny Jpeg Decoder (JPEG解码程序) 源代码分析 1:解码文件头

Tiny Jpeg Decoder (JPEG解码程序) 源代码分析 2:解码数据

===================


Tiny Jpeg Decoder是一个可以用于嵌入式系统的JPEG解码器。也可以在Windows上编译通过。在此分析一下它部分的源代码,辅助学习JPEG解码知识。

通过TinyJpeg可以将JPEG(*.jpg)文件解码为YUV(*.yuv)或者RGB(*.tga)文件。

真正的解码数据开始于tinyjpeg_decode()函数:

注意:本代码中包含部分自己写的代码,用于提取DCT系数表,解码后亮度数据表等数据。

/**
 * 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;

  //-------------------------------------------
	FILE *fp;
	char *temp;
	int j,k;
  //-------------------------------------------

  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:
#if TRACE_PARAM
		 fprintf(param_trace,"Bad pixel format\n");
		 fflush(param_trace);
#endif
       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];
#if TRACE_PARAM
     fprintf(param_trace,"Use decode 1x1 sampling\n");
	 fflush(param_trace);
#endif
  } 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;
#if TRACE_PARAM
     fprintf(param_trace,"Use decode 1x2 sampling (not supported)\n");
	 fflush(param_trace);
#endif
  } 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;
#if TRACE_PARAM 
	 fprintf(param_trace,"Use decode 2x2 sampling\n");
	 fflush(param_trace);
#endif
  } else {
     decode_MCU = decode_mcu_table[2];
     convert_to_pixfmt = colorspace_array_conv[2];
     xstride_by_mcu = 16;
#if TRACE_PARAM
     fprintf(param_trace,"Use decode 2x1 sampling\n");
	 fflush(param_trace);
#endif
  }

  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);

//DCT系数-----------------------------------------------------------
		//temp=(char *)priv->component_infos->DCT;
		//if(y==4&&x==xstride_by_mcu*3){
		if(priv->dlg->m_vijpgoutputdct.GetCheck()==1){
			fp = fopen("DCT系数表.txt", "a+");
			//fwrite(temp,64,1,fp);
			fprintf(fp,"第%d行,第%d列\n",y,x/xstride_by_mcu);
			for(j=0;j<64;j++){
			fprintf(fp,"%d ",priv->component_infos[cY].DCT[j]);
			}
			fprintf(fp,"\n");
			fclose(fp);
		}
#if TRACE_PARAM
		fprintf(param_trace,"\n第3行,第4列\n");
		for(j=0;j<8;j++){
	 		for(k=0;k<8;k++){
				fprintf(param_trace,"%d ",priv->component_infos[cY].DCT[j*8+k]);
			}
			fprintf(param_trace,"\n");
		}
		fprintf(fp,"\n-----------------------\n");
		fflush(param_trace);
#endif
		//}

//解码后系数(Y)---------------------------------------------------
		//temp=(char *)priv->Y;
		//if(y==4&&x==xstride_by_mcu*3){
		if(priv->dlg->m_vijpgoutputy.GetCheck()==1){
			fp = fopen("解码后Y系数表.txt", "a+");
			//fwrite(temp,64*4,1,fp);
			fprintf(fp,"第%d行,第%d列\n",y,x/xstride_by_mcu);
			for(j=0;j<64*4;j++){
			fprintf(fp,"%d ",priv->Y[j]);
			}
			fprintf(fp,"\n");
			fclose(fp);
		}
#if TRACE_PARAM
		fprintf(param_trace,"第3行,第4列\n");
		for(j=0;j<8;j++){
	 		for(k=0;k<8;k++){
				fprintf(param_trace,"%d ",priv->Y[j*8+k]);
			}
			fprintf(param_trace,"\n");
		}
		fprintf(fp,"\n-----------------------\n");
		fflush(param_trace);
#endif
		//}

//------------------------------------------------------------------
		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;
			}
		 }
      }
   }
#if TRACE_PARAM
  fprintf(param_trace,"Input file size: %d\n", priv->stream_length+2);
  fprintf(param_trace,"Input bytes actually read: %d\n", priv->stream - priv->stream_begin + 2);
  fflush(param_trace);
#endif

  return 0;
}


主页:http://www.saillard.org/programs_and_patches/tinyjpegdecoder/

源代码下载:http://download.csdn.net/detail/leixiaohua1020/6383115


本文转载自:http://blog.csdn.net/leixiaohua1020/article/details/12618335

雷霄骅

雷霄骅

粉丝 213
博文 419
码字总数 2129
作品 4
朝阳
程序员
私信 提问
加载中

评论(0)

NIOS2随笔——JPEG解码与VGA显示

1. 系统概述 本设计采用NIOS2 32位处理器,通过SPI接口将SD/TF卡中的JPEG图片数据读取到内存中,SD/TF卡的文件系统为FAT32,NIOS2软件实现JPEG解码后,启动framereader和Clocked Video Outpu...

shugenyin
2017/01/08
0
0
常见图片格式详解(三)---JPEG

JPEG简介 JPEG是一种比较成熟的有损的图像压缩格式,经过JPEG压缩,图像质量会有所损失,但是,人眼不容易分辨出来这种差别。jpeg图像在质量和存储空间得到了一个相对平衡的状态。不过jpeg文...

mmlf
2018/03/19
0
0
英伟达开源数据增强和数据解码库,解决计算机视觉性能瓶颈

     新智元编译   来源:NVIDIA   编辑:肖琴   【新智元导读】在CVPR 2018大会上,英伟达开源了数据增强库DALI和数据解码库nvJPEG。   在CVPR 2018大会上,英伟达开源了数据增...

深度学习
2018/06/25
0
0
数据压缩实验五 JPEG原理分析及JPEG解码器的调试

一、实验原理 1、JPEG图像压缩标准基本介绍 JPEG 是Joint Photographic Experts Group(联合图像专家小组)的缩写,是第一个国际图像压缩标准。JPEG图像压缩算法能够在提供良好的压缩性能的同...

zgyggy
2017/05/23
0
0
[开发者简报第十二期] Web历史 | Vim历史 | React的完整介绍 | JavaScript SEO | 编程算法 | JavaScript 代码规范

文摘 了解渐进式JPEG和WebP格式 什么是渐进式jpeg 渐进式JPEG是使用与典型标准JPEG不同的编码过程创建的图像。传统上,JPEG从上到下,从左到右进行编码和解码。这被称为基线编码。但是,渐进...

developergang
2019/07/26
3.4K
2

没有更多内容

加载失败,请刷新页面

加载更多

手把手教你搭建 ELK 实时日志分析平台

本篇文章主要是手把手教你搭建 ELK 实时日志分析平台,那么,ELK 到底是什么呢? ELK 是三个开源项目的首字母缩写,这三个项目分别是:Elasticsearch、Logstash 和 Kibana。 Elasticsearch ...

武培轩
45分钟前
52
0
直播报名 | Service Mesh技术实践分享

近年来,云原生(Cloud Native)逐渐成为一个技术领域内的流行语,热度居高不下。企业正在加速拥抱云原生架构,以此缩短产品发布周期、敏捷响应市场需求,继而从云计算服务中提炼新的价值和技...

百度开发者中心
56分钟前
57
0
Qt 实现QTableView单元格多按钮效果

实现效果预览: 思路: 使用Qt的委托类独自渲染表格的某一列,如上图字段2的那一列。该一个单元格放入多个按钮,重写 QStyledItemDelegate 委托类 paint 方法即可实现上图效果。 代码: 委托...

剑是SR剑
57分钟前
71
0
第一章 引子--总结

1.开发过程中对公共、通用的素材做好沉淀。 2.厚平台、薄应用:理解是底层较多的基础公共平台、薄应用 最上层的应用,具体实现 3.烟卤式系统建设:一个业务一个系统,比如天猫和淘宝,开始是...

zxx901221
今天
57
0
利用docker来部署go应用程序

利用docker实现go程序的快速部署 最近很长一段时间一直通过各种渠道去了解国内外有关devops方面的实践,感受很多的知识点都特别的分散,所以想通过系统的整理来巩固相应的知识体系。接下来会...

罗布V
今天
64
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部