Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transparency flag to pngview #25

Open
bverc opened this issue Jun 10, 2019 · 15 comments
Open

Transparency flag to pngview #25

bverc opened this issue Jun 10, 2019 · 15 comments

Comments

@bverc
Copy link
Contributor

bverc commented Jun 10, 2019

Thanks for such a great tool.

How complex would adding a transparency flag to reduce the alpha value by a fraction of the entire image at imageload or on display?

@AndrewFromMelbourne
Copy link
Owner

AndrewFromMelbourne commented Jun 11, 2019

It shouldn't be too hard, but unfortunately I don't have time these days to make changes to the code myself. There are two ways this could be done.

  1. Change the Alpha channel in the image itself after the PNG file has been read, by adding new functionality to image.c
  2. Pass in a different alpha value to addElementImageLayer at the moment the alpha value for the element is fixed at 255 in imageLayer.c

@bverc
Copy link
Contributor Author

bverc commented Jun 11, 2019

Thanks. I might have play and see what I can pull together.

@bverc
Copy link
Contributor Author

bverc commented Jul 12, 2019

Had a play around with the following code:

    VC_DISPMANX_ALPHA_T alpha =
    {
        DISPMANX_FLAGS_ALPHA_FROM_SOURCE, 
        255, /*alpha 0->255*/
        0
    };

However, couldn't get any noticeable affect from either adjusting the 255 value, 0 value, or replacing DISPMANX_FLAGS_ALPHA_FROM_SOURCE with DISPMANX FLAGS_ALPHA_FIXED_ALL_PIXELS

Looks like I'll need to dive in dispmanx a bit further.

@AndrewFromMelbourne
Copy link
Owner

Sorry to hear that. It has been a long time since I looked at this. If I get a chance I will have see what I can do.

@raspi-user
Copy link

In file imageLayer.c function addElementImageLayer() change DISPMANX_FLAGS_ALPHA_FROM_SOURCE to DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS

For dynamic alpha change:
add function:

void
setImageLayerAlpha(
IMAGE_LAYER_T *il,
int32_t alpha,
DISPMANX_UPDATE_HANDLE_T update)
{
#define ELEMENT_CHANGE_OPACITY (1<<1)
int8_t result = vc_dispmanx_element_change_attributes(update,
il->element,
ELEMENT_CHANGE_OPACITY,
il->layer,
alpha,
NULL,
NULL,
0,
(DISPMANX_TRANSFORM_T)0);
assert(result == 0);
}

call:

update = vc_dispmanx_update_start(0);
assert(update != 0);
setImageLayerAlpha(&imageLayer, alpha, update);
int result = vc_dispmanx_update_submit_sync(update);
assert(result == 0);

@nagualcode
Copy link

pardon me... What is the use case for this?

@raspi-user
Copy link

re: nagualcode

Ask the OP(bverc), I was just answering their question. I would guess, fading in/out an image...

@bverc
Copy link
Contributor Author

bverc commented Aug 12, 2019

Thanks @raspi-user

Firstly, the reason my first attempt failed was due the bug #16. Recompiling didn't regenerate my library so it appeared as nothing was happening.

Once I sorted that, changing the two lines below worked:

        DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 
        100, /*alpha 0->255*/

The solution by @raspi-user above is a more elegant solution to the same outcome.

However, my application can't use the same alpha value for the entire image. I'd like fully transparent pixels to remain transparent, while all other alphas are scaled down. Is there a nice way to do this with dispmanx?

@raspi-user
Copy link

Agreed @bverc , I'm looking for a solution for the same problem - true PNG transparency with dynamic alpha changes. The code above was developed en-route to this goal.

As suggested by @AndrewFromMelbourne, the required code change will probably have to be performed in image.c.

@bverc
Copy link
Contributor Author

bverc commented Aug 12, 2019

Something like this maybe:

