Stamping the pen trails on the stage is lossy

The following script will stamp several hundred random turtles on the Stage, and then continuously take the pen trails image and stamp it back on a clear Stage:


Because the pen trails costume is always a lower resolution than the Stage, sampling/anti-aliasing is applied to the stamp costume, making it blurry. Is there any way to directly set the costume of the pen trails in a lossless format, directly setting the costume instead of stamping it all funky like this?

edit: there is a solution, but it requires JavaScript

Yep, our fellow @gplb2718, there is a way. But doing it unfortunately requires to apply pure
JavaScript. If I remember, this changes how the costumes and pen trails render in the GUI.

// SpriteMorph rendering

SpriteMorph.prototype.render = function (ctx) {
    var myself = this,
        facing, // actual costume heading based on my rotation style
        isFlipped,
        isLoadingCostume,
        cst,
        pic, // (flipped copy of) actual costume based on my rotation style
        stageScale,
        handle;

        ctx.imageSmoothingEnabled = false;
    isLoadingCostume = this.costume &&
        typeof this.costume.loaded === 'function';
    stageScale = this.parent instanceof StageMorph ?
            this.parent.scale : 1;
    facing = this.rotationStyle ? this.heading : 90;
    if (this.rotationStyle === 2) {facing = 90;
        this.heading = ((this.heading < 0) ? (
        360 - (Math.abs(this.heading) % 360)) : (
        this.heading % 360)); isFlipped = !(
        this.heading < 180);  /* Very good! */
    };  if (this.costume && !isLoadingCostume) {
        pic = isFlipped ? this.costume.flipped() : this.costume; ctx.save();
        ctx.scale(this.scale * stageScale, this.scale * stageScale);
        ctx.translate(Math.round((this.imageOffset).x),
        Math.round((this.imageOffset).y));
        ctx.rotate(radians(facing - 90));
        ctx.drawImage(pic.contents, 0, 0);
        ctx.restore();

    } else {
        facing = isFlipped ? -90 : facing;
        SpriteMorph.uber.render.call(this, ctx, facing);

        if (isLoadingCostume) { // retry until costume is done loading
            cst = this.costume;
            handle = setInterval(
                function () {
                    myself.wearCostume(cst, true);
                    clearInterval(handle);
                },
                100
            );
            return this.wearCostume(null, true);
        };
    }; // apply graphics effects to image
    this.cachedImage = this.applyGraphicsEffects(
    this.cachedImage); this.version = Date.now();
};

// StageMorph rendering

StageMorph.prototype.render = function (ctx) {
    ctx.imageSmoothingEnabled = false;  ctx.save(
    );  ctx.fillStyle = this.color.toString();
    ctx.fillRect(0, 0, this.width(), this.height());
    if (this.costume && !(this.costume.loaded instanceof Function)) {
        ctx.scale(this.scale, this.scale);
        ctx.drawImage(
            this.costume.contents,
            Math.round((this.width() / this.scale - this.costume.width()) / 2),
            Math.round((this.height() / this.scale - this.costume.height()) / 2)
        );  this.cachedImage = this.applyGraphicsEffects(this.cachedImage);
    };  ctx.restore();
    this.version = Date.now(); // for observer optimization
};

this.rerender();
if (this.parent instanceof StageMorph) {this.parent.rerender();};

We have to apply this in every agent (any sprite or the stage it self) :eyes::

In every Canvas2D context, the image aliasing is determined by the “imageSmoothingEnabled”
property. Also that if you want to preserve the pixels, you need to round their coordinates to
evade blurriness. Now, try the code in the “JavaScript function” block, and see the changes. :)

I really hope this gets added into vanilla, as it would make terminal scrolling MUCH easier, and make pen projects that use stamping clean.

I mentioned the same issue in a bug report I made last month. I’m glad that someone posted a solution in this topic even it if is a JavaScript solution. It’s nice to have an explanation. Of course we always have the option of redoing the stamping and pen work but there could be cases where that’s undesirable.