Blur Picture without PIXI.js

Hisao Shou

Veteran
Veteran
Joined
Jan 8, 2015
Messages
146
Reaction score
21
Primarily Uses
Hello there,
I recently encountered a problem where I want to blur a picture and have it work for both Canvas (because Android deployment) and WebGL (PC/Web deployment). Can someone please tell me how can I blur a Picture without using PIXI.js?

Thank you for you time!
 

CaRa_CrAzY

Undefined Custom Title
Veteran
Joined
Jan 19, 2019
Messages
52
Reaction score
24
First Language
Portuguese
Primarily Uses
Other
I don't think I fully understand your question and I never coded for MV, but I will try to help anyways since I worked with blurring images manually in VXA.

If you are able to access an image's pixel data, you can generate another image which is a blurred copy of it by computing the average color between a pixel and it surrounding neighbors.

It's not very efficient, but if you want to blur one single image and cache it, I think there is no problem in it.

I can elaborate if you wish.
 

caethyril

^_^
Veteran
Joined
Feb 21, 2018
Messages
1,716
Reaction score
1,165
First Language
EN
Primarily Uses
RMMV
Alternatively, MV implements a blur method on its Bitmap prototype: looks like it simply draws multiple copies of the image at small x/y offsets to the original. Not sure about efficiency, but it may be more convenient if your picture is a Bitmap instance! Relevant excerpt (rpg_core.js)~
JavaScript:
/**
 * Applies a blur effect to the bitmap.
 *
 * @method blur
 */
Bitmap.prototype.blur = function() {
    for (var i = 0; i < 2; i++) {
        var w = this.width;
        var h = this.height;
        var canvas = this._canvas;
        var context = this._context;
        var tempCanvas = document.createElement('canvas');
        var tempContext = tempCanvas.getContext('2d');
        tempCanvas.width = w + 2;
        tempCanvas.height = h + 2;
        tempContext.drawImage(canvas, 0, 0, w, h, 1, 1, w, h);
        tempContext.drawImage(canvas, 0, 0, w, 1, 1, 0, w, 1);
        tempContext.drawImage(canvas, 0, 0, 1, h, 0, 1, 1, h);
        tempContext.drawImage(canvas, 0, h - 1, w, 1, 1, h + 1, w, 1);
        tempContext.drawImage(canvas, w - 1, 0, 1, h, w + 1, 1, 1, h);
        context.save();
        context.fillStyle = 'black';
        context.fillRect(0, 0, w, h);
        context.globalCompositeOperation = 'lighter';
        context.globalAlpha = 1 / 9;
        for (var y = 0; y < 3; y++) {
            for (var x = 0; x < 3; x++) {
                context.drawImage(tempCanvas, x, y, w, h, 0, 0, w, h);
            }
        }
        context.restore();
    }
    this._setDirty();
};
 

Hisao Shou

