从图像 RGB bmp 纯 C 编写灰度 bmp 的这段代码有什么问题 - Windows 操作系统

2023-12-19

这是我的函数,我根据维基百科 BITMAPINFOHEADER 使用标题 BMP。但是,我得到的文件没有任何图像......当放置填充时,该过程停止。

 // Structures for header info
 #pragma pack(push,1)
 /* Windows 3.x bitmap file header */
 typedef struct {
      char         filetype[2];   /* magic - always 'B' 'M' */
      unsigned int filesize;
      short        reserved1;
      short        reserved2;
      unsigned int dataoffset;    /* offset in bytes to actual bitmap data */
  } file_header;

  /* Windows 3.x bitmap full header, including file header */
 typedef struct {
      file_header  fileheader;
      unsigned int headersize;
      int          width;
      int          height;
      short        planes;
      short        bitsperpixel;  /* we only support the value 24 here */
      unsigned int compression;   /* we do not support compression */
      unsigned int bitmapsize;
      int          horizontalres;
      int          verticalres;
      unsigned int numcolors;
      unsigned int importantcolors;
  } bitmap_header;
  #pragma pack(pop)


int RGB2GREY(char* input, char *greyImage) {

  //variable declaration:
  FILE *fp, *grey;
  bitmap_header* hp;
  int n;
  char *data;
  int oldBitsperpixel;

  //Open input file:
  fp = fopen(input, "rb");
  if(fp==NULL){
     //cleanup
  }

  //Read the input file headers:
  hp=(bitmap_header*)malloc(sizeof(bitmap_header));
  if(hp==NULL)
      return 3;

  n=fread(hp, sizeof(bitmap_header), 1, fp);
  if(n<1){
     //cleanup
  }

  //Read the data of the image:
  data = (char*)malloc(sizeof(char)*hp->bitmapsize);
  if(data==NULL){
      //cleanup
  }
  //Put me in the position after header...
  fseek(fp,sizeof(char)*hp->fileheader.dataoffset,SEEK_SET);
  printf("Width %d and Height %d\n",hp->width,hp->height);

  int i, j;
  unsigned char BGR[3];
  unsigned colorIntensity[3];
  /*unsigned char bmppad[hp->width] = {0};*/

  printf("New bitmapSize %d\n\n",hp->bitsperpixel);

  //Open greayImage file:
  grey = fopen(greyImage, "wb");
  if(grey==NULL){
    //cleanup
  }
  //Writes the header
  n=fwrite(hp,sizeof(char),sizeof(bitmap_header),grey);
  if(n<1){
      //cleanup
  }
  //Again going to position after header
  fseek(out,sizeof(char)*hp->fileheader.dataoffset,SEEK_SET);
  for (i=0; i<hp->height; i++){
    for (j=0; j<hp->width; j++){
        //Reading pixel by pixel  
        fread(BGR, 3, 1, fp); //1 unsigned char of 3 positions
        unsigned char colorGrey;
        colorGrey = (unsigned char) 0.3*BGR[2] + 0.6*BGR[1]  + 0.1*BGR[0];
        colorIntensity[2] = colorGrey;
        colorIntensity[1] = colorGrey;
        colorIntensity[0] = colorGrey;
        /*printf("B %d G %d R %d ",BGR[0],BGR[1],BGR[2]);
        printf("Gray %d ",colorIntensity);*/
        fwrite(colorIntensity, 3, 1, grey);
    }
    /*
    // Adding pad option1 
    //fwrite(bmppad, sizeof(bmppad), 1, grey); 
    //Adding pad option2
    for (j=0; j>hp->width; j++){
        fwrite(0, 1, 1, grey);
    }*/
}
fclose(fp);
fclose(grey);
free(hp);
free(data);
return 0;

}

在灰色的输出文件中,我什么也没得到......而且,我想知道是否有办法从 24 位减少到 8 位。

附:我的代码来自在c中读取/写入bmp文件 https://stackoverflow.com/questions/11129138/reading-writing-bmp-files-in-c

公式来自于从 RGB BMP 创建灰度 BMP https://stackoverflow.com/questions/20480726/create-greyscale-bmp-from-rgb-bmp

Thanks,


您实质上是通过以灰色显示的方式更改颜色值,将 32 位彩色位图转换为 32 位灰色位图(这种方式不会节省任何空间;位图保持原来的大小)。无论如何,它解释了为什么您不需要调整位图标头。

但是,当您每三个字节读取一次并每三个字节更改一次时,您就不会考虑扫描线。

图像由扫描线组成,扫描线由像素组成。扫描线在偶数字边界上对齐,因此扫描线的最后几个字节未使用(因此扫描线比其上的所有像素都长一些)。

要正确处理输入并创建输出,您的循环必须是:

(编辑:更新为每个像素输出使用 1 个字节):

