通过操作bmBits

时间:2020-11-12 08:33:43

标签: c casting char autohotkey grayscale

我仅在Windows(AutoHotkey)上编程,并且主要使用其win32 API。 我想将GDI位图(32位DIB)转换为灰度。 我使用GetObject()获得一个BITMAP结构,并将bmBITS及其大小传递给以下函数

int ToGrayscale(unsigned char * s, int n)
{
  float b, g, r, y;
  for (int i=0; i<n; i+=4)
  {
       b = (float) s[i+0];
       g = (float) s[i+1];
       r = (float) s[i+2];
     y = (0.299 * r) + (0.587 * g) + (0.114 * b);
     s[i+0] = s[i+1] = s[i+2] = (unsigned char)y;
  }
return 1;
}

上面是完整的代码。我用Pelles C将其编译为.obj,然后从.obj中提取机器代码 并从AutoHotkey语言调用/使用该机器代码。

机器代码在调用时给我访问冲突错误。

s[i+0] = s[i+1] = s[i+2] = 0;

工作正常,并将图像填充为黑色,但是我想用y(灰度值)转换像素。 正确的方法是什么?

我不确定是否提供了足够的信息。请询问/建议,我会进行更新。

编辑1: 我在c文件中添加了另一个工作函数ToBlack()。

int ToBlack(unsigned char * s, int n)
{
  for (int i=0; i<n; i+=4)
  {
     s[i+0] = s[i+1] = s[i+2] = 0;
  }
return 1;
}

int ToGrayscale(unsigned char * s, int n)
{
  float b, g, r, y;
  for (int i=0; i<n; i+=4)
  {
       b = (float) s[i+0];
       g = (float) s[i+1];
       r = (float) s[i+2];
     y = (0.299 * r) + (0.587 * g) + (0.114 * b);
     s[i+0] = s[i+1] = s[i+2] = (unsigned char)y;
  }
return 1;
}

源位图是具有单个ARGB颜色FFAABBCC的2x2 32位不透明位图 bmBITS大小为16个字节,数据的十六进制表示为 CCBBAAFFCCBBAAFFCCBBAAFFCCBBAAFF

ToBlack()工作正常,当我在运行机器代码后检查bmBITS时, 我得到以下结果-正确。

ToBlack(bmBITS,16)结果: 000000FF000000FF000000FF000000FF

ToBlack(bmBITS,12)结果: 000000FF000000FF000000FFCCBBAAFF

ToBlack(bmBITS,8)结果: 000000FF000000FFCCBBAAFFCCBBAAFF

ToBlack(bmBITS,4)结果: 000000FFCCBBAAFFCCBBAAFFCCBBAAFF

使用ToGrayscale(bmBITS,16)时,数据保持不变。 我猜测当分配y时会发生崩溃。

1 个答案:

答案 0 :(得分:0)

我找到了访问冲突错误的来源。 机器代码不可移植。 对于以下C代码

int ToGrayscale(unsigned char * s, int n)
{
  float b, g, r, y;
  for (int i=0; i<n; i+=4)
  {
       b = (float) s[i+0];
       g = (float) s[i+1];
       r = (float) s[i+2];
     y = (0.299 * r) + (0.587 * g) + (0.114 * b);
     s[i+0] = s[i+1] = s[i+2] = (unsigned char)y;
  }
return 1;
}

.obj转储如下:

Dump of D:\AhkScripts\AHK-003\ToGrayscale.obj

File type: OBJ


_ToGrayscale:
  [00000000] 55                     push              ebp
  [00000001] 89E5                   mov               ebp,esp
  [00000003] 83EC10                 sub               esp,10
  [00000006] 56                     push              esi
  [00000007] 8B5508                 mov               edx,dword ptr [ebp+8]
  [0000000A] 8B4D0C                 mov               ecx,dword ptr [ebp+C]
  [0000000D] 85C9                   test              ecx,ecx
  [0000000F] 7E6C                   jle               0000007D
  [00000011] 31F6                   xor               esi,esi
  [00000013] 0FB60432               movzx             eax,byte ptr [edx+esi]
  [00000017] 50                     push              eax
  [00000018] DB0424                 fild              dword ptr [esp]
  [0000001B] 58                     pop               eax
  [0000001C] D95DFC                 fstp              dword ptr [ebp-4]
  [0000001F] 0FB6443201             movzx             eax,byte ptr [edx+esi+1]
  [00000024] 50                     push              eax
  [00000025] DB0424                 fild              dword ptr [esp]
  [00000028] 58                     pop               eax
  [00000029] D95DF8                 fstp              dword ptr [ebp-8]
  [0000002C] 0FB6443202             movzx             eax,byte ptr [edx+esi+2]
  [00000031] 50                     push              eax
  [00000032] DB0424                 fild              dword ptr [esp]
  [00000035] 58                     pop               eax
  [00000036] D95DF4                 fstp              dword ptr [ebp-C]
  [00000039] D945F4                 fld               dword ptr [ebp-C]
  [0000003C] DC0D00000000           fmul              qword ptr [@37]
  [00000042] D945F8                 fld               dword ptr [ebp-8]
  [00000045] DC0D00000000           fmul              qword ptr [@38]
  [0000004B] DEC1                   faddp             st(1),st
  [0000004D] D945FC                 fld               dword ptr [ebp-4]
  [00000050] DC0D00000000           fmul              qword ptr [@39]
  [00000056] DEC1                   faddp             st(1),st
  [00000058] D95DF0                 fstp              dword ptr [ebp-10]
  [0000005B] D945F0                 fld               dword ptr [ebp-10]
  [0000005E] E800000000             call              ___ftouc
  [00000063] 88443202               mov               byte ptr [edx+esi+2],al
  [00000067] D945F0                 fld               dword ptr [ebp-10]
  [0000006A] E800000000             call              ___ftouc
  [0000006F] 88443201               mov               byte ptr [edx+esi+1],al
  [00000073] 880432                 mov               byte ptr [edx+esi],al
  [00000076] 83C604                 add               esi,4
  [00000079] 39CE                   cmp               esi,ecx
  [0000007B] 7C96                   jl                00000013
  [0000007D] B801000000             mov               eax,1
  [00000082] 5E                     pop               esi
  [00000083] 89EC                   mov               esp,ebp
  [00000085] 5D                     pop               ebp
  [00000086] C3                     ret               

SUMMARY
      28 .drectve
      18 .rdata
      87 .text

似乎有一个名为 ___ ftouc 的不存在的函数的调用 是浮动到未签名的字符,并且只有在链接时才可用。 (如果我错了,请纠正我)

解决方案?以不需要类型转换的方式进行数学运算。 下面的代码在x86 / x64中可以正常工作。

void ToGrayscale(unsigned char * s, int n)
{
  for (int i=0; i<n; i+=4)
     s[i+0] = s[i+1] = s[i+2] = ( (s[i+0]*114) + (s[i+1]*587) + (s[i+2]*299) ) / 1000;
}
相关问题