how get matrix from image

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Pedin
Prole
Posts: 16
Joined: Thu Aug 04, 2016 7:21 pm

how get matrix from image

Post by Pedin »

im try manipulate images and i cant find a function that returns a matrix ou other datastructure from image, someone know how can i do it?without use getpixel() pixel by pixel from imagedata?
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: how get matrix from image

Post by pgimeno »

You can get an FFI pointer, which you can use to manipulate the data:

Code: Select all

local ffi = require 'ffi'
local imgBytes = ffi.cast('uint8_t *', imageData:getFFIPointer())
You can also get the same data as a string, but then you can't manipulate it:

Code: Select all

local imgBytesAsString = imageData:getString()
User avatar
zorg
Party member
Posts: 3468
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: how get matrix from image

Post by zorg »

Technically speaking, you can also manipulate the string as well... but in lua, that would mean generating a LOT of garbage due to any edits creating new strinsg... and it's just not the best solution.

You could also use mapPixel, which is way faster than get/setPixel.

That said, an Image object is data on the GPU; you NEED to use an ImageData if you want to manipulate the image's contents yourself outside of the graphics card.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: how get matrix from image

Post by pgimeno »

zorg wrote: Wed Sep 02, 2020 4:13 pm Technically speaking, you can also manipulate the string as well... but in lua, that would mean generating a LOT of garbage due to any edits creating new strinsg... and it's just not the best solution.
I meant that it's not useful for manipulating the object because there's no setString, so there doesn't seem to be much point in manipulating the string itself, or am I missing something again?

Also, Lua strings are immutable, so you don't really manipulate them, you just create new ones with different contents.
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: how get matrix from image

Post by ReFreezed »

pgimeno wrote: Thu Sep 03, 2020 4:04 am I meant that it's not useful for manipulating the object because there's no setString, so there doesn't seem to be much point in manipulating the string itself, or am I missing something again?
You can use the modified string as an argument when calling newImageData() though.

Anyway, using ImageData:mapPixel() is probably the best option for retrieving/updating all pixels in an image.
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: how get matrix from image

Post by pgimeno »

ReFreezed wrote: Thu Sep 03, 2020 8:38 am Anyway, using ImageData:mapPixel() is probably the best option for retrieving/updating all pixels in an image.
Depends on what you call best. Here's a benchmark:

Code: Select all

local imgData = love.image.newImageData(4096, 4096)
local time = love.timer.getTime

local t1 = time()

--[[

local function desaturate(x, y, r, g, b, a)
  local v = 1/3 * (r + g + b)
  return v, v, v, a
end

imgData:mapPixel(desaturate)

--[=[]]

local ffi = require 'ffi'

local data = ffi.cast('uint8_t *', imgData:getFFIPointer())

for i = 0, 4 * imgData:getWidth() * imgData:getHeight() - 1, 4 do
  local v = 1/3 * (data[i] + data[i+1] + data[i+2])
  data[i] = v
  data[i+1] = v
  data[i+2] = v
end

--]=]

local t2 = time()

print(t2 - t1)
Switch between both by adding or removing a dash in the first comment.

Sample run:
  • With mapPixel: 0.15587068721652 seconds
  • With FFI: 0.025541770271957 seconds
That means FFI is ~6x faster in this example. I didn't expected otherwise: mapPixel prevents compilation of the inner body due to the constant switching between C and Lua, and the lack of an actual Lua loop. The FFI loop allows compilation, and LuaJIT's compiled code is fast.
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: how get matrix from image

Post by ReFreezed »

pgimeno wrote: Thu Sep 03, 2020 2:34 pm Depends on what you call best. (...)
You're right. I wasn't thinking about the FFI approach. I would say mapPixel is more of a "Lua" way of doing things as with FFI you're directly reading from and writing to memory (i.e. bypassing everything in Lua completely). It depends on what the OP is looking for. Both ways are however most likely better than using getPixel/setPixel or anything involving getString.
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
Pedin
Prole
Posts: 16
Joined: Thu Aug 04, 2016 7:21 pm

Re: how get matrix from image

Post by Pedin »

pgimeno wrote: Wed Sep 02, 2020 10:06 am You can get an FFI pointer, which you can use to manipulate the data:

Code: Select all

local ffi = require 'ffi'
local imgBytes = ffi.cast('uint8_t *', imageData:getFFIPointer())
You can also get the same data as a string, but then you can't manipulate it:

Code: Select all

local imgBytesAsString = imageData:getString()
thanks, i will use the ffi pointer, it was what i was looking for. but another question arose, as the name says, it’s a pointer. but you use some functions there like the cast, is the imageBytes a copy by reference or by value?
Pedin
Prole
Posts: 16
Joined: Thu Aug 04, 2016 7:21 pm

Re: how get matrix from image

Post by Pedin »

zorg wrote: Wed Sep 02, 2020 4:13 pm Technically speaking, you can also manipulate the string as well... but in lua, that would mean generating a LOT of garbage due to any edits creating new strinsg... and it's just not the best solution.

You could also use mapPixel, which is way faster than get/setPixel.

That said, an Image object is data on the GPU; you NEED to use an ImageData if you want to manipulate the image's contents yourself outside of the graphics card.
yeah i write wrong, it was to be imageData.
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: how get matrix from image

Post by pgimeno »

Pedin wrote: Fri Sep 04, 2020 2:35 pm thanks, i will use the ffi pointer, it was what i was looking for. but another question arose, as the name says, it’s a pointer. but you use some functions there like the cast, is the imageBytes a copy by reference or by value?
A pointer is a reference. If you modify the data pointed to by the pointer, you're modifying the image. In a previous post in this thread, I posted an example using both FFI and mapPixel to desaturate the colours of the image, that is, to convert the image to black-and-white.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 5 guests