I am trying to convert some Delphi code to Python PIL. The problem is two pronged. First, I'm not a Delphi programmer. Second, I haven't used PIL before today so I may have problems in either area.
我试图将一些Delphi代码转换为Python PIL。这个问题是双管齐下的。首先,我不是德尔福程序员。其次,我今天之前没有使用过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;
So I get that the PixelFormat attribute denotes the size of each pixel in bytes. I also get that the ScanLine method is supposed to get an array of pixels that represent the line. What I don't get is that I tend to visualize each pixel as an RGB value. I'm used to extracting the least significant bit of a color value. However, I don't think I'm even sure what the existing code is extracting. I have some python PIL code that will extract RGB values of each pixel in the same image, but I don't know how the tuple of RGB values compares to PB variable obtained in the earlier code. Based on some experiments I'm guessing that it doesn't compare at all.
所以我得到PixelFormat属性表示每个像素的大小(以字节为单位)。我还得到ScanLine方法应该得到一个代表该行的像素数组。我没有得到的是我倾向于将每个像素可视化为RGB值。我习惯于提取颜色值的最低位。但是,我认为我甚至不确定现有代码的提取方式。我有一些python PIL代码将提取同一图像中每个像素的RGB值,但我不知道RGB值的元组如何与早期代码中获得的PB变量进行比较。基于一些实验,我猜它根本没有比较。
Thanks in advance.
提前致谢。
2 个解决方案
#1
1
In case anyone is trying to do this later. Thanks to David for the help in clarifying what ScanLine was returning.
如果有人试图在以后这样做。感谢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
-1
It would help to show how the variables you are using are defined so we can see what you are trying to do with them. That said, the ScanLine property is an array representing the bytes representing the pixels. That said, you need a little function like your case statement to determine the number of bytes. But you need to pull each ScanLine off as a pointer to an array of bytes.
这将有助于显示您正在使用的变量是如何定义的,以便我们可以看到您尝试使用它们的内容。也就是说,ScanLine属性是一个表示代表像素的字节的数组。也就是说,你需要一个像case语句一样的函数来确定字节数。但是您需要将每个ScanLine作为指向字节数组的指针拉出。
So the number of entries in the ScanLine array is Bitmap1.Height, which means you have that part right. But the rest is a little different. Let's say we define a variable named row to be a pointer. Then to find a specific pixel in the array, you have to set another pointer accordingly.
因此,ScanLine数组中的条目数是Bitmap1.Height,这意味着您拥有该部分。但其余的则有所不同。假设我们将名为row的变量定义为指针。然后,要在数组中查找特定像素,您必须相应地设置另一个指针。
Not sure if this gets it since it's very lightly tested. I just used Longint to represent the pixel data I was pulling back. You'd use something more fitting for your needs to pull out the RGB data, but hopefully this demonstrates how to handle the ScanLine property to get the pixel data you need out of it:
不确定这是否得到它,因为它是非常轻微的测试。我只是使用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;
#1
1
In case anyone is trying to do this later. Thanks to David for the help in clarifying what ScanLine was returning.
如果有人试图在以后这样做。感谢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
-1
It would help to show how the variables you are using are defined so we can see what you are trying to do with them. That said, the ScanLine property is an array representing the bytes representing the pixels. That said, you need a little function like your case statement to determine the number of bytes. But you need to pull each ScanLine off as a pointer to an array of bytes.
这将有助于显示您正在使用的变量是如何定义的,以便我们可以看到您尝试使用它们的内容。也就是说,ScanLine属性是一个表示代表像素的字节的数组。也就是说,你需要一个像case语句一样的函数来确定字节数。但是您需要将每个ScanLine作为指向字节数组的指针拉出。
So the number of entries in the ScanLine array is Bitmap1.Height, which means you have that part right. But the rest is a little different. Let's say we define a variable named row to be a pointer. Then to find a specific pixel in the array, you have to set another pointer accordingly.
因此,ScanLine数组中的条目数是Bitmap1.Height,这意味着您拥有该部分。但其余的则有所不同。假设我们将名为row的变量定义为指针。然后,要在数组中查找特定像素,您必须相应地设置另一个指针。
Not sure if this gets it since it's very lightly tested. I just used Longint to represent the pixel data I was pulling back. You'd use something more fitting for your needs to pull out the RGB data, but hopefully this demonstrates how to handle the ScanLine property to get the pixel data you need out of it:
不确定这是否得到它,因为它是非常轻微的测试。我只是使用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;