gpt4 book ai didi

opengl - 从 OpenGL/GLUT 应用程序读取像素

转载 作者:行者123 更新时间:2023-12-02 09:41:31 26 4
gpt4 key购买 nike

我有一个应用程序,它使用 OpenGL 和 GLUT 在屏幕上显示一些内容。我想访问“逐像素”显示的颜色,但我无法理解所提供的方法。

访问此类数据的方法似乎是使用以下函数:readPixels::Position -> Size -> PixelData a -> IO()这绝对是非 Haskelly,因为它使用 C 模式获取目标指针并写入该指针。

第三个参数是重要的部分,其构造类似于PixelData PixelFormat DataType (Ptr a)PixelFormatDataType 都是枚举,前者采用诸如 RGBAInteger、RGBA、CMYK 等的值,后者采用诸如 >UnsignedByte、Short、Float 等。 这些选择让我感到困惑,但这不是真正的问题。我真的很难使用指针。我不知道使用 malloc 什么样的 Storable 数据来创建指针,或者如果我选择使用 mallocBytes 则要分配多少字节。

我有一个正在搞乱的函数,目前看起来像这样:

pixels :: IO ()
pixels = do
pointer <- mallocBytes 50000
let pdata = PixelData RGBA Int pointer
let pos = Position 0 0
let siz = Size 10 10
readPixels pos siz pdata
print pdata
mypixels <- peek pointer
-- TODO, what kind of data is mypixels?
free pointer

它运行良好,我只是不知道如何使用从 Ptr 获得的数据。也许我没有完全理解文档,但是如何确定指针处的数据类型以及如何在程序中使用它?请注意,我对 RGBA 和 Int 参数的选择是任意的,它们听起来足够无害。我真正想要的是某种格式的 RGBA 像素值的列表或多维列表(Color 4 或类似性质的东西)。任何帮助将不胜感激,我似乎不知所措。

最佳答案

您正在使用低级绑定(bind),不要对它们的低级感到惊讶。 readPixels 直接对应 glReadPixels (他们使用 MathML,因此使用 a browser that supports it 来查看它)。

您返回的是一个 32 位整数数组,每个整数都包含 RGBA 颜色值。您只需要 width * height * 4 字节即可,您已经过度分配了很多。

FFI 机制使读取它变得非常容易 - 它提供了 peekArray,可用于将像素数据提取到 Haskell 列表中。您还需要使用正确类型的指针。 mallocBytes 返回与void* 对应的特殊类型的指针。我使用 ForeignPtr 以便运行时负责完成它(使用 mallocBytes 您需要使用 castPtr 以及 bracket 来解释异常)。

import Data.Word
import Foreign
import Graphics.Rendering.OpenGL

readPixelArray :: Int -> Int -> Int -> Int -> IO [Word32]
readPixelArray x y w h = do
let arraySize = w * h
array <- mallocForeignPtrArray arraySize :: IO (ForeignPtr Word32)
withForeignPtr array $ \ptr -> do
-- ptr :: Ptr Word32
-- fromIntegral is needed because Position and Size store GLints not Ints
let position = Position (fromIntegral x) (fromIntegral y)
let size = Size (fromIntegral w) (fromIntegral h)
readPixels position size $ PixelData RGBA UnsignedInt ptr
peekArray arraySize ptr

现在您已经有了一个一维颜色值数组。我们可以将其拆分为这样的类型:

import Data.Bits

data Pixel = Pixel {
red :: Word8, green :: Word8, blue :: Word8, alpha :: Word8
} deriving (Eq, Show)

readPixels' :: Int -> Int -> Int -> Int -> IO [Pixel]
readPixels' x y w h = do
rawPixels <- readPixelArray x y w h
return $ map pixelFromWord32 rawPixels

-- pixelFromWord32 0xAABBCCDD = Pixel 0xAA 0xBB 0xCC 0xDD
pixelFromWord32 :: Word32 -> Pixel
pixelFromWord32 colour = Pixel (extract 3) (extract 2) (extract 1) (extract 0)
where extract idx = fromIntegral $ (colour `shiftR` (idx * 8)) .&. 0xFF

关于opengl - 从 OpenGL/GLUT 应用程序读取像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14226905/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com