作者:朱金灿

来源:http://blog.csdn.net/clever101

PCI的系统格式pix是一个设计很巧妙的遥感图像格式,而且其设计巧妙之处不止一处两处,这些都有待我日后一一去摸索。今天就具体谈谈它的设计巧妙的一个地方——它是认真地考虑图像的大小端字节存储的问题并作出了针对性的设计。

关于计算机处理器的大小端字节序存储的基础知识不在本文的论述范围之列,有兴趣的读者可以阅读《深入理解计算机系统》这本书。首先要讨论的问题是图像作为一种二进制文件格式,是否有大小端存储之分?我认为是有的。可能有些读者对此有疑问:大小端不是对处理器而言的吗?图像怎么有大小端存储之分的呢?实际上是有的。我们想象这样一个场景:假如一个图像是在一个大端机器创建并处理了,毫无疑问它是按大端的字节序存储的,现在用户把它拷贝到一个小端机器上浏览,软件不知道它是按大端存储还是按小端存储的,就想当然地按小端字节序来浏览,自然就看到一堆乱码而不是一个预想中的有序图像。这个问题其实是一直存在的,为什么我们几乎很少碰到?一是我们日常接触的都是8位图像(8位图像不存在字节序存储问题,大于8位的图像在遥感领域很常见),二则很可能是因为PC领域一直是由intel的小端模式的x86架构所统治。

现在问题来了:如何解决这个问题?显然要根本解决问题是图像文件要提供记忆自己是哪种字节序来存储的功能。pix文件正是基于这种考虑,在每个波段头都存储了它是按哪种字节序存储的标记(绝妙的是它是每个波段都有这个标记,这就意味着它的每个波段是可以按照不同的字节序存储的)。现在我们看看pix文件是如何具体实现的。这个我们从PCI公司提供的读写pix文件的开源库中找到答案。首先源码中的PCIDSK::Create函数是负责创建pix文件的。在pix文件中每个波段头都有1024字节用于存储波段的描述信息,其中它的第201个字节就是用于保存是大端字节序存储还是小端字节序存储的,设为'S'为小端存储,设为'N'为大端存储。注意要直接指定ih.buffer[201]='S';而不能使用它的设置函数,如ih.Put('S',201,1);Put函数是一个坑爹的函数!

在读取和写入pix文件是这样处理的:

unsigned short test_value = 1;
// byte_order保存的是图像是按哪种字节序存储
//假如是小端机器,同时又是小端存储,那么就不需要交换高低位的数//据,否则需要交换
if( ((uint8 *) &test_value)[0] == 1 )
needs_swap = (byte_order != 'S');
else //假如是大端机器,办法和小端一样
needs_swap = (byte_order == 'S');

交换的做法很简单,以交换32位浮点数为例,具体如下:

   BYTE  *pbBuffer = NULL;
BYTE *pbtPixel = NULL;
float fValue=(static_cast<float*>(pvBuffer))[i];
pbtPixel=(BYTE*)(&fValue);
*pbBuffer = pbtPixel[3];
pbBuffer++;
*pbBuffer = pbtPixel[2];
pbBuffer++;
*pbBuffer = pbtPixel[1];
pbBuffer++;
*pbBuffer = pbtPixel[0];
pbBuffer++;

