Last active
March 2, 2025 03:54
-
-
Save tinkerer-red/ae6c05e0362fb38b7b55aa17c7cef156 to your computer and use it in GitHub Desktop.
`buffer_create_from_surface` and `surface_create_from_buffer`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region jsDoc | |
/// @func buffer_create_from_surface | |
/// @desc Creates a fixed-size buffer containing the pixel data from the given surface. The buffer size is determined | |
/// by the surface's dimensions and format. The buffer is populated with the surface's pixel data starting at byte offset 0. | |
/// @param {Id.Surface} _surf - The source surface from which to read pixel data. | |
/// @returns {Id.Buffer} A buffer containing the surface's pixel data. | |
#endregion | |
function buffer_create_from_surface(_surf) { | |
// Get surface properties | |
var _width = surface_get_width(_surf); | |
var _height = surface_get_height(_surf); | |
var _format = surface_get_format(_surf); | |
// Determine bytes per pixel based on format | |
var _bytes_per_pixel; | |
switch (_format) { | |
case surface_rgba4unorm: _bytes_per_pixel = 2; break; | |
case surface_rgba8unorm: _bytes_per_pixel = 4; break; | |
case surface_rgba16float: _bytes_per_pixel = 8; break; | |
case surface_rgba32float: _bytes_per_pixel = 16; break; | |
case surface_r8unorm: _bytes_per_pixel = 1; break; | |
case surface_r16float: _bytes_per_pixel = 2; break; | |
case surface_r32float: _bytes_per_pixel = 16; break; | |
case surface_rg8unorm: _bytes_per_pixel = 2; break; | |
default: throw "Unsupported format" | |
} | |
// Create a buffer large enough to store the surface data | |
var _buff_size = _width * _height * _bytes_per_pixel; | |
var _buff = buffer_create(_buff_size, buffer_fixed, 1); | |
// Write surface data into buffer | |
buffer_get_surface(_buff, _surf, 0); | |
buffer_seek(_buff, buffer_seek_start, 0); | |
return _buff; | |
} | |
#region jsDoc | |
/// @func surface_create_from_buffer | |
/// @desc Creates a new surface with the specified width, height, and format, and populates it with pixel data | |
/// read from the provided buffer. The buffer data is written to the surface starting at byte offset 0. | |
/// @param {Id.Buffer} _buff - The buffer containing the pixel data to write to the surface. | |
/// @param {Real} _width - The width of the new surface. | |
/// @param {Real} _height - The height of the new surface. | |
/// @param {Constant.SurfaceFormatConstant} _format - The format to use for the new surface. | |
/// @returns {Id.Surface} The newly created surface containing the pixel data from the buffer. | |
#endregion | |
function surface_create_from_buffer(_buff, _width, _height, _format=surface_rgba8unorm) { | |
// Create a new surface with the specified width, height, and format. | |
var _surf = surface_create(_width, _height, _format); | |
// Determine bytes per pixel based on format | |
var _bytes_per_pixel; | |
switch (_format) { | |
case surface_rgba4unorm: _bytes_per_pixel = 2; break; | |
case surface_rgba8unorm: _bytes_per_pixel = 4; break; | |
case surface_rgba16float: _bytes_per_pixel = 8; break; | |
case surface_rgba32float: _bytes_per_pixel = 16; break; | |
case surface_r8unorm: _bytes_per_pixel = 1; break; | |
case surface_r16float: _bytes_per_pixel = 2; break; | |
case surface_r32float: _bytes_per_pixel = 16; break; | |
case surface_rg8unorm: _bytes_per_pixel = 2; break; | |
default: throw "Unsupported format" | |
} | |
// Calculate the expected buffer size based on the surface dimensions and bytes per pixel. | |
var _expected_size = _width * _height * _bytes_per_pixel; | |
var _actual_size = buffer_get_size(_buff); | |
// Safety check: Ensure the buffer size matches the expected size. | |
if (_actual_size != _expected_size) { | |
show_error("Buffer size mismatch: expected " + string(_expected_size) + " but got " + string(_actual_size), true); | |
} | |
// Write the pixel data from the buffer into the surface, starting at byte offset 0. | |
buffer_set_surface(_buff, _surf, 0); | |
// Return the newly created surface. | |
return _surf; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function string_real_size(_text, _font) { | |
// Store previous render settings | |
var prev_font = draw_get_font(); | |
// Set the font | |
draw_set_font(_font); | |
// Get the estimated width and height | |
var _approx_width = string_width(_text); | |
var _approx_height = string_height(_text); | |
// Create a temporary surface | |
var _surf = surface_create(_approx_width, _approx_height); | |
surface_set_target(_surf); | |
draw_clear_alpha(c_black, 0); // Fully transparent background | |
// Draw the text | |
draw_set_color(c_white); | |
draw_text(0, 0, _text); | |
// Reset render target | |
surface_reset_target(); | |
// Create a buffer and read the pixel data | |
var _buff = buffer_create_from_surface(_surf); | |
var x1 = infinity, | |
var y1 = infinity, | |
var x2 = -infinity; | |
var y2 = -infinity; | |
buffer_seek(_buff, buffer_seek_start, 0); | |
// Scan the buffer to find non-transparent pixels | |
for (var _y = 0; _y < _approx_height; _y++) { | |
for (var _x = 0; _x < _approx_width; _x++) { | |
var r = buffer_read(_buff, buffer_u8); | |
var g = buffer_read(_buff, buffer_u8); | |
var b = buffer_read(_buff, buffer_u8); | |
var a = buffer_read(_buff, buffer_u8); // Alpha channel | |
if (a > 0) { // If the pixel is not fully transparent | |
if (_x < x1) x1 = _x; | |
if (_x > x2) x2 = _x; | |
if (_y < y1) y1 = _y; | |
if (_y > y2) y2 = _y; | |
} | |
} | |
} | |
// Calculate the actual width & height | |
var real_width = (x2 >= x1) ? (x2 - x1 + 1) : 0; | |
var real_height = (y2 >= y1) ? (y2 - y1 + 1) : 0; | |
// Cleanup | |
buffer_delete(_buff); | |
surface_free(_surf); | |
draw_set_font(prev_font); // Restore previous font | |
// Return the real text size and bounding box | |
return { | |
width: real_width, | |
height: real_height, | |
x1: x1, // Left bound | |
y1: y1, // Top bound | |
x2: x2, // Right bound | |
y2: y2 // Bottom bound | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment