RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / user-468942

WaitingForTheLP'sComeback's questions

Martin Hope
WaitingForTheLP'sComeback
Asked: 2022-07-27 02:15:53 +0000 UTC

蒙版如何在 BMP 图像中发挥作用?

  • 9

我正在尝试编写用于将各种格式的图像读取到字节数组中的原始算法。在我设法解析 PPM 和 TGA 图纸后,我决定启动 BMP 格式。目前,我已经学习了如何在以下情况下将 BMP 图像转换为 RGB 序列数组:

  • 在图片中,有关特定像素的信息使用四位或八位进行编码,并且文件包含一个颜色表。
  • 在绘图中,有关特定像素的信息使用 24 位进行编码,并且文件不包含颜色表。这是最简单的选择。

32 位 BMP 图像出现问题。我使用 Paint dot NET 图形编辑器生成 BMP 文件。在带有保存选项的窗口中,您可以选择图片的位深度。我的 32 位图像是 2*2 像素,看起来像这样:

在此处输入图像描述

像素 #1 是 RGB(11, 12, 13),像素 #2 是 RGB(51, 52, 53),像素 #3 是 RGB(101, 102, 103),像素 #4 是 RGB(151, 152, 153) )。

使用类std::ifstream及其方法get(),我将文件的内容显示到控制台(首先是字节数,然后是具有该数字的字节的内容):

在此处输入图像描述

相同的输出,但在文本中:

1) 66   2) 77   3) 166   4) 0   5) 0   6) 0   7) 0   8) 0   9) 0   10) 0   11) 150   12) 0   13) 0   14) 0   15) 124   16) 0   17) 0   18) 0   19) 2   20) 0   21) 0   22) 0   23) 2   24) 0   25) 0   26) 0   27) 1   28) 0   29) 32   30) 0   31) 3   32) 0   33) 0   34) 0   35) 0   36) 0   37) 0   38) 0   39) 196   40) 14   41) 0   42) 0   43) 196   44) 14   45) 0   46) 0   47) 0   48) 0   49) 0   50) 0   51) 0   52) 0   53) 0   54) 0   55) 0   56) 0   57) 255   58) 0   59) 0   60) 255
61) 0   62) 0   63) 255   64) 0   65) 0   66) 0   67) 0   68) 0   69) 0   70) 255   71) 32   72) 110   73) 105   74) 87   75) 0   76) 0   77) 0   78) 0   79) 0   80) 0   81) 0   82) 0   83) 0   84) 0   85) 0   86) 0   87) 0   88) 0   89) 0   90) 0   91) 0   92) 0   93) 0   94) 0   95) 0   96) 0   97) 0   98) 0   99) 0   100) 0   101) 0   102) 0   103) 0   104) 0   105) 0   106) 0   107) 0   108) 0   109) 0   110) 0   111) 0   112) 0   113) 0   114) 0   115) 0   116) 0   117) 0   118) 0   119) 0   120) 0   121) 0   122) 0   123) 0   124) 0   125) 0   126) 0   127) 0   128) 0   129) 0   130) 0   131) 0   132) 0   133) 0   134) 0   135) 0   136) 0   137) 0   138) 0   139) 255   140) 0   141) 0   142) 0   143) 0   144) 255   145) 0   146) 0   147) 0   148) 0   149) 255   150) 0   151) 103   152) 102   153) 101   154) 255   155) 153   156) 152   157) 151   158) 255   159) 13   160) 12   161) 11   162) 255   163) 53   164) 52   165) 51   166) 255

