Video with alpha mask

#1

Hi,
I’m dealing with video transparencies. I have a couple of videos in mp4 formats. The first video contains color information, the second has the alpha channel mapped on gray scale. I would like to use the second video as an alpha mask for the first.

I wrote down this piece of code, taken from the forum, but it doesn’t work to me, it display the first video with no transparencies

void ofApp::draw(){
ofBackground(255, 255, 255);
Drop.getTexture().setAlphaMask(DropMask.getTexture());
Drop.draw(100, 100, 200, 200);

DropMask.draw(100, 100, 200, 200);

}

Here is the project:

Any help ?
Thank you very much !!!

#2

you shouldn’t need to draw the mask at all just the first video and you should be able to do setAlphaMask only once in setup after opening the videos. No need to do it everytime in draw

#3

Thank you for the fast reply, unfortunately it doesn’t work. I have got this error message:

[ error ] ofTexture: getTextureData(): texture has not been allocated

#4

I suppose he is willing to update the alpha mask for every frame, like one of the two videos is the mask for the other.

I did not try the code but it looks like one of the two videos (Drop) is never play()ed.

ciao
Davide

#5

Besides I do not remember the details at the moment but a couple of years ago I experimented playing videos with embedded alpha mask on OSX (some apple prores codec may be) and they were doing fine without having to mess with two separated video files and setAlphaMask.

Massimiliano I can try to find the code if you think it could be useful.

#6

It would help a lot. Than you !!!

#7

Ok I used the ofxAVFVideoPlayer addon, it was a few of versions ago but it should work with newer ones too.

Just use it like a regular video player, try feeding it with a prores 4444 encoded video with alpha channel.

It performs quite well, by the way, the prores encoded files are very large but the player can play smoothly more than a few of them together with negligible delay. A nice tool :slight_smile:

#8

Cool ! Thank you very much.

#9

the video player in the core already uses AV foundation since some years ago so there shouldn’t be any need to use an external addon.

also the videoplayer initializes 1 texture at the beginning and keeps using it so there’s no need to keep setting the alpha mask every time since the texture should be the same.

Are you loading the video player with loadAsync? in that case the texture might not be loaded until the first frame arrives but otherwise it should be ready once play is called.

#10

Solved, thank you very much !!

#12

Hi Massimiliano. Would you mind sharing how you solved it? I am trying to achieve the same effect but haven’t succeeded yet.
Thank you in advance.
Best,
Paulo

#13

Hi, well I did it in a not very elegant way, I guess.
I defined a couple of ofVideoPlayer and an ofImage, which is the frame to display

ofVideoPlayer Drop;
ofVideoPlayer DropMask;
ofImage DropImage;

I load the video and the mask

Drop.setPixelFormat(OF_PIXELS_BGRA);
Drop.load("DROP_10_COMP_and loop_color.mp4");
DropMask.load("DROP_10_COMP_and loop_alpha.mp4");

then in update section

if (Drop.isFrameNew()) {
   ofPixels pixels = Drop.getPixels();
   ofPixels pixelsMasK = DropMask.getPixels();

   for (int y=0; y<pixels.getHeight(); y++) {
      for (int x=0; x<pixels.getWidth(); x++) {

         ofColor col = pixels.getColor(x,y);
         ofColor alpha = pixelsMasK.getColor(x,y);
         col.a = alpha.b;

         pixels.setColor(x,y,col);
      }
   }
   DropImage.setFromPixels(pixels);
}
#14

Thank you Massimiliano.
I’ll leave my solution here as well. Hope it helps.

#include "ofApp.h"
ofImage bckg;
ofImage mask;
ofVideoPlayer video;
ofVideoPlayer videoA;


void ofApp::setup() {
	bckg.load("background.jpg");
	video.load("video1.mp4");
	videoA.load("videoalpha1.mp4");
	video.play();
	videoA.play();
	mask.allocate(bckg.getWidth(), bckg.getHeight(), OF_IMAGE_COLOR_ALPHA);
}
void ofApp::update() {
	video.update();
	videoA.update();
	mask.setFromPixels(videoA.getPixels());
	mask.setImageType(OF_IMAGE_COLOR_ALPHA);
	mask.getPixels().setChannel(3, circMask.getPixels().getChannel(0));
	mask.update();
	video.getTexture().setAlphaMask(mask.getTexture());
}
void ofApp::draw() {
	ofBackground(100);
	bckg.draw(0, 0);
	video.draw(0, 0);


	stringstream ss;
	ss << "FPS: " << ofToString(ofGetFrameRate(), 0) << endl << endl;
	ofDrawBitmapStringHighlight(ss.str().c_str(), 20, 20);
}