09-05-2025, 05:48 AM
Just for giggles, I asked google if it could convert the GoLang code to QB64PE, and here's what it came up with:
Quote:Converting this GoLang code to QB64PE 4.x is not a straightforward process because the two languages have very different paradigms, standard libraries, and approaches to image manipulation and animation. However, I can provide a conceptual translation and a partial QB64PE implementation that demonstrates the core logic.
The main challenges in this conversion are:
- Pointers and Structures: Go uses structs and pointers extensively, which are handled differently in QB64PE.
- Libraries: The Go code relies on external libraries like bild, which have no direct equivalent in QB64PE. You would have to manually recreate the functionality (e.g., blending, resizing).
- Image Handling: QB64PE uses its own built-in graphics functions for handling images (_LOADIMAGE, _PUTIMAGE), which differ from Go's image package.
- Concurrency: Go's concurrency model (goroutines) is not applicable here but is a key difference between the languages.
Here's the conceptual translation and a partial QB64PE implementation.
Conceptual Translation
The Go program lightbox.go reads an image, processes each pixel through a series of mathematical operations, and then saves the result as an animated PNG. The core steps are:
- Read Image: It opens an image file named input.jpg. In QB64PE, you'd use _LOADIMAGE.
- Process Frames: It iterates to create multiple frames for the animation. For each frame, it iterates over every pixel in the original image.
- Frequency Modulation (FM) Effect: This is the most complex part. For each pixel, it applies a frequency modulation effect using math.Cos based on the pixel's RGB values and its position (x-coordinate). It also adds a time progression offset to make the effect animate over the frames.
- Remapping: The result of the FM is a value between -1 and 1. It remaps this to an 8-bit color channel value (0-255).
- Blending: After creating the initial distorted frame, it blends it with the original image using a HardMix function. This function's logic needs to be manually replicated.
- Resizing: It resizes the blended image to half its original size. QB64PE has a _RESIZE function that can accomplish this.
- Save Animation: Finally, it saves the frames as an animated PNG. This requires an external library or manual implementation in QB64PE since it doesn't natively support APNG.
Partial QB64PE 4.x Implementation
VB.Net
Code: (Select All)' QB64PE 4.x Partial Conversion of lightbox.go
' NOTE: This is a conceptual and partial conversion.
' - It lacks error handling.
' - The APNG save functionality requires a separate library or custom code.
' - The 'HardMix' and other complex image processing functions need to be fully implemented.
' Declare custom types and functions at the top, if needed.
' QB64PE supports custom types with TYPE...END TYPE.
' We'll simulate the main logic without custom types for simplicity.
' --- Global Variables (Simulated) ---
' No need for global variables in this simple conversion, but they'd be declared here.
' --- Main Program ---
DECLARE SUB processImageFrames (sourceImage AS LONG, freqMultiplier AS DOUBLE, frameCount AS INTEGER, destFrames() AS LONG)
DECLARE FUNCTION HardMix (r1 AS INTEGER, g1 AS INTEGER, b1 AS INTEGER, r2 AS INTEGER, g2 AS INTEGER, b2 AS INTEGER) AS INTEGER
DIM SHARED sourceImage AS LONG
DIM SHARED frameCount AS INTEGER
DIM SHARED freqMultiplier AS DOUBLE
' Initialize variables
freqMultiplier = 5
frameCount = 8
' Load the source image.
sourceImage = _LOADIMAGE("input.jpg", 32) ' 32-bit color for alpha support
IF sourceImage = 0 THEN
PRINT "Error: Could not load input.jpg"
END
END IF
DIM frames(frameCount) AS LONG
' Process the frames
CALL processImageFrames(sourceImage, freqMultiplier, frameCount, frames())
' Save the frames as an APNG.
' This part is not native to QB64PE and would require an external library or custom code.
' For demonstration purposes, we'll just show the first frame.
' _PUTIMAGE , (0, 0), frames(0)
' Clean up images
_FREEIMAGE sourceImage
FOR i = 0 TO frameCount - 1
_FREEIMAGE frames(i)
NEXT i
END
' --- Subroutines and Functions ---
SUB processImageFrames (sourceImage AS LONG, freqMultiplier AS DOUBLE, frameCount AS INTEGER, destFrames() AS LONG)
DIM width AS INTEGER
DIM height AS INTEGER
DIM minOmega AS DOUBLE
DIM baseOmega AS DOUBLE
width = _WIDTH(sourceImage)
height = _HEIGHT(sourceImage)
' Calculate the omega values based on the Go code
minOmega = 2 * 3.14159265358979323846 / (0.05 * width)
baseOmega = minOmega * freqMultiplier
FOR frame = 0 TO frameCount - 1
' Create a new image for the destination frame
destFrames(frame) = _NEWIMAGE(width, height, 32)
DIM timeOffset AS DOUBLE
timeOffset = frame / frameCount * 2 * 3.14159265358979323846
' Iterate through each pixel
FOR y = 0 TO height - 1
DIM rf AS DOUBLE
DIM gf AS DOUBLE
DIM bf AS DOUBLE
rf = 0
gf = 0
bf = 0
FOR x = 0 TO width - 1
DIM pixel AS _UNSIGNED LONG
pixel = _GETIMAGE(sourceImage, x, y)
DIM r, g, b, a AS INTEGER
r = _RED32(pixel)
g = _GREEN32(pixel)
b = _BLUE32(pixel)
a = _ALPHA32(pixel)
' Add the pixel values to the running total (simulated Go code logic)
rf = rf + (r / 255.0) - 1
gf = gf + (g / 255.0) - 1
bf = bf + (b / 255.0) - 1
' Apply frequency modulation
DIM rm AS DOUBLE
DIM gm AS DOUBLE
DIM bm AS DOUBLE
rm = COS(baseOmega * x + rf + timeOffset)
gm = COS(baseOmega * x + gf + timeOffset)
bm = COS(baseOmega * x + bf + timeOffset)
' Remap signal back to channel value (0-255)
DIM rv, gv, bv AS INTEGER
rv = _UNSIGNED(INT((rm + 1) * 127.5))
gv = _UNSIGNED(INT((gm + 1) * 127.5))
bv = _UNSIGNED(INT((bm + 1) * 127.5))
' Set the pixel in the destination image
DIM newPixel AS _UNSIGNED LONG
newPixel = _RGB32(rv, gv, bv)
_PUTIMAGE , (x, y), newPixel, destFrames(frame)
NEXT x
NEXT y
' Apply blending and resizing (conceptual, not fully implemented here)
' Blending would require a pixel-by-pixel loop and a custom blend function.
' QB64PE's _RESIZE function can handle the resizing.
DIM tempImage AS LONG
tempImage = destFrames(frame)
destFrames(frame) = _RESIZE(tempImage, width / 2, height / 2)
_FREEIMAGE tempImage
NEXT frame
END SUB
' The HardMix function would be complex to implement pixel by pixel.
' Here's a conceptual placeholder.
FUNCTION HardMix (r1 AS INTEGER, g1 AS INTEGER, b1 AS INTEGER, r2 AS INTEGER, g2 AS INTEGER, b2 AS INTEGER) AS INTEGER
' The Go function's logic:
' f(i, j) = 0 if j < 1 - i, else 1
' This would need to be applied to each color channel (normalized 0-1) and then remapped.
' This is a simplified placeholder.
DIM r AS DOUBLE
DIM g AS DOUBLE
DIM b AS DOUBLE
DIM f1 AS DOUBLE
DIM f2 AS DOUBLE
f1 = r1 / 255.0
f2 = r2 / 255.0
IF f2 < 1 - f1 THEN
r = 0
ELSE
r = 1
END IF
' ... and so on for g and b
HardMix = _RGB32(r * 255, g * 255, b * 255)
END FUNCTION