从第 15 到第 18 字节占用的字段(取决于 BMP 版本称为 bcSize/biSize/bV4Size/bV5Size)的值为 124,对应于 BMP 版本 5。这表明图片可能包含“bitmasks to提取通道值:红色、绿色、蓝色强度和 alpha 通道值”(来源:https ://ru.wikipedia.org/wiki/BMP#BITMAPINFO )。压缩字段的值(从第 31 到第 34 个字节)也指示掩码的存在,因为它等于数字 3。包含掩码的字段占用 4 个字节,并从第 55 个字节开始相互跟随. 从控制台输出来看,在我的图像中,掩码具有以下值(十进制):

红色掩码:(0 0 255 0第 55 到第 58 个字节)

绿色掩码:(0 255 0 0从第 59 到第 62 字节)

蓝色掩码:(255 0 0 0从第 63 到第 66 字节)

Alpha 通道掩码:(0 0 0 255从第 67 到第 70 个字节)

我不知道如何解释这些值并将它们应用于位于文件末尾的像素颜色。如果我忽略这些值并直接提取颜色(从有时称为图像数据或像素数据的数据块中),我会得到正确的颜色。这一定是因为我没有在图形编辑器中调整蒙版,程序为它们写下了不会扭曲像素颜色的默认值。

如果手动更正蒙版的值并覆盖文件,每个像素的颜色都会发生变化。例如,我将红色蒙版更改为0 0 60 0(十进制),在图形编辑器中打开图像,得到以下结果:

在此处输入图像描述

像素 #1 现在是 RGB(34, 12, 13),像素 #2 是 RGB(204, 52, 53),像素 #3 是 RGB(153, 102, 103),像素 #4 是 RGB(85, 152) , 153)。

确实,每个像素的红色值都发生了变化。可能,编辑器使用数字的二进制表示执行了一些操作,但我不知道哪些操作。在我看过的有关 BMP 的文章中,出于某种原因顺便提到了掩码。位于图像数据之前的数据块也提出了问题。它占据文件的第 139 到第 150 个字节(在我的情况下),根据维基百科,它的名称是 GAP1(https://commons.wikimedia.org/wiki/File:BMPfileFormat.svg?uselang=ru) . 只有在我在保存选项中将位深度设置为 32 后,GAP1 才会出现在我的 BMP 绘图中。这个块的数据和颜色掩码非常相似,但我不确定它是否有任何联系,因为我找不到关于 GAP1 的信息。我可能做错了什么。

请告诉我如何理解蒙版在 BMP 图纸中的工作原理?

#include <iostream>
#include <fstream>
#include <string>

void ReadImage_BMP(const char* file_path_c_str);

int main()
{

    ReadImage_BMP(".../image.bmp");

    return 0;
}

void ReadImage_BMP(const char* file_path_c_str)
{
    std::string file_path = file_path_c_str;

    std::ifstream input_fs;
    input_fs.open(file_path, std::ios_base::binary);

    if (input_fs.is_open() == false)
    {
        perror(("Error while opening file " + file_path).c_str());
        return;
    }

    char current_byte;
    int count = 1;

    while ((bool)input_fs.get(current_byte) == true)
    {
        std::cout << count << ") " << (int)(unsigned char)current_byte << std::endl;
        count++;
    }

    if (input_fs.eof())
    {
        std::cout << "End of file reached." << std::endl;
    }
    else if (input_fs.fail())
    {
        std::cout << "Type error." << std::endl;
    }
    else
    {
        std::cout << "Unknown error" << std::endl;
    }

    input_fs.close();

}
c++ изображения
  • 4 个回答
  • 185 Views
Martin Hope
WaitingForTheLP'sComeback
Asked: 2022-07-23 01:37:18 +0000 UTC

压缩算法如何在 TGA 图像中工作?

  • 2

我想学习如何将各种格式的图像读入字节数组。这对我来说是一项相当艰巨的任务,所以我从最简单的格式开始。PPM P6 没有问题,但是当我决定处理 TGA 图像时,我遇到了一些我无法找到解释的事情。例如,我不明白使用这种格式的压缩算法是如何工作的。

你可以在网上找到一个TGA 2的规范,据我了解,TGA 2格式并没有改变常规TGA的基本原理,只是在文件末尾添加了一些数据,所以压缩算法并且排序图像像素颜色序列不应该改变。可以在此处阅读规范:https ://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf或此处: http://tfc.duke.free.fr/coding/tga_specs。 pdf

该文档指出,如果文件的第三个字节指示该格式可以使用游程编码 (RLE) 算法(假设第三个字节是 TGA 压缩图像中的 9、10 或 11 [第 6 页])。

我对 RLE 在理论上的工作原理知之甚少。例如,字符序列AAABBBBBC压缩后应该变成3A5B1C或A3B5C1。因此,算法必须固定重复字符的数量。我希望在 TGA 文件中看到类似的内容。

为了获取和比较压缩和未压缩的 TGA 图像,我使用了 Paint dot NET 图形编辑器。保存 TGA 文件时,编辑器允许您在特殊窗口中启用或禁用压缩,如下图所示: 在此处输入图像描述

我保存的压缩和未压缩的图像是 50*50px 并且是 RGB(11,12,13)​​ 颜色的实心正方形。图像中的所有像素都必须是这种颜色。

使用 slassstd::ifstream及其方法get(),我能够将图像的 TGA 字符输出到控制台。根据规范,文件的前 18 个字节总是被关于图像的各种信息占用。如果文件不包含颜色图和名为 Image ID 的字段,则图片像素的颜色序列在第 18 个字节之后立即开始。

这是我得到的:

未压缩的TGA 图像:

1) 0
2) 0
3) 2 // <- третий байт не равен 9, 10 или 11, поэтому изображение является несжатым
4) 0
5) 0
6) 0
7) 0
8) 0
9) 0
10) 0
11) 0
12) 0
13) 50
14) 0
15) 50
16) 0
17) 24
18) 0
19) 13 // <- первый символ, описывающий цвет пикселя
20) 12
21) 11
22) 13
23) 12
24) 11
25) 13
26) 12
27) 11
28) 13
29) 12
30) 11
31) 13
32) 12
33) 11
... // и так далее

