I can draw an image. Now how do you mirror / flip it?


#1

I have a simple paint function:

void paint(Graphics& g) override
{
    g.drawImage(*myImage, area.removeFromLeft(8));
}

Now I just want to draw it flipped / mirrored. I’m confused by the transformation functions because there’s no obvious way to pass in rectangle bounds.


#2

https://docs.juce.com/develop/classGraphics.html#aa738caa959cc0f067eaaebca956a7012

g.drawImageTransformed()

apply an AffineTransform that rotates the image along one or 2 of the axes.

taken from: http://gamma.cs.unc.edu/COMP770/LECTURES/2D%20Transforms.pdf


#3

drawImageTransformed does not take a rectangle bounds.

Also, the example provided above changes the original position.


#4

you can try applying an AffineTransform to the graphics context first, and then doing your g.drawImage(…)

if we outright gave you the answer, you’d never learn what you would learn by experimenting with the suggestions offered…


#5

I prefer learning by copying!

Please write out a full code example so I can learn.

Edit: Once I see one full example, I can begin to understand how it works and I can experiment further.


#6
void paint(Graphics& g) override
{
    g.addTransform( /* look up how to make an AffineTransform */ );
    g.drawImage( *myImage, area.removeFromLeft(8) );
}

https://docs.juce.com/develop/classAffineTransform.html


#7

I don’t have foundational knowledge to know what to do, I’m still lost. Here’s the full context: And note the stretch to fit thing is already working. No additional code needed there, drawImage automatically stretches to fit.

void paint(Graphics& g) override
{
    auto area = getLocalBounds().toFloat();
    if (doDrawPointingLeft)
    {
        g.drawImage(*leftSideImage, area.removeFromLeft(8));
        g.drawImage(*rightSideImage, area.removeFromRight(3));
        g.drawImage(*middleImage, area);
    }
    else
    {
        // doesn't work, images no longer visible
        juce::AffineTransform transform = AffineTransform::scale(-1, 1);
        g.addTransform(transform);
        // removeFromLeft/Right swapped here
        g.drawImage(*leftSideImage, area.removeFromRight(8));
        g.drawImage(*rightSideImage, area.removeFromLeft(3));
        g.drawImage(*middleImage, area);
    }
}

image

now I need this:

image


#8

you could do all of that drawing with an instance of the Path class and g.fillRect, to be honest.
You should take your question to either the JUCE discord or The Audio Programmer discord server.

void paint(Graphics& g) override
{
    if( left ) g.addTransform( /* transform to flip along y axis */ );

    g.setColour( Colours::green );
    g.fillRect( /* coordinates of green rect */ );
    g.setColour( Colours::red );
    for( int i = 0; i < 4; ++i )
        g.fillRect( /* coordinates of red rectangle, shifted by some x amount */ );

    Path p;
    p.startNewSubPath( /* top left */ );
    p.lineTo( /* topRight */);
    p.lineTo( /* middle right */ );
    p.lineTo( /* bottom right */ );
    p.lineTo( /* bottom left */ );
    p.closeSubPath();

    g.setColour( /* that blueish color */ );
    g.fillPath( p );
}

JUCE discord

The audio Programmer discord:


#9

im using images, my example above is a simplified version of a more complex shape, so I will not be using Path objects.

Again, please help me accomplish the original task.

All I need is how to flip an image without changing its position.

Edit: And then of course I will position it with a rectangle bounds.


#10

I already showed how to apply a transform to the entire graphics context. And i gave you a transform to apply via that image/pdf. Experiment, see if you can make it happen via the documentation for how to create an AffineTransform instance with your required transformation…


#11

scale(-1,1) flips an image and moves its position since it’s flipping along the y axis

translated(1,0) should then move it back, right?


#12

Try it and see!

If it doesn’t, modify the values and see what happens. maybe you’ll get closer to your desired result, maybe not. either way, you’ll learn something about what the inputs to those functions do to the image you’re rendering.


#13

I tried it, I’m trying a lot of things. Image either fails to be flipped or disappears.


#14

matkatmusic provided this code in the Discord applications server, it works! Of course, this is flipping the entire graphics context, not the individual image, but this works for my purposes.

// horizontal flip, to be used in a paint method
g.addTransform(AffineTransform(-1, 0, getWidth(),
                                0, 1, 0));

If someone gets around to it, please provide code on how to flip an individual image easily, I’m sure it will be valuable for future readers. Or maybe there’s no simple way… I can imagine either creating a “FlippableImage” custom component class or drawing/storing a flipped version of the image during runtime to an image member.


#15

just wrap that addTransform() call and the drawImage call inside of a block with https://docs.juce.com/develop/classGraphics_1_1ScopedSaveState.html

{
    ScopedSaveState sss(g);
    g.addTransform(...);
    g.drawImage(...);
}

spend some more time reading the documentation, the tools are already there for you to figure out how to use :slight_smile:

===================================================
@jules
Feature request:

AffineTransform AffineTransform::horizontalFlip(float width)
{
    return { -1.f, 0.f, width,
              0.f, 1.f, 0.f };
} 

to complement the AffineTransform::verticalFlip(int height)


#16

Now I’m starting to understand the solution provided here: How to mirror an Image and change its colour

Personally, I think a simple image flipping function should be added to JUCE, used like this

Image flippedImage = flipImageHorizontal(originalImage) // and of course create a vertical version as well


#17

the “simple image flipping function” is using an AffineTransform to transform your graphics context before you paint() lol
It’s one line of code

g.addTransform( AffineTransform(...) );

we should all learn to fully use the existing tools before writing our own tools that duplicate existing functionality.


#18

The original goal was to flip the one image, not the graphics context. :unamused:

Edit: But I think I see how I might implement my own Image FlipImageHorizontal(const Image & image) function