#pragma pack(push,1)
typedef struct {
    unsigned char rgbBlue;
    unsigned char rgbGreen;
    unsigned char rgbRed;
    unsigned char rgbReserved;
} pal_entry;    
#pragma pack(pop)

int ToGreyScale(FILE *fp, FILE *grey, bitmap_header *hp)
{
    int i, j;
    int iScanlineSizeIn = ((hp->width * hp->bitsperpixel) + 31) / 32 * 4;
    int iScanlineSizeOut= ((hp->width *        8        ) + 31) / 32 * 4;
    unsigned char *scanlineIn = malloc(iScanlineSizeIn), *pIn;
    unsigned char *scanlineOut= malloc(iScanlineSizeOut), *pOut;
    pal_entry pal[256];

    for (i=0; i<256; i++)   // create a gray scale palette
        {pal[i].rgbBlue= i; pal[i].rgbGreen= i; pal[i].rgbRed= i;}

    hp->bitsperpixel= 8;    // set output bits-per-pixel
    hp->fileheader.filesize= sizeof(bitmap_header) + sizeof(pal) + hp->width*iScanlineSizeOut;

    fwrite(hp, sizeof(bitmap_header), 1, grey);     // write the header...
    fwrite(pal, 256*sizeof(pal_entry), 1, grey);    //..followed by palette

    for (i=0; i<hp->height; i++)
    {
        if (fread(scanlineIn, iScanlineSizeIn, 1, fp) != 1) return(0);
        pIn = scanlineIn;
        pOut= scanlineOut;
        for (j=0; j<hp->width; j++)
        {
            *pOut++ = (unsigned char) ((0.1 * *pIn++) + (0.6 * *pIn++) + (0.3 * *pIn++));
        }
        fwrite(scanlineOut, iScanlineSizeOut, 1, grey);
    }
    free(scanlineIn);
    free(scanlineOut);
    return(1);
}   
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从图像 RGB bmp 纯 C 编写灰度 bmp 的这段代码有什么问题 - Windows 操作系统 的相关文章

  • 如何调试Roslyn编译生成的dll?

    我正在使用 Roslyn CSharpCompilation 为我的插件生成 dll 文件 文件具有 OptimizationLevel Debug 并生成 pdb 文件 接下来 我使用 Assembly Load 将这些文件加载 到我的程
  • 是否可以使静态控件透明?

    我正在尝试实现一个静态控件 该控件刷新 更改文本 以响应每秒发生一次的某个事件 由于我不想每秒绘制整个客户区域 所以我决定使用静态控件 现在的问题是父窗口被蒙皮 这意味着它有自定义位图作为背景 而静态控件没有适应 所以我正在寻找使静态控件的
  • 根据当前文化调用不同(本地化)视图

    我在用着LocalizationAttribute它实现了ActionFilterAttribute本地化视图 我简单地说 Localize 在控制器上 我使用 LocalizeStrings resx 文件根据当前线程上的语言进行应用 一
  • 我们可以在 C# 中定义枚举的隐式转换吗?

    是否可以在 C 中定义枚举的隐式转换 可以实现这一目标的东西吗 public enum MyEnum one 1 two 2 MyEnum number MyEnum one long i number 如果没有 为什么不呢 有一个解决方案
  • HTML 文档

    有没有一个工具可以从 VS2010 生成的 XML 文档文件生成 HTML 页面 我在谷歌上搜索了这样的工具 但没有找到 我下载并安装了SandCastle 但我不明白如何使用它 尝试使用Sandcastle 帮助文件生成器 http sh
  • 错误 C2065:'cout':未声明的标识符

    我正在处理我的编程作业的 驱动程序 部分 但我不断收到这个荒谬的错误 错误 C2065 cout 未声明的标识符 我什至尝试过使用std cout但我收到另一个错误 IntelliSense 命名空间 std 没有成员 cout 当我宣布u
  • 在 C/C++ 中绘制填充椭圆的简单算法

    在SO上 找到了以下绘制实心圆的简单算法 for int y radius y lt radius y for int x radius x lt radius x if x x y y lt radius radius setpixel
  • 如何将 QSerialPort 模块添加到 CMake 中?

    我想将 QSerialPort 模块添加到 CMake 中 根据我的理解 我需要将QT 串口添加到 pro中 我只想使用 CMake 所以我尝试编译简单的 CMake 文件 但有错误 QtCore 正在工作 qDebug 可以毫无问题地显示
  • Linux C++ 调试器

    我正在寻找完美的 Linux C 调试器 我不期望成功 但搜索应该提供丰富的信息 我是一个非常有能力的 gdb 用户 但 STL 和 Boost 很容易压垮我的调试技能 并不是说我无法深入了解数据结构的内部结构 而是它需要很长时间 我通常会
  • 如何在 WCF 中反序列化自定义 SOAP 标头?

    我正在尝试向通过 WCF 的所有 SOAP 请求添加自定义标头 我发现这篇精彩的文章 http blogs msdn com b mohamedg archive 2012 10 21 adding custom soap headers
  • 如何“全局”捕获对象实例中引发的异常

    我目前正在编写一个 winforms 应用程序 C 我正在使用企业库异常处理块 遵循我所看到的相当标准的方法 IE 在 Program cs 的 Main 方法中 我已将事件处理程序连接到 Application ThreadExcepti
  • 内存不足异常

    我正在使用 C 和 asp net 开发一个网络应用程序 我一直收到内存不足的异常 该应用程序的作用是从数据源读取一堆记录 产品 可能是数百 数千 通过向导中的设置处理这些记录 然后使用处理的产品信息更新不同的数据源 虽然有多个 DB 类
  • WPF MVVM后台打印数据绑定问题

    我正在使用 wpf mvvm 开发一个销售点应用程序 在交易生命周期的许多阶段 都会在后台打印收据 我已经使用其他示例在后台生成和打印收据 我正在后台打印一个 UserControl 一切看起来都很棒 然后 我为该控件创建了 ViewMod
  • 剥离 OLE 标头信息 (MS Access / SQL Server)

    我有一个 C 应用程序需要支持二进制数据库内容 图像等 当使用 MS Access 或 MS SQL Server 时 此数据被包装在 OLE 对象内 如何去除此 OLE 标头信息 请注意 我不能只查找特定标签的开头 因为内容可以是 png
  • 如何通过 Excel 互操作对象自动调整列大小?

    下面是我用来将数据加载到 Excel 工作表中的代码 但我希望在加载数据后自动调整列的大小 有谁知道自动调整列大小的最佳方法 using Microsoft Office Interop public class ExportReport
  • 64 位随机生成器种子

    我目前正在运行一个具有 8 个以上管道 线程 的多线程模拟应用程序 这些管道运行非常复杂的代码 该代码取决于种子生成的随机序列 然后该序列被归结为单个 0 1 我希望在将种子从主线程传递到处理管道后 这种 随机处理 具有 100 的确定性
  • 使用反射检测属性的访问修饰符类型

    我编写了一些代码来使用反射查看属性 我已经使用反射从类中检索了属性列表 但是我需要查明该财产是公共的还是受保护的 例如 public string Name get set protected int Age get set Propert
  • 从不同的线程访问对象

    我有一个服务器类 它基本上等待来自客户端的连接 在该类中 我创建了一个 NetworkStream 对象 以便能够从客户端接收字节 由于 NetworkStream Read 方法不是异步的 这意味着它将等到从客户端读取字节才能继续执行类似
  • 如何从与 C# lambda 集成(而非代理集成)的 Amazon API 网关获取正确的 http 状态代码?

    我正在使用 C lambda 与 API 网关集成 我希望 API 网关返回正确的错误代码 例如 400 404 500 等 API网关模块tf文件 provider aws version lt 2 70 0 region var aws
  • RC4 实现与 openssl 输出不匹配

    我的目标是在 C C 中实现 RC4 流密码 并确保它产生与使用时相同的输出openssl命令 按照伪代码维基百科 https en wikipedia org wiki RC4 该实现似乎有效 因为它可以加密和解密内容 但是 加密的输出与

