【问题标题】:Delphi TBitmap code to Python PILDelphi TBitmap 代码到 Python PIL
【发布时间】:2012-09-02 01:36:12
【问题描述】:

我正在尝试将一些 Delphi 代码转换为 Python PIL。问题是两方面的。首先,我不是 Delphi 程序员。其次,我今天之前没有使用过 PIL,所以我可能在这两个方面都有问题。

case PixelFormat of
  pf32bit: PixSize:=4;
  pf24bit: PixSize:=3;
  pf16bit: PixSize:=2;

end;
BitCounter:=0;
for i:=0 to Height-1 do begin
  Row:=ScanLine[i];
  PB:=@Row[PixSize-1];
  for j:=0 to Width-1 do begin 
    Ch[BitCounter] := (PB^ and 1);
    ....
    inc(BitCounter);
    inc(PB, PixSize);
end;

所以我知道 PixelFormat 属性表示每个像素的大小(以字节为单位)。我还知道 ScanLine 方法应该获取代表线条的像素数组。我没有得到的是,我倾向于将每个像素可视化为 RGB 值。我习惯于提取颜色值的最低有效位。但是,我认为我什至不确定现有代码正在提取什么。我有一些 python PIL 代码可以提取同一图像中每个像素的 RGB 值,但我不知道 RGB 值的元组与前面代码中获得的 PB 变量相比如何。根据一些实验,我猜它根本无法比较。

提前致谢。

【问题讨论】:

  • 您的问题归结为“从哪个通道是最高有效字节的最低有效位”。这是明确定义的,但我一生都无法理解为什么这些信息可能有用。您何时想知道红色通道值是否为奇数?
  • @David,这篇文章的代码太奇怪了,我不得不用谷歌搜索。它将用于steganography,因为这篇文章中的代码是相同的。 user1641230,您可能会在我在此评论中链接的页面上找到答案。无论如何,有趣的技术......
  • @TLama,你是对的,它是用于检测隐写术。

标签: python delphi python-imaging-library timage tbitmap


【解决方案1】:

以防以后有人尝试这样做。感谢 David 帮助澄清 ScanLine 返回的内容。

from PIL import Image
img = Image.open('picture.gif')
(width, height) = img.size
conv = img.convert("RGB").getdata()
bt = []
for h in range(height):
  for w in range(width):
    pixel = conv.getpixel((w, h))[0]    # getpixel returns a tuple (R,G,B)
    bt.append((pixel & 0x1))

【讨论】:

    【解决方案2】:

    这将有助于显示您正在使用的变量是如何定义的,这样我们就可以看到您尝试使用它们做什么。也就是说,ScanLine 属性是一个数组,表示代表像素的字节。也就是说,您需要一个像 case 语句这样的小函数来确定字节数。但是您需要将每个 ScanLine 作为指向字节数组的指针拉出。

    所以 ScanLine 数组中的条目数是 Bitmap1.Height,这意味着您拥有正确的部分。但其余的有点不同。假设我们将一个名为 row 的变量定义为一个指针。然后要在数组中找到特定的像素,您必须相应地设置另一个指针。

    不确定这是否得到它,因为它经过了非常轻微的测试。我只是用 Longint 来表示我拉回的像素数据。您可以使用更适合您需要的东西来提取 RGB 数据,但希望这能演示如何处理 ScanLine 属性以从中获取您需要的像素数据:

    var
      i, j: integer;
      row: pointer;
      pixel: pointer;
      pixelsize: integer;
      thepixel: longint;
    begin
      for i := 0 to (Image1.Picture.Height - 1) do
        begin
          row := Image1.Picture.Bitmap.ScanLine[i];
          pixelsize := GetPixelSize(Image1.Picture.Bitmap.PixelFormat);
          pixel := row;
          for j := 0 to (Image1.Picture.Width - 1) do
            begin
              thepixel := Longint(Pixel^);
       //     Memo1.Lines.Add(IntToHex(thepixel, 12));
              Inc(Longint(Pixel), pixelsize);
            end;
         end;
    end;
    

    【讨论】:

    • 这如何解决所提出的问题(如何将 Delphi 转换为 Python PIL)?您基本上只是将 Delphi 代码重写为不同的 Delphi 代码表示。
    • @Glenn,肯是正确的。 Delphi 代码已经按照发布的方式工作。我不得不在 Python 中重新实现它的一部分。我大部分都在工作(我认为),但核心问题是我不明白原始代码中的 PB 变量具体引用了什么。它指向一个像素吗?如果是这样,它是具体的 R、G 还是 B 值(或其他)?
    • PB 指向一个颜色通道。它是一个指向字节的指针。我相信这是红色通道。我相信,在 16 位颜色中,它是蓝色通道的最后 3 位和红色通道的 5 位。所以我认为你的代码总是挑选出红色通道的最低有效位。
    • @David,这正是我想要的。感谢您的帮助。
    • @David,对于 32 位位图,像素阵列通道值排列为 BGRA,当您访问 [PixSize-1] 在这种情况下是 3 时,您将访问 alpha频道,不是吗?
    猜你喜欢
    • 2016-10-02
    • 1970-01-01
    • 2016-11-22
    • 2012-08-25
    • 1970-01-01
    • 2012-01-07
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多