Veteran
Veteran
Joined
Jan 8, 2015
Messages
146
Reaction score
21
Primarily Uses
Alternatively, MV implements a blur method on its Bitmap prototype: looks like it simply draws multiple copies of the image at small x/y offsets to the original. Not sure about efficiency, but it may be more convenient if your picture is a Bitmap instance! Relevant excerpt (rpg_core.js)~
JavaScript:
/**[/INDENT]
[INDENT]* Applies a blur effect to the bitmap.[/INDENT]
[INDENT]*[/INDENT]
[INDENT]* @method blur[/INDENT]
[INDENT]*/[/INDENT]
[INDENT]Bitmap.prototype.blur = function() {[/INDENT]
[INDENT]    for (var i = 0; i < 2; i++) {[/INDENT]
[INDENT]        var w = this.width;[/INDENT]
[INDENT]        var h = this.height;[/INDENT]
[INDENT]        var canvas = this._canvas;[/INDENT]
[INDENT]        var context = this._context;[/INDENT]
[INDENT]        var tempCanvas = document.createElement('canvas');[/INDENT]
[INDENT]        var tempContext = tempCanvas.getContext('2d');[/INDENT]
[INDENT]        tempCanvas.width = w + 2;[/INDENT]
[INDENT]        tempCanvas.height = h + 2;[/INDENT]
[INDENT]        tempContext.drawImage(canvas, 0, 0, w, h, 1, 1, w, h);[/INDENT]
[INDENT]        tempContext.drawImage(canvas, 0, 0, w, 1, 1, 0, w, 1);[/INDENT]
[INDENT]        tempContext.drawImage(canvas, 0, 0, 1, h, 0, 1, 1, h);[/INDENT]
[INDENT]        tempContext.drawImage(canvas, 0, h - 1, w, 1, 1, h + 1, w, 1);[/INDENT]
[INDENT]        tempContext.drawImage(canvas, w - 1, 0, 1, h, w + 1, 1, 1, h);[/INDENT]
[INDENT]        context.save();[/INDENT]
[INDENT]        context.fillStyle = 'black';[/INDENT]
[INDENT]        context.fillRect(0, 0, w, h);[/INDENT]
[INDENT]        context.globalCompositeOperation = 'lighter';[/INDENT]
[INDENT]        context.globalAlpha = 1 / 9;[/INDENT]
[INDENT]        for (var y = 0; y < 3; y++) {[/INDENT]
[INDENT]            for (var x = 0; x < 3; x++) {[/INDENT]
[INDENT]                context.drawImage(tempCanvas, x, y, w, h, 0, 0, w, h);[/INDENT]
[INDENT]            }[/INDENT]
[INDENT]        }[/INDENT]
[INDENT]        context.restore();[/INDENT]
[INDENT]    }[/INDENT]
[INDENT]    this._setDirty();[/INDENT]
[INDENT]};
I have seen this around the code, the problem is that I don't know how to make it work to blur a specific picture.
 

CaRa_CrAzY

Undefined Custom Title
Veteran
Joined
Jan 19, 2019
Messages
52
Reaction score
24
First Language
Portuguese
Primarily Uses
Other
To get your picture will depend on the use case you have got.
Is this image already rendered onscreen?
Or do want to load it directly from your resources?
 

Kaliya

// Caffeine Overload
Developer
Joined
Nov 1, 2015
Messages
506
Reaction score
566
First Language
English
Primarily Uses
RMMV
I have seen this around the code, the problem is that I don't know how to make it work to blur a specific picture.
You would need to get the bitmap of that picture, since you are using "picture" as the word for it I am going to assume you literally mean picture and not say an actor. For that you'd get the bitmap property of the Sprite_Picture object. Without knowing more I can't really say how to get the picture object, because it could be something you coded custom.
 

Hisao Shou

Veteran
Veteran
Joined
Jan 8, 2015
Messages
146
Reaction score
21
Primarily Uses
I want to blur a particular already displayed Picture. So yes, it would be already rendered on the screen.

The code mentioned above seems to the whole canvas and make it a picture, not a particular bitmap.
Unfortunately I don't have enough javascript knowledge to make it blur a specific particular picture rendered on the screen.
 

caethyril

^_^
Veteran
Joined
Feb 21, 2018
Messages
1,716
Reaction score
1,165
First Language
EN
Primarily Uses
RMMV
Each Bitmap instance has its own canvas, I don't think that's a problem. The picture sprites are squirrelled away in the scene's spriteset...I tried this snippet in the console after using the Show Picture command to display something for picture 1:
JavaScript:
var id = 1;  // game picture ID
var pic = SceneManager._scene._spriteset._pictureContainer.children[id - 1];
pic.bitmap.blur(), pic._refresh();
It did blur the indicated picture's image, but it also turned transparent areas of that image opaque (black). Not sure why, may be a result of how the blur method works. :kaoslp:

I also experimented a little with setting the bitmap's filters to 'blur(8px)', but that didn't seem to have any effect:
JavaScript:
var id = 1;  // game picture ID
var pic = SceneManager._scene._spriteset._pictureContainer.children[id - 1];
var cs = pic.bitmap._canvas.style;
cs.filter = 'blur(8px)';
cs.webkitFilter = 'blur(8px)';
pic._refresh();
 

Hisao Shou