随机推荐

  • 如何在反应日期中添加一年的选择?

    向右滑动几个月直到我到达正确的年份是很痛苦的react dates 是否有可能添加一些年份 月份的选择 是的 从版本开始是可能的 电子邮件受保护 cdn cgi l email protection 相关拉取请求 https github
  • gcc include 顺序损坏?

    我遇到了一个奇怪的问题 linux c 编译器包含本地目录而不是系统目录中的文件 使用 H 选项查看预编译器输出 可以看到系统文件 usr include sched h突然包括time h来自本地目录而不是系统一的标头 我假设如果包含文件
  • powershell 无法向 Excel 图表添加多个图例条目(系列)

    我在通过 powershell 将多个系列添加到 Excel 图表对象中的系列集合时遇到问题 这是我的代码 threading thread CurrentThread CurrentCulture en US excel New Obje
  • 带有 BroadcastReceiver 的清单中的 ACTION_USER_PRESENT

    对于是否可以通过清单捕获 ACTION USER PRESENT 屏幕解锁似乎存在不同意见 该线程暗示不 它不能完成 Android 广播接收器不工作 https stackoverflow com questions 6698716 an
  • 使用 Scala 中的原始类型实现 Java 接口

    我正在尝试使用 Scala 构建 Sonar 的扩展 我需要扩展以下 Java 接口 public interface Decorator extends BatchExtension CheckProject void decorate
  • 使用 NSKeyedUnarchiver 解码时出现问题

    我正在 XCode 3 2 3 上编写一个针对 iOS 4 0 的应用程序 当应用程序关闭时 我使用 NSCoder 协议存储一些数据 保存似乎工作正常 问题是从保存的文件中检索数据 我的保存方法如下所示 void saveMusicalW
  • 如何将 TrueType 字体转换为 PCL5 Soft 字体?

    如何将 TrueType 字体转换为 PCL5 softfont spf 主要思想是将软字体嵌入到 PCL5 打印文件中 然后选择它供打印机使用 因为它是通过 PCL5 命令指定的字体 ID 另外 如果您知道在创建 PCL5 文件时使用 T
  • 在 C++11 中使用没有托管共享指针的shared_from_this()

    假设我有一个类 它是enable shared from this 的子类 这个基类的文档说在调用shared from this之前应该有一个拥有这个类的共享指针 用new分配类并调用shared from this来管理对象是否安全 正
  • 解析不同架构维度输入的所有可能类型

    我正在为我们公司的产品编写一个库 它将采用我们的用户已经熟悉的任何类型的架构维度作为从字符串转换为双精度的函数的输入 这是我们希望有效的输入类型列表 Input 意义 Output 英寸以双精度表示 12 5 12 英尺 6 英寸 150
  • C# WPF - 窗口中的黑线

    我的窗户上有一条小黑线 为什么
  • 为什么单态和多态在 JavaScript 中很重要?

    我一直在阅读一些有关更改检测的文章 它们都说单态函数比多态函数快得多 例如 这里有一个引用 这样做的原因是 它必须以动态方式编写 所以 它可以检查每个组件 无论其模型结构如何 喜欢 虚拟机不喜欢这种动态代码 因为它们不能 优化它 它被认为是
  • 从内存映射文件读取时出现问题

    我试图在我的应用程序 特别是 Windows 服务 中实现内存映射文件 然后使用 C 形式从服务写入的 MMF 中读取 不幸的是 我似乎无法获得从 MMF 读取任何内容的表单 更重要的是 该表单似乎从未找到该服务创建的 MMF 下面是概述我
  • 如何在不安装 Visual Studio 2012 的情况下使用 MsBuild 在生成服务器上生成 Visual Studio 2012 发布配置文件

    我阅读了这里的许多帖子 但从未找到有效的明确答案 因此 在花了时间让它发挥作用后 我认为我应该发布它 问题 发布配置文件将在服务器上构建 但不会发布 解决方案 确保您已安装Microsoft Windows SDK 和 Net Framew
  • Django 强制密码过期

    是否有任何 django 应用程序可以在一定的时间间隔 例如 30 天 后强制使用户的密码过期 我正在使用 djangp 的身份验证 并希望扩展它或使用社区应用程序 到目前为止我已经尝试过 在用户配置文件中添加了一个字段 用于存储上次更新密
  • 如何强制oracle使用索引范围扫描?

    我对包含 14 亿条记录 带索引 的表运行了一系列极其相似的查询 唯一的问题是这些查询中至少有 10 的执行时间比其他查询多 100 倍以上 我运行了一个解释计划 并注意到对于快速查询 大约 90 Oracle 使用索引范围扫描 对于慢速的
  • 是否有任何简单的自动化方法可以找出与 Delphi 项目关联的所有源文件?

    我喜欢在发布版本时备份项目的源代码集 我使用 GExperts 项目备份 它似乎将项目管理器中的所有文件收集到 ZIP 文件中 您还可以将任意文件添加到此文件集中 但我始终意识到我不一定获得所有文件 除非我专门仔细检查使用条款并将我拥有的所
  • ValueError:endog必须在单位间隔内

    在使用 statsmodels 时 我收到这个奇怪的错误 ValueError endog must be in the unit interval 有人可以给我有关此错误的更多信息吗 谷歌没有提供帮助 产生错误的代码 Multiple r
  • 如何为 Kubernetes 中的 Flink 应用程序自定义资源提供 Vault 密钥

    我想为 Kubernetes 集群中运行的 Apache Flink 作业提供来自 Hashicorp Vault 的机密 这些积分将用于访问状态后端以进行检查点和保存点 例如 状态后端可以是 Minio S3 存储 有人可以提供一个工作示
  • 如何将位图附加到电子邮件 android

    我有一个保存在外部存储器中的位图 我已经有一个加载和返回位图的方法 我的问题是 如何将此图像附加到电子邮件意图中 注意 我知道如何启动电子邮件意图 我只需要知道如何附加位图 谢谢 这就是我保存图片的方式 private void saveP
  • 从图像 RGB bmp 纯 C 编写灰度 bmp 的这段代码有什么问题 - Windows 操作系统

    这是我的函数 我根据维基百科 BITMAPINFOHEADER 使用标题 BMP 但是 我得到的文件没有任何图像 当放置填充时 该过程停止 Structures for header info pragma pack push 1 Wind