DamonOehlman / videoproc

Draw video frames to a canvas and analyse / modify pixel data
10 stars 1 forks source link

Publish the black and white filter as it's own module #6

Closed balupton closed 10 years ago

balupton commented 10 years ago

Unfortunately, having the black and white filter inside this module makes it inaccessible to browserify unless specifically included in the bundle. This means that it is not accessible via wzrd.in too.

Having it published as it's own module would be really cool, and open the door to user contributed filters a lot easier.

DamonOehlman commented 10 years ago

Interesting, I've been pretty successful at cherrypicking internal modules like this in the past. A require call like the following should do the trick:

var filter = require('rtc-videoproc/filters/grayscale');

I have seen browserify-cdn really aggressively cache modules though so it might be that the version of rtc-videoproc that is getting loaded in requirebin is 0.7.x rather than 0.8.x which has the filters included.

I'm definitely open to splitting it out though, and if you think it would help drive people creating their own filters then I think it would be a no brainer. So something like rtc-filter-grayscale then?

Also, I guess I'd be interested in thoughts from @maxogden on this as the approach I'm taking here with rtc.io is very much inspired by how well he and @substack crafted the voxeljs module landscape.

My original thoughts about trying to combine certain smaller pieces of functionality into a single module (as is the case with rtc-videoproc) which you cherrypick (much like I do with cog) is that I was trying to limit the difficulty people had finding the rtc.io module that was right for them. My concern is that the main modules that people would normally be interested in (rtc-quickconnect, etc) might possibly be buried under a pile of filter modules.

I guess at the end of the day it comes down to how people find their modules, and whether that is through a project site (such as rtc.io or voxeljs.com) or through surfing github. I tend to do the latter mostly so I guess I'm most sensitive to that case.

DamonOehlman commented 10 years ago

I see what you mean about using the browserify-cdn stuff now too with the example for the other issue:

<script src="//wzrd.in/bundle/rtc-media@latest"></script>
balupton commented 10 years ago

So before we have this:

<!--
This RTC VideoProc
This takes a streamURI and generates an imageURI with the filters applied
-->
<polymer-element name="rtc-videoproc" attributes="streamURI filter fps mime quality greedy imageURI">
    <script src="//wzrd.in/bundle/rtc-videoproc@latest"></script>
    <template></template>
    <script>
        var filters = {
            bw: function(imageData) {
                var channels = imageData.data;
                var rgb = [];
                var rgbAvg;
                var alpha;
                var ii;

                // check that we have channels is divisible by four (just as a safety)
                if (channels.length % 4 !== 0) {
                    return;
                }

                // iterate through the data
                // NOTE: decrementing loops are fast but you need to know that you will
                // hit 0 using this logic otherwise it will run forever (only 0 is falsy)
                for (ii = channels.length; ii -= 4; ) {
                    // get the rgb tuple
                    rgb = [channels[ii], channels[ii + 1], channels[ii + 2]];

                    // get the alpha value
                    alpha = channels[ii + 3];

                    // calculate the rgb average
                    rgbAvg = (rgb[0] + rgb[1] + rgb[2] ) / 3;

                    // update the values to the rgb average
                    channels[ii] = channels[ii + 1] = channels[ii + 2] = rgbAvg;
                }

                return true;
            }
        };

        Polymer('rtc-videoproc', {
            fps: 0.5,
            mime: 'image/jpeg',
            quality: 0.8,
            greedy: true,
            filter: null,
            vidChanged: function(oldValue, newValue) {
                var me = this;
                if ( newValue ) {
                    var canvas = require('rtc-videoproc')(newValue, {
                        fps: me.fps,
                        greedy: me.greedy
                    });

                    document.appendChild(canvas);

                    if ( me.filter ) {
                        var filter = filters[me.filter];
                        canvas.pipeline.add(filter);
                    }

                    canvas.addEventListener('postprocess', function(event){
                        me.imageURI = canvas.toDataURL(me.mime, me.quality);
                    });
                }
            }
        });
    </script>
</polymer-element>

Having this change I could do this:

<!--
This RTC VideoProc
This takes a streamURI and generates an imageURI with the filters applied
-->
<polymer-element name="rtc-videoproc" attributes="streamURI filter fps mime quality greedy imageURI">
    <script src="//wzrd.in/bundle/rtc-videoproc@latest"></script>
    <script src="//wzrd.in/bundle/rtc-filter-{{filter}}@latest" if="{{filter}}"></script>
    <template></template>
    <script>
        Polymer('rtc-videoproc', {
            fps: 0.5,
            mime: 'image/jpeg',
            quality: 0.8,
            greedy: true,
            filter: null,
            vidChanged: function(oldValue, newValue) {
                var me = this;
                if ( newValue ) {
                    var canvas = require('rtc-videoproc')(newValue, {
                        fps: me.fps,
                        greedy: me.greedy
                    });

                    document.appendChild(canvas);

                    if ( me.filter ) {
                        try {
                            var filter = require('rtc-filter-'+me.filter);
                            canvas.pipeline.add(filter);
                        } catch (err) {
                            console.log(err);
                        }
                    }

                    canvas.addEventListener('postprocess', function(event){
                        me.imageURI = canvas.toDataURL(me.mime, me.quality);
                    });
                }
            }
        });
    </script>
</polymer-element>
balupton commented 10 years ago

I'd be happy to implement this if you give me the right accesses :)

DamonOehlman commented 10 years ago

That's the plan - just got to get a few things sorted first. I'll create and publish the module today.

DamonOehlman commented 10 years ago

Done :)

https://github.com/rtc-io/rtc-filter-grayscale