pix格式的摸索(二)的更多相关文章

  1. pix格式的一些摸索

    作者:朱金灿 来源:http://blog.csdn.net/clever101 以前因为工作关系研究过PCI的系统格式pix,但是遗留了一些问题,最近又想重新解决这些问题.研究了一天,有些收获,但是 ...

  2. 用 python 来操作 docx, xlsx 格式文件(二)(使用 docx 库操作 docx 格式文件

    docx 库 文章结构: 一.docx 基本用,创建 docx 文件并添加数据 二.深入理解文本格式(format),并设置所格式属性(attribute) 三.深入理解样式(styles),以及如何 ...

  3. CSS概念 - 可视化格式模型(二) 定位概述(普通流、绝对定位)

    2.定位概念 上一节熟悉了盒模型, 现在来看一下可视化格式模型和定位模型. 理解这两个模型的细微差异是非常重要的, 因为它们一起控制着如何在页面上布置每个元素 2.1 可视化格式模型 CSS有三种基本 ...

  4. Android摸索-二、解决Android SDK Manager下载太慢问题

    下载Android SDK Manger 那个速度…………   有了这个再也不用担心了 1.打开android sdk manager 2.打开tool->options 按图片中输入参数:mi ...

  5. C# 生成 DataMatrix 格式的二维码

    该文主要是利用OnBarcode.dll 生成 DataMatrix 格式的二维码的一些简单方法和操作技巧.关于QrBarcode的二维码比较常见和简单,网上有很多资源. 1.附件为dll 2.利用上 ...

  6. 如何将腾讯视频的qlv格式转换为mp4格式

    基本上每个视频app都会有自己固有的视频播放格式,比如优酷的KUX.爱奇艺的QSV和腾讯的QLV等.而今天我们重点介绍腾讯的QLV格式如何转换为MP4格式,小便也是经过多次的摸索多次的软件试用,发现的 ...

  7. SpringMVC初始化参数绑定--日期格式

    一.初始化参数绑定[一种日期格式] 配置步骤: ①:在applicationcontext.xml中只需要配置一个包扫描器即可 <!-- 包扫描器 --> <context:comp ...

  8. 从零开始系列-R语言基础学习笔记之二 数据结构(二)

    在上一篇中我们一起学习了R语言的数据结构第一部分:向量.数组和矩阵,这次我们开始学习R语言的数据结构第二部分:数据框.因子和列表. 一.数据框 类似于二维数组,但不同的列可以有不同的数据类型(每一列内 ...

  9. C#二维数组

    数组格式 一维数组: Console.WriteLine("输入班级人数"); int renshu = int.Parse(Console.ReadLine()); ; i &l ...

随机推荐

  1. AngularJs轻松入门(一)创建第一个应用

    AngularJs是Google工程师研发的一款JS框架,官方文档中对它的描述是,它是完全使用JavaScript编写的客户端技术,同其他历史悠久的Web技术(HTML,CSS等)配合使用,使得Web ...

  2. <Sicily> 生成字符串

    一.题目描述 假设一个字符串只由字符'0','1','?'组成,其中字符'?'表示该字符可由字符'0'或'1'替代. 现有一些字符串,根据这些字符串生成所有可生成的字符串. 如:{10,?1,0? } ...

  3. 织梦CMS调用文章第一张图片(非缩略图)终极方法

    之前,网上流传了很多在织梦CMS中调用第一张图片的方法,但大体都一样.即删除缩略图字符串,并添加后缀.然而这种方法仅限于jpg图片或其他单独图片类的调用.如果一个站有png.JPG.gif等多种格式. ...

  4. sql 除法运算 保留两位小数

    sql 除法运算 保留两位小数 SELECT 1530/60 select cast(1530*1./60 as decimal(18,1))

  5. Linux安装多功能词典GoldenDict

    Linux安装多功能词典GoldenDict 活腿肠 2017.08.01 20:52* 字数 671 阅读 1555评论 0喜欢 2 Goldendict 简介 GoldenDict是一种开源的辞典 ...

  6. 十一 模板匹配match template

    一.介绍 1.模板匹配 通俗讲就是以图找图,通过图中的一部分来找它在图中的位置(模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域). 模板匹配是一种最原始.最基本的模式识别方法,研究某一特定对 ...

  7. [笔记-图论]Dijkstra

    用于求正权有向图 上的 单源最短路 优化后时间复杂度O(mlogn) 模板 // Dijkstra // to get the minumum distance with no negtive way ...

  8. 13-Linux中进程与线程的概念以及区别

    linux进程与线程的区别,早已成为IT界经常讨论但热度不减的话题.无论你是初级程序员,还是资深专家,都应该考虑过这个问题,只是层次角度不同罢了.对于一般的程序员,搞清楚二者的概念并在工作中学会运用是 ...

  9. python学习---【__all__】

    python包中都会有一个__init__.py的模块,这个模块是区分该父文件是一个python包,或是一个文件目录.这个__init__.py可以是空,也可以添加内容,最常见的就是其中的__all_ ...

  10. 安卓自己定义对话框及The specified child already has a child问题

    问题:在android开发过程中,有时会在不同情况下遇到同种问题:The specified child already has a parent.You must call removeView() ...