Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/111.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
D 我可以从FreeImage导出的最高位深度灰度图像是什么?_D_Tiff_Grayscale_Freeimage_Bpp - Fatal编程技术网

D 我可以从FreeImage导出的最高位深度灰度图像是什么?

D 我可以从FreeImage导出的最高位深度灰度图像是什么?,d,tiff,grayscale,freeimage,bpp,D,Tiff,Grayscale,Freeimage,Bpp,作为背景,我正在建立一个地形规划,需要相对极端的细节。我不希望这些文件很小,也不需要在监视器上正式查看,它们只需要具有非常高的分辨率 我知道大多数图像格式都被限制在8 bpp以内,这是因为在合理的价格下,两种显示器都有标准的限制,而且还取决于人类的感知。然而,2⁸ 只有256个可能的值,这会在重建的位移中产生平稳的伪影。2¹⁶ 可能接近65536个可能的值,我已经达到了 我正在使用FreeImage和DLang构建数据,目前在Linux Mint机器上 然而,当我继续使用2²时,软件支持对我来说

作为背景,我正在建立一个地形规划,需要相对极端的细节。我不希望这些文件很小,也不需要在监视器上正式查看,它们只需要具有非常高的分辨率

我知道大多数图像格式都被限制在8 bpp以内,这是因为在合理的价格下,两种显示器都有标准的限制,而且还取决于人类的感知。然而,2⁸ 只有256个可能的值,这会在重建的位移中产生平稳的伪影。2¹⁶ 可能接近65536个可能的值,我已经达到了

我正在使用FreeImage和DLang构建数据,目前在Linux Mint机器上

然而,当我继续使用2²时,软件支持对我来说似乎逐渐消失了。我尝试了这种形式的TIFF,但似乎没有任何东西能够解释它,要么显示一个完全或大部分透明的图像,记住我不希望任何显示器能够真正支持两种颜色的通道,要么抱怨无法解码RGB数据。我想这是因为它被假定为RGB或RGBA图像

FreeImage在大多数情况下都有很好的文档记录,但我现在想知道,我可以导出的最高精度单通道格式是什么,我将如何做到?有人能举个例子吗?我真的被限制在16位吗?在任何典型的非自滚图像格式中?我知道这对医学成像来说已经足够高了,但我肯定我不是第一个尝试更高目标的人,我们这些科学工作者可能对我们的精度水平非常雄心勃勃

我在代码中犯了一个明显的错误吗?为了达到这种精度,我还应该尝试其他方法吗

这是我的密码

有效的16位TIFF

32位TIFF没有真正起作用


感谢您的指点。

对于单个通道,FreeImage提供的最高值为32位,如FIT_UINT32所示。然而,文件格式必须能够做到这一点,目前为止,只有TIFF似乎能够完成任务,请参见第104页。此外,大多数监视器无法表示超过8位/样本,在极端情况下为12位,因此很难读取数据并正确渲染

单元测试涉及在封送到位图之前比较字节,然后从同一位图中采样,显示数据实际上正在编码

要将数据压印到J2K、JP2、PGM、PGMRAW、PNG和TIF当前支持的16位灰度,请执行以下操作:

void toFreeImageUINT16PNG(string fileName, const double width, const double height, double[] data) {
    FIBITMAP *bitmap = FreeImage_AllocateT(FIT_UINT16, cast(int)width, cast(int)height);
    for(int y = 0; y < height; y++) {
            ubyte *scanline = FreeImage_GetScanLine(bitmap, y);
            for(int x = 0; x < width; x++) {
                    //This magic has to happen with the y-coordinate in order to keep FreeImage from following its default behavior, and generating
                    //the image upside down.
                    ushort v = cast(ushort)(data[cast(ulong)(((height - 1) - y) * width + x)] * 0xFFFF); //((x * 0xFFFF)/width);
                    ubyte[2] bytes = nativeToLittleEndian(v);
                    scanline[x * ushort.sizeof + 0] = bytes[0];
                    scanline[x * ushort.sizeof + 1] = bytes[1];
            }
    }
    FreeImage_Save(FIF_PNG, bitmap, fileName.toStringz);
    FreeImage_Unload(bitmap);
}
当然,您会希望针对目标文件类型进行调整。要导出为48位RGB16,您可以这样做

