DCMTK学习之RGB颜色的存储以及转换

前言

现在去医院进行身体检测,一般都会有几种选择,例如我们可以选择进行B超,拍出黑白的“胶片”(不是专业人员,不知道怎么称呼这玩意);我们也可以选择彩超,拍出彩色的“胶片”,但是在程序中我们如何生成这样的图片?这就需要我们了解ARGB的存储。

说明–大端模式以及小端模式

在进行正式的说明之前,先来了解下《操作系统》里面关于“大数据”的存储,对于char类型来说,它只占用一个字节,不存在数据存储的问题,但是对于int(4个字节),long(8个字节)等的数据来说,就存在数据存储的问题。

在操作系统里面,有这么两种存储的方式:大端模式以及小端模式。
大端模式:在这种格式中,字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
例如:0x ae345c,这是一个占3个字节的数据,在大端模式下,内存中的第一个字节(这里是针对这个数据来进行说明的)存放的是ae,第二个字节存放的是34,而第三个字节存放的是5c,如图:
这里写图片描述

小端模式:在小端存储格式中,低地址中存放的是字数据的低字节,高地址存放的是字数据的高字节
还是例如:0x ae345c,在小端模式下,第一个字节存放的是5c,第二个字节存放的是34,第三个字节存放的是ae,如图:
这里写图片描述

至于如何判断大端模式以及小端模式,我这里提供一个思路:
建立这样的一个联合体:

union
{
    int i;
    char ch;
}

接下来让i的值为1(小于255均可),然后读取ch的值,如果ch的值为1(转成int型),那就是小端模式;若为0,那么就是大端模式。(这里主要是利用第一个字节进行判断,字符只有一个字节,不存在什么大端小端,但是对于大于一个字节的数来说就存在这样的问题)

注意:这里说的问题只是针对于数据的储存,对于程序来说还是按照顺序进行存储的,不存在什么大端以及小端模式。例如我定义了两个变量:int a;int b;在进行存储时,a还是存放在b的前面,无论你是什么存储模式。

说明–DCMTK中ARGB的存储

注意:在彩色图片中这四个值是按照A,R,G,B进行拼接形成的。也就是说在程序中,A的值是最高位的,B的值是最低位的。但是写入到内存以后,那就不一样了。

如果你正在处理的是灰度图,也就是整张图没有其他的颜色,只有灰色,那么就无需关注这个问题,因为灰色的RGB值是一样的,只需要存储一个和识别一个就行。如图:

这里写图片描述
另外,不要尝试去下载这个软件,有毒,不好用。

当然,当DCM文件被医疗设备生成时,对于灰度图本身就只存储了一个值,目的就是为了节省内存空间,同时也加快了处理速度,所以当转换成JPG或者其他的图片时,只需要将RGB三个值都设置成这个值就可以了。例如如下代码:

//这里的nBandCount就是像素的个数,这个函数的作用就是反向输出这张图。
if(nBandCount == 1)
        {
            //灰度图像只需要取原值就可以完成,
            for(int y = 0, y1 = nBmpHeight - 1; y < nBmpHeight; y++, y1--)
            {
                for(int x = 0; x < nBmpWidth; x++)
                {
                    //因为灰度图像只需要设定灰度值(0-255),所以这里只需要一个参数即可,
                    //灰色的图像 RGB的三个值是一样的。所以只需要记录一个值就可以了

                    //这里是反向输出这张图片
                    int i = y * nBmpWidth + x;
                    int j = y1 * nBmpWidth + x;
                    pTemp[j * 4]     = pCatheData[i];   //B
                    pTemp[j * 4 + 1] = pCatheData[i];   //G
                    pTemp[j * 4 + 2] = pCatheData[i];   //R
                    pTemp[j * 4 + 3] = 255;             //A
                }
            }
        }

如果你是在处理一张彩色的图片,那么就得注意RGB的存储:
在DCM文件里面,RGB的数据是按照大端模式进行存储的,也就是先存放的是R值,接下来存放的是G值,最后存放的是B值;但是对于操作系统来说,数据要按照小端模式进行存储以及读取,所以这里要完整的读取到RGB值,就必须转换。代码如下:

//这里也是反向输出这张图
if(nBandCount == 3)
        {
            for(int y = 0, y1 = nBmpHeight - 1; y < nBmpHeight; y++, y1--)
            {
                for(int x = 0; x < nBmpWidth; x++)
                {
                    //这里也是反相输出这张图
                    int i = y * nBmpWidth * 3 + x * 3;   //因为DCM文件要记录彩色的RGB值,就需要三个字节进行存储,这里不包含不透明度A值
                    int j = y1 * nBmpWidth * 4 + x * 4;   //但是再实际的形成图像的文件中,就需要A值来指示不透明度,默认的透明的。
                    //这里说明在DCM中,数据是以大端模式进行存储的
                    //在计算机里面,数据是以小端模式进行存储的
                    pTemp[j]     = pCatheData[i + 2];  //B
                    pTemp[j + 1] = pCatheData[i + 1];  //G
                    pTemp[j + 2] = pCatheData[i];      //R
                    pTemp[j + 3] = 255;                //A
                }
            }
        }

明白了RGB值得存储以及转换,就可以进行图像的翻转了。

新手学习建议先查看DCMTK官方的几个示例程序并手动编写一遍,对自己理解DCMTK有很大的用处:http://support.dcmtk.org/docs/index.html

posted @ 2017-06-26 17:56  $逝水无痕$  阅读(1035)  评论(0编辑  收藏  举报