sclass G22BurnIn { settable double alphaStep = 0.1; settable double tolerance = 0.1; settable Color backgroundColor = Color.black; int toleranceSquaredInt; int w, h; int[] mask; void processFrame(BufferedImage frame) { toleranceSquaredInt = iround(sqr(tolerance*255)*3); int w = frame.getWidth(), h = frame.getHeight(); if (mask == null || this.w != w || this.h != h) { this.w = w; this.h = h; this.mask = new int[w*h]; } // We assume the frame has no transparency var gp = grabbableIntPixels_fastOrSlow(frame); int n = w*h, iMask = 0, iFrame = gp.offset; int[] pixels = gp.data; int[] mask = this.mask; for y to h: { for x to w: { int mpix = mask[iMask]; int fcol = pixels[iFrame++] & 0xFFFFFF; if (mpix == 0) mpix = firstTime(fcol); else { int mcol = mpix & 0xFFFFFF; if (isSameColor(mcol, fcol)) mpix = sameColor(mpix); else mpix = differentColor(mpix, fcol); } mask[iMask++] = mpix; } iFrame += gp.scanlineStride-w; } } bool isSameColor(int col1, int col2) { ret toleranceSquaredInt == 0 ? col1 == col2 : rgbDistanceSquaredInt(col1, col2) <= tolerance; } int firstTime(int fcol) { ret withAlpha(alphaStep, fcol); } int sameColor(int mpix) { double newAlpha = rgbAlphaZeroToOne(mpix)+alphaStep; ret withAlpha(newAlpha, mpix); } int differentColor(int mpix, int fcol) { ret 0; } BufferedImage image() { if (mask == null) null; var img = bufferedImage(w, h, mask); ret renderImageOnBackground(backgroundColor, img); } }