Fixed template download/conversion corruption

This commit is contained in:
SwingTheVine 2026-03-01 21:55:53 -05:00
parent fdc3278e80
commit 5b1489e26e
8 changed files with 71 additions and 22 deletions

View file

@ -2,7 +2,7 @@
// @name Blue Marble
// @name:en Blue Marble
// @namespace https://github.com/SwingTheVine/
// @version 0.90.68
// @version 0.90.76
// @description A userscript to enhance the user experience on Wplace.live. This includes, but is not limited to: uploading images to display locally on a canvas, adding a button to move the Wplace color palette menu, and other QoL features.
// @description:en A userscript to enhance the user experience on Wplace.live. This includes, but is not limited to: uploading images to display locally on a canvas, adding a button to move the Wplace color palette menu, and other QoL features.
// @author SwingTheVine
@ -2066,20 +2066,44 @@ Getting Y ${pixelY}-${pixelY + drawSizeY}`);
console.log(`Absolute coordinates: (${absoluteSmallestX}, ${absoluteSmallestY}) and (${absoluteLargestX}, ${absoluteLargestY})`);
const templateWidth = absoluteLargestX - absoluteSmallestX;
const templateHeight = absoluteLargestY - absoluteSmallestY;
const canvasWidth = templateWidth * this.drawMult;
const canvasHeight = templateHeight * this.drawMult;
console.log(`Template Width: ${templateWidth}
Template Height: ${templateHeight}`);
const canvas = new OffscreenCanvas(templateWidth, templateHeight);
Template Height: ${templateHeight}
Canvas Width: ${canvasWidth}
Canvas Height: ${canvasHeight}`);
const canvas = new OffscreenCanvas(canvasWidth, canvasHeight);
const context = canvas.getContext("2d");
context.imageSmoothingEnabled = false;
templateTileKeysSorted.forEach((key, index) => {
const [tileX, tileY, pixelX, pixelY] = key.split(",").map(Number);
const tileImage = templateTilesImageSorted[index];
const absoluteX = tileX * this.tileSize + pixelX;
const absoluteY = tileY * this.tileSize + pixelY;
console.log(`Drawing tile (${tileX}, ${tileY}, ${pixelX}, ${pixelY}) (${absoluteX}, ${absoluteY}) at (${absoluteX - absoluteSmallestX}, ${absoluteY - absoluteSmallestY}) on the canvas...`);
context.drawImage(tileImage, absoluteX - absoluteSmallestX, absoluteY - absoluteSmallestY, tileImage.width / this.drawMult, tileImage.height / this.drawMult);
context.drawImage(tileImage, (absoluteX - absoluteSmallestX) * this.drawMult, (absoluteY - absoluteSmallestY) * this.drawMult, tileImage.width, tileImage.height);
});
return canvas.convertToBlob({ type: "image/png" });
context.globalCompositeOperation = "destination-over";
context.drawImage(canvas, 0, -1);
context.drawImage(canvas, 0, 1);
context.drawImage(canvas, -1, 0);
context.drawImage(canvas, 1, 0);
const smallCanvas = new OffscreenCanvas(templateWidth, templateHeight);
const smallContext = smallCanvas.getContext("2d");
smallContext.imageSmoothingEnabled = false;
smallContext.drawImage(
canvas,
0,
0,
templateWidth * this.drawMult,
templateHeight * this.drawMult,
// Source image size
0,
0,
templateWidth,
templateHeight
// Small canvas size
);
return smallCanvas.convertToBlob({ type: "image/png" });
function convertBase64ToImage(base64) {
return new Promise((resolve, reject) => {
const image = new Image();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -51,7 +51,7 @@
<a href="https://discord.gg/tpeBPy46hf" target="_blank" rel="noopener noreferrer"><img alt="Contact Me" src="https://img.shields.io/badge/Contact_Me-gray?style=flat&logo=Discord&logoColor=white&logoSize=auto&labelColor=cornflowerblue"></a>
<a href="https://bluemarble.lol/" target="_blank" rel="noopener noreferrer"><img alt="Blue Marble Website" src="https://img.shields.io/badge/Blue_Marble_Website-crqch-blue?style=flat&logo=globe&logoColor=white"></a>
<a href="" target="_blank" rel="noopener noreferrer"><img alt="WakaTime" src="https://img.shields.io/badge/Coding_Time-212hrs_17mins-blue?style=flat&logo=wakatime&logoColor=black&logoSize=auto&labelColor=white"></a>
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Patches" src="https://img.shields.io/badge/Total_Patches-1107-black?style=flat"></a>
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Patches" src="https://img.shields.io/badge/Total_Patches-1115-black?style=flat"></a>
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Lines of Code" src="https://img.shields.io/badge/Lines_Of_Code-5908-blue?style=flat"></a>
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Comments" src="https://img.shields.io/badge/Lines_Of_Comments-5160-blue?style=flat"></a>
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Compression" src="https://img.shields.io/badge/Compression-73.34%25-blue"></a>

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "wplace-bluemarble",
"version": "0.90.68",
"version": "0.90.76",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wplace-bluemarble",
"version": "0.90.68",
"version": "0.90.76",
"devDependencies": {
"esbuild": "^0.25.0",
"jsdoc": "^4.0.5",

View file

@ -1,6 +1,6 @@
{
"name": "wplace-bluemarble",
"version": "0.90.68",
"version": "0.90.76",
"type": "module",
"homepage": "https://bluemarble.lol/",
"repository": {

View file

@ -2,7 +2,7 @@
// @name Blue Marble
// @name:en Blue Marble
// @namespace https://github.com/SwingTheVine/
// @version 0.90.68
// @version 0.90.76
// @description A userscript to enhance the user experience on Wplace.live. This includes, but is not limited to: uploading images to display locally on a canvas, adding a button to move the Wplace color palette menu, and other QoL features.
// @description:en A userscript to enhance the user experience on Wplace.live. This includes, but is not limited to: uploading images to display locally on a canvas, adding a button to move the Wplace color palette menu, and other QoL features.
// @author SwingTheVine

View file

@ -1,5 +1,5 @@
import Template from "./Template";
import { base64ToUint8, colorpaletteForBlueMarble, consoleError, consoleLog, consoleWarn, localizeNumber, numberToEncoded, sleep } from "./utils";
import { base64ToUint8, colorpaletteForBlueMarble, consoleError, consoleLog, consoleWarn, localizeNumber, numberToEncoded, sleep, viewCanvasInNewTab } from "./utils";
import WindowWizard from "./WindowWizard";
/** Manages the template system.
@ -351,13 +351,14 @@ export default class TemplateManager {
// Calculates the template/canvas width and height
const templateWidth = absoluteLargestX - absoluteSmallestX;
const templateHeight = absoluteLargestY - absoluteSmallestY;
const canvasWidth = templateWidth * this.drawMult;
const canvasHeight = templateHeight * this.drawMult;
console.log(`Template Width: ${templateWidth}\nTemplate Height: ${templateHeight}`);
console.log(`Template Width: ${templateWidth}\nTemplate Height: ${templateHeight}\nCanvas Width: ${canvasWidth}\nCanvas Height: ${canvasHeight}`);
// Creates a new canvas the size of the template
const canvas = new OffscreenCanvas(templateWidth, templateHeight);
const canvas = new OffscreenCanvas(canvasWidth, canvasHeight);
const context = canvas.getContext('2d');
context.imageSmoothingEnabled = false; // Forces nearest neighbor scaling algorithm
// For each tile...
templateTileKeysSorted.forEach((key, index) => {
@ -373,12 +374,36 @@ export default class TemplateManager {
console.log(`Drawing tile (${tileX}, ${tileY}, ${pixelX}, ${pixelY}) (${absoluteX}, ${absoluteY}) at (${absoluteX - absoluteSmallestX}, ${absoluteY - absoluteSmallestY}) on the canvas...`);
// Draws the tile to the canvas AND scales it down in the process
context.drawImage(tileImage, absoluteX - absoluteSmallestX, absoluteY - absoluteSmallestY, tileImage.width / this.drawMult, tileImage.height / this.drawMult);
// Draws the tile to the canvas
context.drawImage(tileImage, (absoluteX - absoluteSmallestX) * this.drawMult, (absoluteY - absoluteSmallestY) * this.drawMult, tileImage.width, tileImage.height);
})
// The expanded template is now on the canvas
context.globalCompositeOperation = "destination-over"; // Draw under the canvas (new draws only show in place of transparent pixels)
// Extends the template vertically to create columns
context.drawImage(canvas, 0, -1);
context.drawImage(canvas, 0, 1);
// Extends the columns horizontally to become a solid template
context.drawImage(canvas, -1, 0);
context.drawImage(canvas, 1, 0);
const smallCanvas = new OffscreenCanvas(templateWidth, templateHeight);
const smallContext = smallCanvas.getContext("2d");
smallContext.imageSmoothingEnabled = false; // Forces nearest neighbor scaling algorithm
// Downscale the template
smallContext.drawImage(
canvas,
0, 0, templateWidth * this.drawMult, templateHeight * this.drawMult, // Source image size
0, 0, templateWidth, templateHeight // Small canvas size
);
// Returns a blob
return canvas.convertToBlob({ type: 'image/png' });
return smallCanvas.convertToBlob({ type: 'image/png' });
/** Turns a chunked base 64 string template tile into an Image template tile
* @param {string} base64 - Base64 string of image data (without URI header)