Veteran
Veteran
Joined
Jan 8, 2015
Messages
146
Reaction score
21
Primarily Uses
Each Bitmap instance has its own canvas, I don't think that's a problem. The picture sprites are squirrelled away in the scene's spriteset...I tried this snippet in the console after using the Show Picture command to display something for picture 1:
JavaScript:
var id = 1;  // game picture ID
var pic = SceneManager._scene._spriteset._pictureContainer.children[id - 1];
pic.bitmap.blur(), pic._refresh();
It did blur the indicated picture's image, but it also turned transparent areas of that image opaque (black). Not sure why, may be a result of how the blur method works. :kaoslp:

I also experimented a little with setting the bitmap's filters to 'blur(8px)', but that didn't seem to have any effect:
JavaScript:
var id = 1;  // game picture ID
var pic = SceneManager._scene._spriteset._pictureContainer.children[id - 1];
var cs = pic.bitmap._canvas.style;
cs.filter = 'blur(8px)';
cs.webkitFilter = 'blur(8px)';
pic._refresh();
Thank you for your answer!
This is exactly what I wanted. Yet, do you know any way how to revert the picture back to normal? I think the blur function takes the filename of the bitmap and works strictly on that, which prevents me from creating two same pictures and making only one blurred
 

Kaliya

// Caffeine Overload
Developer
Joined
Nov 1, 2015
Messages
506
Reaction score
566
First Language
English
Primarily Uses
RMMV
You could create two pictures, and blur only one. It doesn't blur the actual file, but the image in memory.
 

Hisao Shou

Veteran
Veteran
Joined
Jan 8, 2015
Messages
146
Reaction score
21
Primarily Uses
You could create two pictures, and blur only one. It doesn't blur the actual file, but the image in memory.
Nope. This does not work.
Apparently this command:
Code:
var id = 1;  // game picture ID
var pic = SceneManager._scene._spriteset._pictureContainer.children[id - 1];
pic.bitmap.blur(), pic._refresh();
... will blur both pictures even if they have different IDs but same location/name.
 

caethyril

^_^
Veteran
Joined
Feb 21, 2018
Messages
1,716
Reaction score
1,165
First Language
EN
Primarily Uses
RMMV
Apparently this command:
Code:
var id = 1;  // game picture ID
var pic = SceneManager._scene._spriteset._pictureContainer.children[id - 1];
pic.bitmap.blur(), pic._refresh();
... will blur both pictures even if they have different IDs but same location/name.
Oh, yes. Drat. I think it's because of the image reservation system: both pictures point to the same reserved bitmap data and that's what's getting blurred? I hadn't noticed because when I was testing I showed two pictures with the same image, then blurred one of them and forced that one to redraw. The other remained unblurred because it had no reason to redraw its canvas. All subsequent pictures drawn referencing that image, though, are blurry. :kaoback:

This blur (maybe there's a better option) uses a blitting approach ("paint on canvas"), so to unblur the reservation I think you'd need to force it to reload from file, i.e. delete the existing reservation. Just tested with this script call and it seems to work OK... :kaoswt:
JavaScript:
var id  = 1;       // game picture ID
var key = 'icon';  // picture file name
var pic = SceneManager._scene._spriteset._pictureContainer.children[id - 1];
pic.bitmap.blur(), pic._refresh();
key = 'img/pictures/' + key + '.png:0';
delete ImageManager._imageCache._items[key];
I think a technically better approach would be to have a separate "blurred image" cache, but I'm not personally down to write such a plugin at present. :kaoslp:
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts


I have recently returned to try and developing games after I learned how to use digital drawing software.

My goal is to start simple and small. I am mostly aiming to create a game that I would play, and to tell a story that I would like to read. :smile:
RayGarden7 wrote on Geovid's profile.
Hey I'm new the RPG Maker forms as well and was having the same problem you are with needing 30 post or 30 threads we must complete. Maybe we could help each other out? Why you on the forms what is your goal?

Apparently the various VS core plugins are going to be free. :LZSexcite:
Now to go wash the stink off myself from having had to look at Twitter.
:rtear:

heroine before entering いせかい

Forum statistics

Threads
100,806
Messages
979,761
Members
132,448
Latest member
Tip2202
Top