Searched through the forums for a way to do this and couldn’t find anything conclusive.
Just as a note: I’m still rather new to programming in JUCE; most of my graphics programming experience has been in C with SDL2 or messing around in Turbo C on old MSDOS systems just to see what I could do.
In SDL2, you can draw pixel data into a Uint32 buffer in the “background”, so to speak, and then copy that buffer all at once by with SDL_UpdateTexture() and then SDL_RenderCopy()
I wasn’t able to find anything directly similar in JUCE but I was able to hack together this method
juce::SoftwareImageType temp;
if (screenBuffer == nullptr) return;
screenImage = juce::Image(temp.create(juce::Image::ARGB, SCREEN_WIDTH, SCREEN_HEIGHT, true));
if (screenImage.isValid())
{
juce::Image::BitmapData pixelMap(screenImage, juce::Image::BitmapData::writeOnly);
memcpy(pixelMap.data, screenBuffer, SCREEN_AREA * sizeof *screenBuffer);
}
which copies the buffer to an image which can then my drawn to the window with drawImageWithin
My question is for those more experienced with JUCE’s more niche functions: is there a better/faster way to do this? I’ve looked over the JUCE website, the JUCE forum, and the source code and haven’t been able to find anything that inherently does what I’m looking for, so I just wanted to check if this was the “right” way to render an array of pixel data
For a full example of code that uses this method:
class MainComponent : public juce::Component
{
public:
MainComponent::MainComponent()
{
screenBuffer = new uint32_t[SCREEN_AREA];
memset(screenBuffer, 0, SCREEN_AREA * sizeof *screenBuffer);
setSize (600, 400);
for (int y = 50; y < 150; y++)
for (int x = 100; x < 200; x++)
*(screenBuffer + x + (y * SCREEN_WIDTH)) = 0xFFFFFFFF;
copyScreenBuffer();
}
MainComponent::~MainComponent()
{
if (screenBuffer != nullptr)
{
delete[] screenBuffer;
screenBuffer = nullptr;
}
}
//==============================================================================
void MainComponent::paint (juce::Graphics& g)
{
g.fillAll (juce::Colours::blue);
g.setImageResamplingQuality(juce::Graphics::lowResamplingQuality);
g.drawImageWithin(screenImage, 0, 0, getWidth(), getHeight(),
juce::RectanglePlacement::stretchToFit, false);
}
void MainComponent::resized()
{
}
void MainComponent::copyScreenBuffer()
{
juce::SoftwareImageType temp;
if (screenBuffer == nullptr) return;
screenImage = juce::Image(temp.create(juce::Image::ARGB, SCREEN_WIDTH, SCREEN_HEIGHT, true));
if (screenImage.isValid())
{
juce::Image::BitmapData pixelMap(screenImage, juce::Image::BitmapData::writeOnly);
memcpy(pixelMap.data, screenBuffer, SCREEN_AREA * sizeof *screenBuffer);
repaint(getBounds());
}
}
private:
juce::Image screenImage;
uint32_t *screenBuffer = nullptr;
const int SCREEN_WIDTH = 300,
SCREEN_HEIGHT = 200,
SCREEN_AREA = SCREEN_WIDTH * SCREEN_HEIGHT;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainComponent)
};
Which draws:
(obviously this is an overly simplified example and the surrounding code can be more fleshed out in a full program)