压缩的 TGA 图像:

1) 0
2) 0
3) 10 // <- третий байт равен 10, поэтому изображение является сжатым
4) 0
5) 0
6) 0
7) 0
8) 0
9) 0
10) 0
11) 0
12) 0
13) 50
14) 0
15) 50
16) 0
17) 24
18) 0
19) 177 // <- первый символ, описывающий цвет пикселя
20) 13
21) 12
22) 11
23) 177
24) 13
25) 12
26) 11
27) 177
28) 13
29) 12
30) 11
31) 177
32) 13
33) 12
34) 11
... // и так далее

在未压缩的图像中,蓝色、绿色和红色 (BGR) 值位于字符 18 之后。由于图片中的所有像素都有这个颜色,所以三个值13 12 11的序列重复了很多次。压缩后的图像多次重复四个值的序列177 13 12 11。我不明白那是什么意思。结果与我之前的预期和描述不同。

我真的很想了解这个压缩算法的逻辑,但目前我找不到这方面的信息。阅读规范和搜索互联网还没有帮助我找到这个问题的答案。请告诉我在哪里可以读到它?也许有一些文章或书籍?

我还没有弄清楚如何附加我的代码在此处处理的 TGA 格式图像,但在我看来这不是必需的。

#include <iostream>
#include <fstream>
#include <string>

void ReadImage_TGA(const char* file_path_c_str);

int main()
{

    ReadImage_TGA(".../image.tga");

    return 0;
}

void ReadImage_TGA(const char* file_path_c_str)
{
    std::string file_path = file_path_c_str;

    std::ifstream file_stream;
    file_stream.open(file_path, std::ios_base::binary);

    if (file_stream.is_open() == false)
    {
        perror(("Error while opening file " + file_path).c_str());
        return;
    }

    char current_char;
    int count = 1;

    while ((bool)file_stream.get(current_char) == true)
    {
        std::cout << count << ") " << (int)current_char << std::endl;
        count++;
    }

    if (file_stream.eof())
    {
        std::cout << "End of file reached." << std::endl;
    }
    else if (file_stream.fail())
    {
        std::cout << "Type error." << std::endl;
    }
    else
    {
        std::cout << "Unknown error" << std::endl;
    }

    file_stream.close();

}
c++ изображения
  • 1 个回答
  • 72 Views

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5