void toFreeImageColorPNG(string fileName, const double width, const double height, double[] data) {
    FIBITMAP *bitmap = FreeImage_AllocateT(FIT_RGB16, cast(int)width, cast(int)height);
    uint pitch = FreeImage_GetPitch(bitmap);
    uint bpp = FreeImage_GetBPP(bitmap);
    for(int y = 0; y < height; y++) {
            ubyte *scanline = FreeImage_GetScanLine(bitmap, y);
            for(int x = 0; x < width; x++) {
                    ulong offset = cast(ulong)((((height - 1) - y) * width + x) * 3);
                    ushort r = cast(ushort)(data[(offset + 0)] * 0xFFFF);
                    ushort g = cast(ushort)(data[(offset + 1)] * 0xFFFF);
                    ushort b = cast(ushort)(data[(offset + 2)] * 0xFFFF);
                    ubyte[6] bytes = nativeToLittleEndian(r) ~ nativeToLittleEndian(g) ~ nativeToLittleEndian(b);
                    scanline[(x * 3 * ushort.sizeof) + 0] = bytes[0];
                    scanline[(x * 3 * ushort.sizeof) + 1] = bytes[1];
                    scanline[(x * 3 * ushort.sizeof) + 2] = bytes[2];
                    scanline[(x * 3 * ushort.sizeof) + 3] = bytes[3];
                    scanline[(x * 3 * ushort.sizeof) + 4] = bytes[4];
                    scanline[(x * 3 * ushort.sizeof) + 5] = bytes[5];
            }
    }
    FreeImage_Save(FIF_PNG, bitmap, fileName.toStringz);
    FreeImage_Unload(bitmap);
}
void toFreeImageTIF32(string fileName, const double width, const double height, double[] data) {
    FIBITMAP *bitmap = FreeImage_AllocateT(FIT_UINT32, cast(int)width, cast(int)height);

    //DEBUG
    int xtest = cast(int)(width/2);
    int ytest = cast(int)(height/2);
    uint comp1a = cast(uint)(data[cast(ulong)(((height - 1) - ytest) * width + xtest)] * 0xFFFFFFFF);
    writeln("initial: ", nativeToLittleEndian(comp1a));

    for(int y = 0; y < height; y++) {
            ubyte *scanline = FreeImage_GetScanLine(bitmap, y);
            for(int x = 0; x < width; x++) {
                    //This magic has to happen with the y-coordinate in order to keep FreeImage from following its default behavior, and generating
                    //the image upside down.
                    ulong i = cast(ulong)(((height - 1) - y) * width + x);
                    uint v = cast(uint)(data[i] * 0xFFFFFFFF);
                    ubyte[4] bytes = nativeToLittleEndian(v);
                    scanline[x * uint.sizeof + 0] = bytes[0];
                    scanline[x * uint.sizeof + 1] = bytes[1];
                    scanline[x * uint.sizeof + 2] = bytes[2];
                    scanline[x * uint.sizeof + 3] = bytes[3];
            }
    }

    //DEBUG
    ulong index = cast(ulong)(xtest * uint.sizeof);
    writeln("Final: ", FreeImage_GetScanLine(bitmap, ytest)
            [index .. index + uint.sizeof]);

    FreeImage_Save(FIF_TIFF, bitmap, fileName.toStringz);
    FreeImage_Unload(bitmap);
}
最后,要对目前仅限于TIFF的UINT32灰度图像进行编码,您可以这样做

