Image - An image deserializer

Project Logo

Image

An image deserializer for Roblox.
Part of the OSGL project.

Links

Github Discord

About

What exactly is Image?


Image is a utility module designed primarily for plugin development that allows developers to deserialize various popular image formats into a buffer format compatible with EditableImage objects.

Serialization and deserialization


While the module primarily focuses on deserialization, it supports the following image formats:

  • PNG
  • JPEG
  • BMP
  • TGA

The library can deserialize all four formats into buffer data for use with EditableImages. Additionally, it provides serialization capabilities to convert buffer data back into the BMP format.

Reading images


To read any sort of image, use the ImageReader class exported under the main image module.

The module provides two primary functions for creating an ImageReader (what you’ll use to decode the data):

ImageReader.open(data)

Simply loads the data into the ImageReader. You should use :WithGuessedFormat() to automatically detect the image format:

local Image = require(...)
local ImageReader = Image.ImageReader

local myImg = ImageReader.open(...)
myImg:WithGuessedFormat() -- Automatically guess the format 

ImageReader.fromFormat(data, format)

Explicitly specifies the image format for deserialization. Use this method when you already know the format of the image data.

Once you’ve created your ImageReader instance, there are 3 main functions you can use:

  • :IntoHeader() - Returns the header information of the image. Since different file formats provide different headers, each one has slightly different fields. If you used fromFormat() , you’ll get proper intellisense for that specific format’s header structure. All headers include a dimensions field for consistency.
  • :IntoDimensions() - Returns only the dimensions (width and height) of the image without decoding the full image data. This is useful for quick metadata inspection.
  • :Decode() - Fully decodes the image and returns a DynamicImage object containing the pixel data ready for use with EditableImages. (More information on DynamicImage will be covered later)

:warning: Warning
It’s important to note that all of the functions mentioned so far (other than open and fromFormat) return a Result<T, E> for error handling. You can read more about results here (or the Rust equivalent here).

The Result type will either contain:

  • The expected value (T) on success, or
  • An ImageError (E) on failure

You can check if the operation succeeded using result.isOk. Use :Unwrap() to get the value when isOk is true, or :UnwrapErr() to get the error when isOk is false.

Dynamic Images

A DynamicImage represents a decoded image in memory and contains the pixel data buffer that can be used with EditableImage objects. It has the following properties:

  • .buffer - The raw pixel data buffer compatible with EditableImages
  • .width - The width of the image in pixels
  • .height - The height of the image in pixels
  • .header - The image header metadata containing format-specific information

… and the following methods:

  • :Encode(format: ImageFormat) - Encodes the image into the specified format and returns a buffer. Currently only supports encoding to BMP format. Attempting to encode to other formats will return an error.

Example usage

Integrating Image into your projects is straightforward. Here’s a basic example:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local StudioService = game:GetService("StudioService")

local Image = require(ReplicatedStorage.image)
local ImageReader = Image.ImageReader

local imageContent = StudioService:PromptImportFile():GetBinaryContents()

local img = ImageReader.open(imageContent)

-- Guess the format; if we get an error then 
-- it's not supported.
if not img:WithGuessedFormat().isOk then
    error("attempt to load an unsupported image format !!")
    return
end

local decodeResult = img:Decode()
if not decodeResult.isOk then
    error("some error while decoding. check against `Image.ImageError` to get the specific error!")
end

local decodedImageData = decodeResult:Unwrap()

-- We now have the width, height, and buffer!
print(decodedImageData.width, decodedImageData.height, decodedImageData.buffer)

Contribution


This library is apart of OSGL.

OSGL is an open-source project, and we welcome your contributions! You’re encouraged to edit the source code and share your ideas. Feel free to participate via GitHub, Discord, or even on the DevForum. Your involvement is greatly appreciated!

Credits


While you do not need to credit me for using this library, acknowledging the original creator is always appreciated but entirely optional. You are free to modify the source code as you wish, but please refrain from reuploading or claiming the asset as your own work.

9 Likes

Will there ever be support for more complicated formats, such as webp, gif (static), etc?

From what I know, GIF is quite easy to parse so possibly in the near future.
As for WEBP, the decoding process is extremely complicated and the only documentation is around 200 pages long and is extremely vague (random variables that were never mentioned suddenly appear etc) so don’t expect anything like that for a while.