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