void toFreeImageColorPNG(string fileName, const double width, const double height, double[] data) {
    FIBITMAP *bitmap = FreeImage_AllocateT(FIT_RGB16, cast(int)width, cast(int)height);
    uint pitch = FreeImage_GetPitch(bitmap);
    uint bpp = FreeImage_GetBPP(bitmap);
    for(int y = 0; y < height; y++) {
            ubyte *scanline = FreeImage_GetScanLine(bitmap, y);
            for(int x = 0; x < width; x++) {
                    ulong offset = cast(ulong)((((height - 1) - y) * width + x) * 3);
                    ushort r = cast(ushort)(data[(offset + 0)] * 0xFFFF);
                    ushort g = cast(ushort)(data[(offset + 1)] * 0xFFFF);
                    ushort b = cast(ushort)(data[(offset + 2)] * 0xFFFF);
                    ubyte[6] bytes = nativeToLittleEndian(r) ~ nativeToLittleEndian(g) ~ nativeToLittleEndian(b);
                    scanline[(x * 3 * ushort.sizeof) + 0] = bytes[0];
                    scanline[(x * 3 * ushort.sizeof) + 1] = bytes[1];
                    scanline[(x * 3 * ushort.sizeof) + 2] = bytes[2];
                    scanline[(x * 3 * ushort.sizeof) + 3] = bytes[3];
                    scanline[(x * 3 * ushort.sizeof) + 4] = bytes[4];
                    scanline[(x * 3 * ushort.sizeof) + 5] = bytes[5];
            }
    }
    FreeImage_Save(FIF_PNG, bitmap, fileName.toStringz);
    FreeImage_Unload(bitmap);
}
void toFreeImageTIF32(string fileName, const double width, const double height, double[] data) {
    FIBITMAP *bitmap = FreeImage_AllocateT(FIT_UINT32, cast(int)width, cast(int)height);

    //DEBUG
    int xtest = cast(int)(width/2);
    int ytest = cast(int)(height/2);
    uint comp1a = cast(uint)(data[cast(ulong)(((height - 1) - ytest) * width + xtest)] * 0xFFFFFFFF);
    writeln("initial: ", nativeToLittleEndian(comp1a));

    for(int y = 0; y < height; y++) {
            ubyte *scanline = FreeImage_GetScanLine(bitmap, y);
            for(int x = 0; x < width; x++) {
                    //This magic has to happen with the y-coordinate in order to keep FreeImage from following its default behavior, and generating
                    //the image upside down.
                    ulong i = cast(ulong)(((height - 1) - y) * width + x);
                    uint v = cast(uint)(data[i] * 0xFFFFFFFF);
                    ubyte[4] bytes = nativeToLittleEndian(v);
                    scanline[x * uint.sizeof + 0] = bytes[0];
                    scanline[x * uint.sizeof + 1] = bytes[1];
                    scanline[x * uint.sizeof + 2] = bytes[2];
                    scanline[x * uint.sizeof + 3] = bytes[3];
            }
    }

    //DEBUG
    ulong index = cast(ulong)(xtest * uint.sizeof);
    writeln("Final: ", FreeImage_GetScanLine(bitmap, ytest)
            [index .. index + uint.sizeof]);

    FreeImage_Save(FIF_TIFF, bitmap, fileName.toStringz);
    FreeImage_Unload(bitmap);
}
我还没有找到一个由其他人构建的程序,它可以在显示器的可用调色板上轻易地呈现32位灰度图像。然而,我留下了我的检查代码,它将在顶部调试和底部调试时一致地写出相同的数组,这对我来说已经足够一致了


希望这将在将来帮助其他人。

它是否必须是灰度的?您可以使用24或32位数字作为颜色三元组。。严格来说,它不是一个大的单通道,但你可以这样处理它,可能有一个供用户翻译的颜色表。例如,更多的红色意味着大的变化,更多的蓝色意味着小的变化。用uint.sizeof替换ushort.sizeof。@beerboy哦,我的天哪。我怎么会错过呢!?好的,我修复了代码中的明显错误;不幸的是,行为没有改变。谢谢你指出这一点,比尔比。一切都无法读取RGB数据。至于只使用颜色,@adamdruppe,为了效率起见,我想避免不必要的指针数学。顺便说一下,我已经看过你的书了;非常好。如果有可能将其可靠地编码为灰度,那么这就是我的目标;因为32位/4十亿分的分数可能并不总是足够的;我刚刚读到TIFF被限制为16位。我还不确定这是否是一个错误;要么是,要么是我以前的数据。文件成功地将tiff报告为32位,这似乎很奇怪。在任何情况下,我都在深入挖掘深度极高的图像,当我找到它时,我可能会发布我的解决方案。