在 Ruby 中逐像素读取图像

发布于 2024-10-05 14:02:44 字数 266 浏览 2 评论 0原文

我正在尝试打开一个图像文件并将像素列表按颜色存储在变量/数组中,以便我可以将它们一一输出。

图像类型:可以是 BMP、JPG、GIF 或 PNG。其中任何一个都可以,只需要支持一个。 颜色输出:RGB 或 Hex。

我看过几个库(RMagick、Quick_Magick、Mini_Magick 等),它们看起来都有些过头了。 Heroku 在使用 ImageMagick 时也遇到了一些困难,并且我的测试无法运行。我的应用程序是在 Sinatra 中。

有什么建议吗?

I'm trying to open an image file and store a list of pixels by color in a variable/array so I can output them one by one.

Image type: Could be BMP, JPG, GIF or PNG. Any of them is fine and only one needs to be supported.
Color Output: RGB or Hex.

I've looked at a couple libraries (RMagick, Quick_Magick, Mini_Magick, etc) and they all seem like overkill. Heroku also has some sort of difficulties with ImageMagick and my tests don't run. My application is in Sinatra.

Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

别闹i 2024-10-12 14:02:44

您可以使用Rmagickeach_pixel< /a> 方法。 each_pixel 接收一个块。对于每个像素,块被传递像素、像素的列号和行号。它从左到右、从上到下迭代像素。

所以像这样:

pixels = []

img.each_pixel do |pixel, c, r|
    pixels.push(pixel)
end
# pixels now contains each individual pixel of img

You can use Rmagick's each_pixel method for this. each_pixel receives a block. For each pixel, the block is passed the pixel, the column number and the row number of the pixel. It iterates over the pixels from left-to-right and top-to-bottom.

So something like:

pixels = []

img.each_pixel do |pixel, c, r|
    pixels.push(pixel)
end
# pixels now contains each individual pixel of img
说谎友 2024-10-12 14:02:44

我认为 Chunky PNG 应该适合你。它是纯红宝石,相当轻量级,内存效率高,并提供对像素数据和图像元数据的访问。

I think Chunky PNG should do it for you. It's pure ruby, reasonably lightweight, memory efficient, and provides access to pixel data as well as image metadata.

何以笙箫默 2024-10-12 14:02:44

如果您只是打开文件来显示字节,而不需要将其作为图像进行操作,那么就像打开文件一样,这是一个简单的过程,读取 X 个字节,然后迭代它们。类似于:

File.open('path/to/image.file', 'rb') do |fi|
  byte_block = fi.read(1024)
  byte_block.each_byte do |b|
    puts b.asc
  end 
end

这只会以十进制形式输出字节。您需要查看字节值并构建 RGB 值来确定颜色,因此也许使用 each_slice(3) 并以 3 字节的倍数读取会有所帮助。

各种图像格式包含不同的标头和尾部块,用于存储有关捕获设备的图像、数据格式和 EXIF 信息的信息,具体取决于类型。如果您要读取文件并直接输出字节,例如未压缩的 TIFF,那么使用未压缩的内容可能会更好。一旦您决定,您可以根据需要跳转到文件中跳过标题,或者也可以阅读这些标题以查看或了解其中的内容。维基百科的图像文件格式页面是了解有关各种可用格式的更多信息的一个很好的起点。

如果您只想查看图像数据,那么高级库之一将会有所帮助,因为它们具有捕获图像特定部分的接口。但是,实际上访问字节并不难,也不难跳转。

如果您想了解有关 EXIF 块的更多信息,该块用于描述许多不同供应商的 Jpeg 和 TIFF 格式 ExifTool 可以很方便。它是用 Perl 编写的,因此您可以查看代码是如何工作的。该文档很好地显示了标题块和字段,您可以使用该应用程序读取/写入值。

我正在测试一个新路由器,所以我还没有机会测试该代码,但它应该很接近。我会稍微检查一下并更新答案(如果不起作用)。

If you are only opening the file to display the bytes, and don't need to manipulate it as an image, then it's a simple process of opening the file like any other, reading X number of bytes, then iterating over them. Something like:

File.open('path/to/image.file', 'rb') do |fi|
  byte_block = fi.read(1024)
  byte_block.each_byte do |b|
    puts b.asc
  end 
end

That will merely output bytes as decimal. You'll want to look at the byte values and build up RGB values to determine colors, so maybe using each_slice(3) and reading in multiples of 3 bytes will help.

Various image formats contain differing header and trailing blocks used to store information about the image, data format and EXIF information for the capturing device, depending on the type. Probably going with a something that is uncompressed would be good if you are going to read a file and output the bytes directly, such as uncompressed TIFF. Once you've decided on that you can jump into the file to skip headers if you want, or just read those too to see or learn what's in them. Wikipedia's Image file formats page is a good jumping off place for more info on the various formats available.

If you only want to see the image data then one of the high-level libraries will help as they have interfaces to grab particular sections of the image. But, actually accessing the bytes isn't hard, nor is it to jump around.

If you want to learn more about the EXIF block, used to describe a lot of different vendor's Jpeg and TIFF formats ExifTool can be handy. It's written in Perl so you can look at how the code works. The docs nicely show the header blocks and fields, and you can read/write values using the app.

I'm in the process of testing a new router so I haven't had a chance to test that code, but it should be close. I'll check it in a bit and update the answer if that didn't work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文