mirror of
https://github.com/SwingTheVine/Wplace-BlueMarble.git
synced 2026-05-06 15:49:26 +00:00
Optimized template-tile generation
This commit is contained in:
parent
11590007a7
commit
663ac2950c
7 changed files with 61 additions and 183 deletions
4
dist/BlueMarble.user.js
vendored
4
dist/BlueMarble.user.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -44,7 +44,7 @@
|
|||
<a href="https://github.com/SwingTheVine/Wplace-BlueMarble/blob/main/LICENSE.txt" target="_blank" rel="noopener noreferrer"><img alt="Software License: MPL-2.0" src="https://img.shields.io/badge/Software_License-MPL--2.0-slateblue?style=flat"></a>
|
||||
<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="" target="_blank" rel="noopener noreferrer"><img alt="WakaTime" src="https://img.shields.io/badge/Coding_Time-87hrs_0mins-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-455-black?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Patches" src="https://img.shields.io/badge/Total_Patches-459-black?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Lines of Code" src="https://tokei.rs/b1/github/SwingTheVine/Wplace-BlueMarble?category=code"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Comments" src="https://tokei.rs/b1/github/SwingTheVine/Wplace-BlueMarble?category=comments"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Compression" src="https://img.shields.io/badge/Compression-75.07%25-blue"></a>
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.71.0",
|
||||
"version": "0.72.4",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.71.0",
|
||||
"version": "0.72.4",
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"terser": "^5.43.1"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.72.0",
|
||||
"version": "0.72.4",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "node build/build.js",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// ==UserScript==
|
||||
// @name Blue Marble
|
||||
// @namespace https://github.com/SwingTheVine/
|
||||
// @version 0.72.0
|
||||
// @version 0.72.4
|
||||
// @description A userscript to automate and/or enhance the user experience on Wplace.live. Make sure to comply with the site's Terms of Service, and rules! This script is not affiliated with Wplace.live in any way, use at your own risk. This script is not affiliated with TamperMonkey. The author of this userscript is not responsible for any damages, issues, loss of data, or punishment that may occur as a result of using this script. This script is provided "as is" under the MPL-2.0 license. The "Blue Marble" icon is licensed under CC0 1.0 Universal (CC0 1.0) Public Domain Dedication. The image is owned by NASA.
|
||||
// @author SwingTheVine
|
||||
// @license MPL-2.0
|
||||
|
|
|
|||
136
src/Template.js
136
src/Template.js
|
|
@ -1,37 +1,10 @@
|
|||
/** An instance of a template with comprehensive pixel counting and statistics.
|
||||
* Handles all mathematics, manipulation, and statistical analysis regarding a single template.
|
||||
*
|
||||
* TEMPLATE FEATURES:
|
||||
* - Automatic pixel counting and dimension analysis
|
||||
* - Tile-based template chunking for efficient rendering
|
||||
* - Statistical information storage and retrieval
|
||||
* - Bitmap processing with configurable scaling
|
||||
* - Memory-efficient template tile generation
|
||||
*
|
||||
* PIXEL COUNTING SYSTEM:
|
||||
* - Calculates total pixel count (width × height) during template creation
|
||||
* - Stores pixel count for statistical display and analysis
|
||||
* - Integrates with template manager for aggregate statistics
|
||||
* - Provides formatted pixel count information to user interface
|
||||
*
|
||||
/** An instance of a template.
|
||||
* Handles all mathematics, manipulation, and analysis regarding a single template.
|
||||
* @since 0.65.2
|
||||
*/
|
||||
export default class Template {
|
||||
|
||||
/** The constructor for the {@link Template} class with enhanced pixel tracking.
|
||||
*
|
||||
* Initializes a new template instance with all necessary properties for rendering
|
||||
* and statistical analysis. The pixel counting system is initialized here and
|
||||
* populated during the template creation process.
|
||||
*
|
||||
* PIXEL COUNTING INTEGRATION:
|
||||
* The pixelCount property is automatically calculated during createTemplateTiles()
|
||||
* and represents the total number of pixels in the source image (width × height).
|
||||
* This information is used for:
|
||||
* - User interface statistics display
|
||||
* - Template comparison and analysis
|
||||
* - Performance optimization decisions
|
||||
* - Memory usage estimation
|
||||
*
|
||||
* @param {Object} [params={}] - Object containing all optional parameters
|
||||
* @param {string} [params.displayName='My template'] - The display name of the template
|
||||
* @param {number} [params.sortID=0] - The sort number of the template for rendering priority
|
||||
|
|
@ -62,38 +35,10 @@ export default class Template {
|
|||
this.coords = coords;
|
||||
this.chunked = chunked;
|
||||
this.tileSize = tileSize;
|
||||
this.pixelCount = 0; // Total pixel count in template (automatically calculated during createTemplateTiles)
|
||||
this.pixelCount = 0; // Total pixel count in template
|
||||
}
|
||||
|
||||
/** Creates chunks of the template for each tile with integrated pixel counting system.
|
||||
*
|
||||
* This method processes the template image and performs several critical operations:
|
||||
* 1. PIXEL ANALYSIS: Calculates total pixel count (width × height) for statistical purposes
|
||||
* 2. TILE CHUNKING: Divides the template into tile-sized chunks for efficient rendering
|
||||
* 3. BITMAP PROCESSING: Applies scaling and filtering for optimal display quality
|
||||
* 4. MEMORY OPTIMIZATION: Creates efficient ImageBitmap objects for each tile segment
|
||||
*
|
||||
* PIXEL COUNTING IMPLEMENTATION:
|
||||
* The pixel counting system calculates the total number of pixels in the source image
|
||||
* by multiplying the bitmap width by height. This information is stored in the
|
||||
* pixelCount property and used throughout the application for:
|
||||
* - User interface statistics display
|
||||
* - Template comparison and analysis
|
||||
* - Performance monitoring and optimization
|
||||
* - Memory usage estimation and management
|
||||
*
|
||||
* TECHNICAL DETAILS:
|
||||
* - Uses createImageBitmap() for efficient image processing
|
||||
* - Applies 3x scaling factor (shreadSize) for pixel art enhancement
|
||||
* - Processes images in tile-sized chunks for memory efficiency
|
||||
* - Maintains pixel-perfect rendering with nearest-neighbor sampling
|
||||
* - Handles coordinate transformation between template and tile coordinate systems
|
||||
*
|
||||
* PERFORMANCE CONSIDERATIONS:
|
||||
* - Large templates are processed incrementally to avoid memory issues
|
||||
* - Bitmap creation uses OffscreenCanvas for optimal performance
|
||||
* - Pixel counting is performed once during initial processing
|
||||
* - Results are cached in the pixelCount property for repeated access
|
||||
/** Creates chunks of the template for each tile.
|
||||
*
|
||||
* @returns {Object} Collection of template bitmaps organized by tile coordinates
|
||||
* @since 0.65.4
|
||||
|
|
@ -106,7 +51,6 @@ export default class Template {
|
|||
const imageWidth = bitmap.width;
|
||||
const imageHeight = bitmap.height;
|
||||
|
||||
// ==================== PIXEL COUNTING SYSTEM ====================
|
||||
// Calculate total pixel count using standard width × height formula
|
||||
// This provides essential statistical information for the user interface
|
||||
const totalPixels = imageWidth * imageHeight;
|
||||
|
|
@ -123,75 +67,53 @@ export default class Template {
|
|||
|
||||
// For every tile...
|
||||
for (let pixelY = this.coords[3]; pixelY < imageHeight + this.coords[3]; ) {
|
||||
|
||||
// Draws the partial tile first, if any
|
||||
// This calculates the size based on which is smaller:
|
||||
// A. The top left corner of the current tile to the bottom right corner of the current tile
|
||||
// B. The top left corner of the current tile to the bottom right corner of the image
|
||||
const drawSizeY = Math.min(
|
||||
this.tileSize - (pixelY % this.tileSize),
|
||||
imageHeight - (pixelY - this.coords[3])
|
||||
);
|
||||
console.log(
|
||||
`Math.min(${this.tileSize} - (${pixelY} % ${
|
||||
this.tileSize
|
||||
}), ${imageHeight} - (${pixelY - this.coords[3]}))`
|
||||
);
|
||||
const drawSizeY = Math.min(this.tileSize - (pixelY % this.tileSize), imageHeight - (pixelY - this.coords[3]));
|
||||
|
||||
for (
|
||||
let pixelX = this.coords[2];
|
||||
pixelX < imageWidth + this.coords[2];
|
||||
console.log(`Math.min(${this.tileSize} - (${pixelY} % ${this.tileSize}), ${imageHeight} - (${pixelY - this.coords[3]}))`);
|
||||
|
||||
for (let pixelX = this.coords[2]; pixelX < imageWidth + this.coords[2];) {
|
||||
|
||||
) {
|
||||
console.log(`Pixel X: ${pixelX}\nPixel Y: ${pixelY}`);
|
||||
|
||||
// Draws the partial tile first, if any
|
||||
// This calculates the size based on which is smaller:
|
||||
// A. The top left corner of the current tile to the bottom right corner of the current tile
|
||||
// B. The top left corner of the current tile to the bottom right corner of the image
|
||||
const drawSizeX = Math.min(
|
||||
this.tileSize - (pixelX % this.tileSize),
|
||||
imageWidth - (pixelX - this.coords[2])
|
||||
);
|
||||
console.log(
|
||||
`Math.min(${this.tileSize} - (${pixelX} % ${
|
||||
this.tileSize
|
||||
}), ${imageWidth} - (${pixelX - this.coords[2]}))`
|
||||
);
|
||||
const drawSizeX = Math.min(this.tileSize - (pixelX % this.tileSize), imageWidth - (pixelX - this.coords[2]));
|
||||
|
||||
console.log(`Math.min(${this.tileSize} - (${pixelX} % ${this.tileSize}), ${imageWidth} - (${pixelX - this.coords[2]}))`);
|
||||
|
||||
console.log(`Draw Size X: ${drawSizeX}\nDraw Size Y: ${drawSizeY}`);
|
||||
|
||||
// Change the canvas size and wipe the canvas
|
||||
const canvasWidth =
|
||||
drawSizeX * shreadSize + (pixelX % this.tileSize) * shreadSize;
|
||||
const canvasHeight =
|
||||
drawSizeY * shreadSize + (pixelY % this.tileSize) * shreadSize;
|
||||
const canvasWidth = drawSizeX * shreadSize;// + (pixelX % this.tileSize) * shreadSize;
|
||||
const canvasHeight = drawSizeY * shreadSize;// + (pixelY % this.tileSize) * shreadSize;
|
||||
canvas.width = canvasWidth;
|
||||
canvas.height = canvasHeight;
|
||||
|
||||
console.log(
|
||||
`Draw X: ${drawSizeX}\nDraw Y: ${drawSizeY}\nCanvas Width: ${canvasWidth}\nCanvas Height: ${canvasHeight}`
|
||||
);
|
||||
console.log(`Draw X: ${drawSizeX}\nDraw Y: ${drawSizeY}\nCanvas Width: ${canvasWidth}\nCanvas Height: ${canvasHeight}`);
|
||||
|
||||
context.imageSmoothingEnabled = false; // Nearest neighbor
|
||||
|
||||
console.log(
|
||||
`Getting X ${pixelX}-${pixelX + drawSizeX}\nGetting Y ${pixelY}-${
|
||||
pixelY + drawSizeY
|
||||
}`
|
||||
);
|
||||
console.log(`Getting X ${pixelX}-${pixelX + drawSizeX}\nGetting Y ${pixelY}-${pixelY + drawSizeY}`);
|
||||
|
||||
// Draws the template segment on this tile segment
|
||||
context.clearRect(0, 0, canvasWidth, canvasHeight); // Clear any previous drawing (only runs when canvas size does not change)
|
||||
context.drawImage(
|
||||
bitmap,
|
||||
pixelX - this.coords[2],
|
||||
pixelY - this.coords[3],
|
||||
drawSizeX,
|
||||
drawSizeY,
|
||||
(pixelX % this.tileSize) * shreadSize,
|
||||
(pixelY % this.tileSize) * shreadSize,
|
||||
drawSizeX * shreadSize,
|
||||
drawSizeY * shreadSize
|
||||
bitmap, // Bitmap image to draw
|
||||
pixelX - this.coords[2], // Coordinate X to draw from
|
||||
pixelY - this.coords[3], // Coordinate Y to draw from
|
||||
drawSizeX, // X width to draw from
|
||||
drawSizeY, // Y height to draw from
|
||||
0, // Coordinate X to draw at
|
||||
0, // Coordinate Y to draw at
|
||||
drawSizeX * shreadSize, // X width to draw at
|
||||
drawSizeY * shreadSize // Y height to draw at
|
||||
); // Coordinates and size of draw area of source image, then canvas
|
||||
|
||||
// const final = await canvas.convertToBlob({ type: 'image/png' });
|
||||
|
|
@ -223,7 +145,6 @@ export default class Template {
|
|||
console.log(`Shreaded pixels for ${pixelX}, ${pixelY}`, imageData);
|
||||
|
||||
context.putImageData(imageData, 0, 0);
|
||||
//templateTiles[`${(this.coords[0] + Math.floor(pixelX / 1000)).toString().padStart(4, '0')},${(this.coords[1] + Math.floor(pixelY / 1000)).toString().padStart(4, '0')},${(pixelX % 1000).toString().padStart(3, '0')},${(pixelY % 1000).toString().padStart(3, '0')}`] = await canvas.convertToBlob({ type: 'image/png' });
|
||||
templateTiles[
|
||||
`${(this.coords[0] + Math.floor(pixelX / 1000))
|
||||
.toString()
|
||||
|
|
@ -236,11 +157,6 @@ export default class Template {
|
|||
|
||||
console.log(templateTiles);
|
||||
|
||||
// const final = await canvas.convertToBlob({ type: 'image/png' });
|
||||
// const url = URL.createObjectURL(final); // Creates a blob URL
|
||||
// window.open(url, '_blank'); // Opens a new tab with blob
|
||||
// setTimeout(() => URL.revokeObjectURL(url), 10000); // Destroys the blob 10 seconds later
|
||||
|
||||
pixelX += drawSizeX;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,32 +1,9 @@
|
|||
import Template from "./Template";
|
||||
import { numberToEncoded } from "./utils";
|
||||
|
||||
/** Manages the comprehensive template system with integrated pixel counting and statistics.
|
||||
*
|
||||
* This class handles all external requests for template modification, creation, and statistical analysis.
|
||||
* It serves as the central coordinator between template instances and the user interface, providing
|
||||
* real-time feedback on template statistics including pixel counts and rendering status.
|
||||
*
|
||||
* ENHANCED FEATURES:
|
||||
* - Real-time pixel counting and statistics display
|
||||
* - Intelligent template filtering based on active tiles
|
||||
* - Internationalized number formatting for large pixel counts
|
||||
* - Comprehensive status reporting with detailed template information
|
||||
* - Enhanced user feedback during template creation and rendering
|
||||
*
|
||||
* PIXEL COUNTING SYSTEM:
|
||||
* The template manager integrates with the Template class pixel counting system to provide:
|
||||
* - Individual template pixel counts during creation
|
||||
* - Aggregate pixel counts for multiple templates during rendering
|
||||
* - Smart filtering to count only actively displayed templates
|
||||
* - Formatted display of pixel statistics in user interface
|
||||
*
|
||||
* STATISTICAL INTEGRATION POINTS:
|
||||
* 1. Template Creation: Displays pixel count when new templates are processed
|
||||
* 2. Template Rendering: Shows aggregate pixel count for templates being displayed
|
||||
* 3. Tile Filtering: Counts pixels only for templates active in current viewport
|
||||
* 4. User Interface: Provides formatted statistics for status messages
|
||||
*
|
||||
/** Manages the template system.
|
||||
* This class handles all external requests for template modification, creation, and analysis.
|
||||
* It serves as the central coordinator between template instances and the user interface.
|
||||
* @since 0.55.8
|
||||
* @example
|
||||
* // JSON structure for a template
|
||||
|
|
@ -205,31 +182,8 @@ export default class TemplateManager {
|
|||
|
||||
}
|
||||
|
||||
/** Draws all templates on the specified tile with intelligent pixel count reporting.
|
||||
*
|
||||
* This method handles the rendering of template overlays on individual tiles and provides
|
||||
* comprehensive statistics about the templates being displayed. It integrates with the
|
||||
* pixel counting system to give users real-time feedback about template complexity.
|
||||
*
|
||||
* PIXEL COUNTING INTEGRATION:
|
||||
* The method implements intelligent pixel counting that:
|
||||
* - Identifies templates that have content in the current tile
|
||||
* - Sums pixel counts only for templates actually being rendered
|
||||
* - Formats large numbers with locale-appropriate separators
|
||||
* - Provides detailed status messages with template and pixel statistics
|
||||
*
|
||||
* PERFORMANCE OPTIMIZATIONS:
|
||||
* - Filters templates by tile coordinates before processing
|
||||
* - Counts pixels only for active templates to avoid unnecessary calculations
|
||||
* - Uses efficient array operations for template filtering and aggregation
|
||||
* - Caches formatted numbers to avoid repeated formatting operations
|
||||
*
|
||||
* USER EXPERIENCE ENHANCEMENTS:
|
||||
* - Shows both template count and total pixel count in status messages
|
||||
* - Uses internationalized number formatting for better readability
|
||||
* - Provides immediate feedback when templates are being displayed
|
||||
* - Handles singular/plural forms correctly for template count
|
||||
*
|
||||
/** Draws all templates on the specified tile.
|
||||
* This method handles the rendering of template overlays on individual tiles.
|
||||
* @param {File} tileBlob - The pixels that are placed on a tile
|
||||
* @param {[number, number]} tileCoords - The tile coordinates [x, y]
|
||||
* @since 0.65.77
|
||||
|
|
@ -246,35 +200,41 @@ export default class TemplateManager {
|
|||
const templateArray = this.templatesArray; // Stores a copy for sorting
|
||||
|
||||
// Sorts the array of Template class instances. 0 = first = lowest draw priority
|
||||
templateArray.sort((a, b) => {
|
||||
return a.sortID - b.sortID;
|
||||
});
|
||||
templateArray.sort((a, b) => {return a.sortID - b.sortID;});
|
||||
|
||||
console.log(templateArray);
|
||||
|
||||
// Retrieves the relavent template tile blobs
|
||||
const templateBlobs = templateArray
|
||||
const templatesToDraw = templateArray
|
||||
.map(template => {
|
||||
const matchingTiles = Object.keys(template.chunked).filter(tile =>
|
||||
tile.startsWith(tileCoords)
|
||||
);
|
||||
|
||||
if (matchingTiles.length === 0) {return null;} // Return nothing when nothing is found
|
||||
if (matchingTiles.length === 0) {return null;} // Return null when nothing is found
|
||||
|
||||
// Retrieves the blobs of the templates for this tile
|
||||
const matchingTileBlobs = matchingTiles.map(tile => template.chunked[tile]);
|
||||
const matchingTileBlobs = matchingTiles.map(tile => {
|
||||
|
||||
const coords = tile.split(','); // [x, y, x, y] Tile/pixel coordinates
|
||||
|
||||
return {
|
||||
bitmap: template.chunked[tile],
|
||||
tileCoords: [coords[0], coords[1]],
|
||||
pixelCoords: [coords[2], coords[3]]
|
||||
}
|
||||
});
|
||||
|
||||
return matchingTileBlobs?.[0];
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
console.log(templateBlobs);
|
||||
console.log(templatesToDraw);
|
||||
|
||||
if (templateBlobs.length > 0) {
|
||||
// ==================== INTELLIGENT PIXEL COUNTING SYSTEM ====================
|
||||
if (templatesToDraw?.bitmap?.length > 0) {
|
||||
|
||||
// Calculate total pixel count for templates actively being displayed in this tile
|
||||
// This provides accurate statistics by counting only templates with content in the current viewport
|
||||
|
||||
const totalPixels = templateArray
|
||||
.filter(template => {
|
||||
// Filter templates to include only those with tiles matching current coordinates
|
||||
|
|
@ -293,7 +253,7 @@ export default class TemplateManager {
|
|||
// Display comprehensive status information including both template count and pixel statistics
|
||||
// This gives users immediate feedback about the complexity and scope of what's being rendered
|
||||
this.overlay.handleDisplayStatus(
|
||||
`Displaying ${templateBlobs.length} template${templateBlobs.length == 1 ? '' : 's'}. ` +
|
||||
`Displaying ${templatesToDraw.bitmap.length} template${templatesToDraw.bitmap.length == 1 ? '' : 's'}. ` +
|
||||
`Total pixels: ${pixelCountFormatted}`
|
||||
);
|
||||
}
|
||||
|
|
@ -314,10 +274,12 @@ export default class TemplateManager {
|
|||
context.drawImage(tileBitmap, 0, 0, drawSize, drawSize);
|
||||
|
||||
// For each template in this tile, draw them.
|
||||
for (const templateBitmap of templateBlobs) {
|
||||
console.log(`Template Blob is ${typeof templateBitmap}`);
|
||||
console.log(templateBitmap);
|
||||
context.drawImage(templateBitmap, 0, 0);
|
||||
for (const template of templatesToDraw) {
|
||||
console.log(`Template:`);
|
||||
console.log(template);
|
||||
|
||||
// Draws the each template on the tile based on it's relative position
|
||||
context.drawImage(template.bitmap, Number(template.pixelCoords[0]) * this.drawMult, Number(template.pixelCoords[1]) * this.drawMult);
|
||||
}
|
||||
|
||||
return await canvas.convertToBlob({ type: 'image/png' });
|
||||
|
|
|
|||
Loading…
Reference in a new issue