Optimize pixel-based collision

Hello good. I am developing a plugin that will be a kind of Motor2d, almost everything is ready; I ran into a problem, and that is that my code is very poorly optimized for too many pixels, I don’t know what to do, I already had many conversations with ChatGPT to see how much it helped me, and it significantly reduced the lag, but not enough.

Here is the code for generating collidable pixels:

local module = {}
local PixelsGenerate = {}
function module.SetPixelHash(image: EditableImage, size:Vector2,ID:string)
		local activePixelHash = {}
		local pixels = image:ReadPixelsBuffer(Vector2.zero, size)
		local index = 1
		for y = 0, size.Y - 1 do
			for x = 0, size.X - 1 do
				local pixelIndex = (y * size.X + x) * 4
				if buffer.readu8(pixels, pixelIndex + 3) > 0 then
					activePixelHash[index] = Vector2.new(x, y)
					index = index + 1
				end
			end
		end
	PixelsGenerate[ID] = activePixelHash
	return activePixelHash
end
function module.getPixelHash(ID)
	return PixelsGenerate[ID]
end
return module

Here is the one that detects if there is a collision with another image:

local module = {}
function rotatePoint(x, y, angle, cx, cy)
	local radian = math.rad(angle)
	local cosAngle = math.cos(radian)
	local sinAngle = math.sin(radian)
	x = x - cx
	y = y - cy
	local newX = cosAngle * x - sinAngle * y + cx
	local newY = sinAngle * x + cosAngle * y + cy
	return newX, newY
end
function module.pixelPerfectCollisionFromHashes(hash1, hash2, rotation1, rotation2, size1, size2, pos1, pos2, scale1, scale2)
	local newPos1 = {}
	for i = 1, #hash1 do
		local pos = hash1[i]
		local rotatedX1, rotatedY1 = rotatePoint(pos.X, pos.Y, rotation1, size1.X / 2, size1.Y / 2)
		local scaledX1 = math.round(pos1.X + rotatedX1 * scale1.X)
		local scaledY1 = math.round(pos1.Y + rotatedY1 * scale1.Y)
		newPos1[scaledX1] = newPos1[scaledX1] or {}
		newPos1[scaledX1][scaledY1] = true
	end
	for i = 1, #hash2 do
		local pos = hash2[i]
		local rotatedX2, rotatedY2 = rotatePoint(pos.X, pos.Y, rotation2, size2.X / 2, size2.Y / 2)
		local scaledX2 = math.round(pos2.X + rotatedX2 * scale2.X)
		local scaledY2 = math.round(pos2.Y + rotatedY2 * scale2.Y)
		if newPos1[scaledX2] and newPos1[scaledX2][scaledY2] then
			return true
		end
	end
	return false
end
return module

Here I made a small code to connect the module:

local A = script.Parent:FindFirstChild("a")--imageLabel
if A.ImageContent.Object then
	A.ImageContent.Object:Destroy()
end
local B = script.Parent:FindFirstChild("b")--imageLabel
if B.ImageContent.Object then
	B.ImageContent.Object:Destroy()
end

local a = game:GetService("AssetService"):CreateEditableImage({Size = A.AbsoluteSize})--EditableImage
local b = game:GetService("AssetService"):CreateEditableImage({Size = B.AbsoluteSize})--EditableImage
A.ImageContent = Content.fromObject(a)
B.ImageContent = Content.fromObject(b)
local obj1 = game.ReplicatedStorage:WaitForChild("SpriteFolder"):WaitForChild("First Sprite"):FindFirstChild("4")--Image folder Data
local myString = obj1:GetAttribute("Image")--BufferString
local obj2 =game.ReplicatedStorage:WaitForChild("SpriteFolder"):WaitForChild("First Sprite"):FindFirstChild("5")--Image folder Data
local myString2 = obj2:GetAttribute("Image")--BufferString
a:WritePixelsBuffer(Vector2.zero,obj1:GetAttribute("Size"),buffer.fromstring(myString))--Buffer Convertion
b:WritePixelsBuffer(Vector2.zero,obj2:GetAttribute("Size"),buffer.fromstring(myString2))--Buffer Convertion


local DetecCollider = require(game.ReplicatedStorage.touch)--Name of the module Collider detector
local GenerateActivePixels = require(game.ReplicatedStorage["Pre-Pixels"])----Name of the module Pixels Collider
local hash1 = GenerateActivePixels.SetPixelHash(a, a.Size, obj1:GetAttribute("ID"))--Create a hash of the image
local hash2 = GenerateActivePixels.SetPixelHash(b, b.Size,	obj2:GetAttribute("ID"))--Create a hash of the image
local Mouse = game.Players.LocalPlayer:GetMouse()
local objMove = A
local Rotate = false
game:GetService("UserInputService").InputBegan:Connect(function(obj)
	if obj.KeyCode == Enum.KeyCode.Tab then
		if objMove == A then
			objMove = B
			A.ImageColor3 = Color3.new(1,1,1)
		else
			objMove = A
			B.ImageColor3 = Color3.new(1,1,1)
		end
	elseif obj.KeyCode == Enum.KeyCode.F then
		Rotate = true
	end
end)
game:GetService("UserInputService").InputEnded:Connect(function(obj)
	if obj.KeyCode == Enum.KeyCode.F then
		Rotate = false
	end
end)
game:GetService("RunService").RenderStepped:Connect(function(deltaTime)
	local scale1 = Vector2.new(A.AbsoluteSize.X / a.Size.X, A.AbsoluteSize.Y / a.Size.Y)--AbsoluteSizeWordFrame
	local scale2 = Vector2.new(B.AbsoluteSize.X / b.Size.X, B.AbsoluteSize.Y / b.Size.Y)--AbsoluteSizeWordFrame
	objMove.Position=UDim2.fromOffset(Mouse.X,Mouse.Y)--MoveToMousePosition
	local rotationA = A.Rotation
	local rotationB = B.Rotation
	local canCollide = DetecCollider.pixelPerfectCollisionFromHashes(hash1, hash2, rotationA, rotationB, a.Size, b.Size, A.AbsolutePosition, B.AbsolutePosition, scale1, scale2,obj1:GetAttribute("ID"),obj2:GetAttribute("ID"))
	if canCollide then
		objMove.ImageColor3 = Color3.new(0, 1, 0)
	else
		objMove.ImageColor3 = Color3.new(1, 0, 0)
	end
	if Rotate then
		objMove.Rotation +=20
		if objMove.Rotation>180 then
			objMove.Rotation=-180
		elseif objMove.Rotation<-180 then
			objMove.Rotation=180
		end
	end
end)

Comparisons:
Few pixels:

6 times more pixels

97344 Pixels

I need help optimizing this. For the rest, thank you for reading. Excuse my bad English.