Added basic resolution support for custom maps

This commit is contained in:
Mitchell McCaffrey 2020-07-13 19:36:38 +10:00
parent 3afae404d7
commit 914889c56d
3 changed files with 75 additions and 8 deletions

View File

@ -17,9 +17,15 @@ function MapTile({
onMapReset,
onDone,
}) {
const mapSource = useDataSource(map, defaultMapSources, unknownSource);
const [isMapTileMenuOpen, setIsTileMenuOpen] = useState(false);
const isDefault = map.type === "default";
const mapSource = useDataSource(
isDefault ? map : map.resolutions.length > 0 ? map.resolutions[0] : map,
defaultMapSources,
unknownSource
);
const hasMapState =
mapState &&
(Object.values(mapState.tokens).length > 0 ||

View File

@ -1,17 +1,18 @@
const lightnessDetectionOffset = 0.1;
/**
* @param {HTMLImageElement} image
* @returns {boolean} True is the image is light
*/
export function getImageLightness(image) {
const imageWidth = image.width;
const imageHeight = image.height;
const width = image.width;
const height = image.height;
let canvas = document.createElement("canvas");
canvas.width = imageWidth;
canvas.height = imageHeight;
canvas.width = width;
canvas.height = height;
let context = canvas.getContext("2d");
context.drawImage(image, 0, 0);
const imageData = context.getImageData(0, 0, imageWidth, imageHeight);
const imageData = context.getImageData(0, 0, width, height);
const data = imageData.data;
let lightPixels = 0;
@ -30,6 +31,38 @@ export function getImageLightness(image) {
}
}
const norm = (lightPixels - darkPixels) / (imageWidth * imageHeight);
const norm = (lightPixels - darkPixels) / (width * height);
return norm + lightnessDetectionOffset >= 0;
}
/**
* @param {HTMLImageElement} image the image to resize
* @param {number} size the size of the longest edge of the new image
* @param {string} type the mime type of the image
* @param {number} quality if image is a jpeg or webp this is the quality setting
*/
export async function resizeImage(image, size, type, quality) {
const width = image.width;
const height = image.height;
const ratio = width / height;
let canvas = document.createElement("canvas");
if (ratio > 1) {
canvas.width = size;
canvas.height = Math.round(size / ratio);
} else {
canvas.width = Math.round(size * ratio);
canvas.height = size;
}
let context = canvas.getContext("2d");
context.drawImage(image, 0, 0, canvas.width, canvas.height);
return new Promise((resolve) => {
canvas.toBlob(
(blob) => {
resolve({ blob, width: canvas.width, height: canvas.height });
},
type,
quality
);
});
}

View File

@ -13,6 +13,7 @@ import MapDataContext from "../contexts/MapDataContext";
import AuthContext from "../contexts/AuthContext";
import { isEmpty } from "../helpers/shared";
import { resizeImage } from "../helpers/image";
const defaultMapSize = 22;
const defaultMapProps = {
@ -22,6 +23,12 @@ const defaultMapProps = {
showGrid: false,
};
const mapResolutions = [
{ size: 256, quality: 0.25 },
{ size: 512, quality: 0.5 },
{ size: 1024, quality: 0.75 },
];
function SelectMapModal({
isOpen,
onDone,
@ -103,10 +110,31 @@ function SelectMapModal({
const url = URL.createObjectURL(blob);
return new Promise((resolve, reject) => {
image.onload = function () {
image.onload = async function () {
// Create resolutions
const resolutions = [];
for (let resolution of mapResolutions) {
if (Math.max(image.width, image.height) > resolution.size) {
const resized = await resizeImage(
image,
resolution.size,
file.type,
resolution.quality
);
const resizedBuffer = await blobToBuffer(resized.blob);
resolutions.push({
file: resizedBuffer,
width: resized.width,
height: resized.height,
type: "file",
});
}
}
handleMapAdd({
// Save as a buffer to send with msgpack
file: buffer,
resolutions,
name,
type: "file",
gridX: fileGridX,