void
setImageOpacity(
    IMAGE_T *image,
    uint8_t opacity)
{
    if (image->setPixelDirect != NULL)
    {
        RGBA8_T rgba;
        int j;
        for (j = 0 ; j < image->height ; j++)
        {
            int i;
            for (i = 0 ; i < image->width ; i++)
            {
                getPixelRGB(image, i, j, &rgba);
                rgba.alpha = (uint8_t)(rgba.alpha * (uint16_t)opacity / 255);
                setPixelRGB(image, i, j, &rgba);
            }
        }
    }
}

Doesn't seem to work, but I think this is close.

@bverc
Copy link
Contributor Author

bverc commented Feb 7, 2021

I'm not sure why I gave up on this 18 months ago, as the code I wrote in the above comment works fine. I'll look at adding a flag to pngview and submitting a pull request if of interest to others.

bverc added a commit to bverc/raspidmx that referenced this issue Feb 7, 2021
For AndrewFromMelbourne#25
Added a function to image .c to alllow adjustment of alpha channel over an entire image relatively.
Added flag to pngview to control adjust alpha channel
@magdesign
Copy link

@bverc :Thanks for your great and working pull request: #31

I am trying to load a *.png file with pngview and fade it in and out interactively or over time, how would I achieve this?
Tried with a bash script ./pngview -a $i -t 50 to change the value from the -a flag, but this results in a flickering image.

Any help very welcome!

@bverc
Copy link
Contributor Author

bverc commented May 23, 2021

Thanks @magdesign
I'd really appreciate you commenting on the PR to say you have tested it and it works.

Your problem I don't think would be too difficult. If you check -a is set then call setImageAlphaRelative() from within the while (run) loop, that should work I think. (Similar to the interactive move function)

I think you would have to run vc_dispmanx_update_submit_sync() afterwards, and I have no understanding how that function works.

Something like the following (Warning: Untested!):

uint8_t alpha_frame = 0;

while (run)
{
    ...

    //---------------------------------------------------------------------

    if (alphaRelativeSet == true)
    {
        alpha_frame = currentTime % 256; // however you want to calculate your alpha
        setImageAlphaRelative(&(imageLayer.image), alpha_frame);

        result = vc_dispmanx_update_submit_sync(update);
        assert(result == 0);
    }

    //---------------------------------------------------------------------

    ...
}

Good luck!

@magdesign
Copy link

Thanks.
I tried with adding this bit of code into: pngview.c
in line: 215
compiler fails with:

pngview.c: In function ‘main’:
pngview.c:215:11: error: ‘alpha_frame’ undeclared (first use in this function)
           alpha_frame = currentTime % 256; // however you want to calculate your alpha
           ^~~~~~~~~~~
pngview.c:215:11: note: each undeclared identifier is reported only once for each function it appears in
pngview.c:215:25: error: ‘currentTime’ undeclared (first use in this function)
           alpha_frame = currentTime % 256; // however you want to calculate your alpha
                         ^~~~~~~~~~~
pngview.c:218:9: error: ‘result’ undeclared (first use in this function)
         result = vc_dispmanx_update_submit_sync(update);
         ^~~~~~
pngview.c:218:49: error: ‘update’ undeclared (first use in this function)
         result = vc_dispmanx_update_submit_sync(update);
                                                 ^~~~~~
pngview.c:105:13: warning: variable ‘alphaRelative’ set but not used [-Wunused-but-set-variable]
     uint8_t alphaRelative = 0;
             ^~~~~~~~~~~~~

The main goal is to fade in/out an image interactively and also move it in x and y and zoom interactively so it would be possible to have an image displayed and then send realtime data to move it over the screen and make it any size and transparency... maybe a bit an overkill for a C beginner like I am :-)

@bverc
Copy link
Contributor Author

bverc commented May 25, 2021

Sounds like you didn't add the first line of that code before the loop:
uint8_t alpha_frame = 0;

Regardless, anyway I think your application is a bit niche to try and include in pngview and I think your original idea of calling from bash is correct. Not sure what is causing the flickering. Perhaps the reloading of the image and recalculating the alpha takes too long.

I wonder if keeping two instances of pngview running, so have one running, while the second is loading then swap over. Or start each one as a background process and start the next 10ms earlier than the previous one is expected to end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants