mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-25 03:04:13 +00:00
Image optimalization (#343)
I have minify images and convert them to webp format that reduce size and keep quality. Reduce size of bg image since its already blured by css so no need to have it that big. Reduce size of thumbs and helper images in helper modals should be fine since they will not exceed the container size. Even that make them larger than containter just to be safe
This commit is contained in:
@@ -73,7 +73,7 @@ export class HelpModal extends LitElement {
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<div class="flex flex-col items-center">
|
||||
<div data-i18n="help_modal.ui_leaderboard" class="text-gray-300">Leaderboard</div>
|
||||
<img src="/images/helpModal/leaderboard.png" alt="Leaderboard" title="Leaderboard" />
|
||||
<img src="/images/helpModal/leaderboard.webp" alt="Leaderboard" title="Leaderboard" />
|
||||
</div>
|
||||
<div>
|
||||
<p data-i18n="help_modal.ui_leaderboard_desc">Shows the top players of the game and their names, % owned land and gold.</p>
|
||||
@@ -85,7 +85,7 @@ export class HelpModal extends LitElement {
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<div class="flex flex-col items-center w-full md:w-[80%]">
|
||||
<div data-i18n="help_modal.ui_control" class="text-gray-300">Control panel</div>
|
||||
<img src="/images/helpModal/controlPanel.png" alt="Control panel" title="Control panel" />
|
||||
<img src="/images/helpModal/controlPanel.webp" alt="Control panel" title="Control panel" />
|
||||
</div>
|
||||
<div>
|
||||
<p data-i18n="help_modal.ui_control_desc" class="mb-4">The control panel contains the following elements:</p>
|
||||
@@ -103,7 +103,7 @@ export class HelpModal extends LitElement {
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<div class="flex flex-col items-center">
|
||||
<div data-i18n="help_modal.ui_options" class="text-gray-300">Options</div>
|
||||
<img src="/images/helpModal/options.png" alt="Options" title="Options" />
|
||||
<img src="/images/helpModal/options.webp" alt="Options" title="Options" />
|
||||
</div>
|
||||
<div>
|
||||
<p data-i18n="help_modal.ui_options_desc" class="mb-4">The following elements can be found inside:</p>
|
||||
@@ -121,7 +121,7 @@ export class HelpModal extends LitElement {
|
||||
<div data-i18n="radial_title" class="text-2xl font-bold text-center">Radial menu</div>
|
||||
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<img src="/images/helpModal/radialMenu.png" alt="Radial menu" title="Radial menu", class="radial-menu-image" />
|
||||
<img src="/images/helpModal/radialMenu.webp" alt="Radial menu" title="Radial menu", class="radial-menu-image" />
|
||||
<div>
|
||||
<p data-i18n="help_modal.radial_desc" class="mb-4">Right clicking (or touch on mobile) opens the radial menu. From there you can:</p>
|
||||
<ul>
|
||||
@@ -141,7 +141,7 @@ export class HelpModal extends LitElement {
|
||||
<div class="flex flex-col md:flex-row gap-4 mt-2">
|
||||
<div class="flex flex-col items-center w-full md:w-[80%]">
|
||||
<div data-i18n="help_modal.info_enemy_panel" class="text-gray-300">Enemy info panel</div>
|
||||
<img src="/images/helpModal/infoMenu.png" alt="Enemy info panel" title="Enemy info panel" />
|
||||
<img src="/images/helpModal/infoMenu.webp" alt="Enemy info panel" title="Enemy info panel" />
|
||||
</div>
|
||||
<div class="pt-4">
|
||||
<p data-i18n="help_modal.info_enemy_desc" class="mb-4">
|
||||
@@ -160,7 +160,7 @@ export class HelpModal extends LitElement {
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<div class="flex flex-col items-center w-full md:w-[62%]">
|
||||
<div data-i18n="help_modal.info_ally_panel" class="text-gray-300">Ally info panel</div>
|
||||
<img src="/images/helpModal/infoMenuAlly.png" alt="Ally info panel" title="Ally info panel" />
|
||||
<img src="/images/helpModal/infoMenuAlly.webp" alt="Ally info panel" title="Ally info panel" />
|
||||
</div>
|
||||
<div class="pt-4">
|
||||
<p data-i18n="help_modal.info_ally_desc" class="mb-4">
|
||||
@@ -262,17 +262,17 @@ export class HelpModal extends LitElement {
|
||||
<div class="flex flex-col md:flex-row gap-4 mt-2">
|
||||
<div class="flex flex-col items-center">
|
||||
<div data-i18n="help_modal.icon_crown" class="text-gray-300">Crown - This is the number 1 player in the leaderboard</div>
|
||||
<img src="/images/helpModal/number1.png" alt="Number 1 player" title="Number 1 player" />
|
||||
<img src="/images/helpModal/number1.webp" alt="Number 1 player" title="Number 1 player" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center">
|
||||
<div data-i18n="help_modal.icon_traitor" class="text-gray-300">Crossed swords - Traitor. This player attacked an ally.</div>
|
||||
<img src="/images/helpModal/traitor.png" alt="Traitor" title="Traitor" />
|
||||
<img src="/images/helpModal/traitor.webp" alt="Traitor" title="Traitor" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-center">
|
||||
<div data-i18n="help_modal.icon_ally" class="text-gray-300">Handshake - Ally. This player is your ally.</div>
|
||||
<img src="/images/helpModal/ally.png" alt="Ally" title="Ally" />
|
||||
<img src="/images/helpModal/ally.webp" alt="Ally" title="Ally" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@ import "./components/Difficulties";
|
||||
import "./components/baseComponents/Modal";
|
||||
import { DifficultyDescription } from "./components/Difficulties";
|
||||
import "./components/Maps";
|
||||
import randomMap from "../../resources/images/RandomMap.png";
|
||||
import randomMap from "../../resources/images/RandomMap.webp";
|
||||
import { generateID } from "../core/Util";
|
||||
import { getServerConfigFromClient } from "../core/configuration/ConfigLoader";
|
||||
import { JoinLobbyEvent } from "./Main";
|
||||
|
||||
@@ -8,7 +8,7 @@ import "./components/baseComponents/Modal";
|
||||
import "./components/baseComponents/Button";
|
||||
import { DifficultyDescription } from "./components/Difficulties";
|
||||
import "./components/Maps";
|
||||
import randomMap from "../../resources/images/RandomMap.png";
|
||||
import randomMap from "../../resources/images/RandomMap.webp";
|
||||
import { GameInfo } from "../core/Schemas";
|
||||
import { JoinLobbyEvent } from "./Main";
|
||||
import { translateText } from "../client/Utils";
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
.bg-image {
|
||||
content: "";
|
||||
background-image: url("/images/EuropeBackground.svg");
|
||||
background-image: url("/images/EuropeBackground.webp");
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import world from "../../../resources/maps/WorldMapThumb.png";
|
||||
import oceania from "../../../resources/maps/OceaniaThumb.png";
|
||||
import europe from "../../../resources/maps/EuropeThumb.png";
|
||||
import mena from "../../../resources/maps/MenaThumb.png";
|
||||
import northAmerica from "../../../resources/maps/NorthAmericaThumb.png";
|
||||
import southAmerica from "../../../resources/maps/SouthAmericaThumb.png";
|
||||
import blackSea from "../../../resources/maps/BlackSeaThumb.png";
|
||||
import africa from "../../../resources/maps/AfricaThumb.png";
|
||||
import pangaea from "../../../resources/maps/PangaeaThumb.png";
|
||||
import asia from "../../../resources/maps/AsiaThumb.png";
|
||||
import mars from "../../../resources/maps/MarsThumb.png";
|
||||
import britannia from "../../../resources/maps/BritanniaThumb.png";
|
||||
import gatewayToTheAtlantic from "../../../resources/maps/GatewayToTheAtlanticThumb.png";
|
||||
import australia from "../../../resources/maps/AustraliaThumb.png";
|
||||
import iceland from "../../../resources/maps/IcelandThumb.png";
|
||||
import world from "../../../resources/maps/WorldMapThumb.webp";
|
||||
import oceania from "../../../resources/maps/OceaniaThumb.webp";
|
||||
import europe from "../../../resources/maps/EuropeThumb.webp";
|
||||
import mena from "../../../resources/maps/MenaThumb.webp";
|
||||
import northAmerica from "../../../resources/maps/NorthAmericaThumb.webp";
|
||||
import southAmerica from "../../../resources/maps/SouthAmericaThumb.webp";
|
||||
import blackSea from "../../../resources/maps/BlackSeaThumb.webp";
|
||||
import africa from "../../../resources/maps/AfricaThumb.webp";
|
||||
import pangaea from "../../../resources/maps/PangaeaThumb.webp";
|
||||
import asia from "../../../resources/maps/AsiaThumb.webp";
|
||||
import mars from "../../../resources/maps/MarsThumb.webp";
|
||||
import britannia from "../../../resources/maps/BritanniaThumb.webp";
|
||||
import gatewayToTheAtlantic from "../../../resources/maps/GatewayToTheAtlanticThumb.webp";
|
||||
import australia from "../../../resources/maps/AustraliaThumb.webp";
|
||||
import iceland from "../../../resources/maps/IcelandThumb.webp";
|
||||
|
||||
import { GameMapType } from "../../core/game/Game";
|
||||
|
||||
|
||||
Vendored
+5
@@ -7,6 +7,11 @@ declare module "*.jpg" {
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module "*.webp" {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module "*.jpeg" {
|
||||
const value: string;
|
||||
export default value;
|
||||
|
||||
@@ -338,15 +338,31 @@ function getNeighborCoords(x: number, y: number, map: Terrain[][]): Coord[] {
|
||||
return coords;
|
||||
}
|
||||
|
||||
async function createMapThumbnail(map: Terrain[][]): Promise<Bitmap> {
|
||||
async function createMapThumbnail(
|
||||
map: Terrain[][],
|
||||
quality: number = 0.5,
|
||||
): Promise<Bitmap> {
|
||||
console.log("creating thumbnail");
|
||||
const bitmap = new Bitmap(map.length, map[0].length);
|
||||
for (let x = 0; x < bitmap.width; x++) {
|
||||
for (let y = 0; y < bitmap.height; y++) {
|
||||
const rgba = getThumbnailColor(map[x][y]);
|
||||
|
||||
const srcWidth = map.length;
|
||||
const srcHeight = map[0].length;
|
||||
|
||||
const targetWidth = Math.max(1, Math.floor(srcWidth * quality));
|
||||
const targetHeight = Math.max(1, Math.floor(srcHeight * quality));
|
||||
|
||||
const bitmap = new Bitmap(targetWidth, targetHeight);
|
||||
|
||||
for (let x = 0; x < targetWidth; x++) {
|
||||
for (let y = 0; y < targetHeight; y++) {
|
||||
const srcX = Math.floor(x / quality);
|
||||
const srcY = Math.floor(y / quality);
|
||||
const terrain =
|
||||
map[Math.min(srcX, srcWidth - 1)][Math.min(srcY, srcHeight - 1)];
|
||||
const rgba = getThumbnailColor(terrain);
|
||||
bitmap.setPixelRGBA_i(x, y, rgba.r, rgba.g, rgba.b, rgba.a);
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@@ -357,9 +373,9 @@ function getThumbnailColor(t: Terrain): {
|
||||
a: number;
|
||||
} {
|
||||
if (t.type === TerrainType.Water) {
|
||||
//shoreline water
|
||||
// Shoreline water
|
||||
if (t.shoreline) return { r: 100, g: 143, b: 255, a: 0 };
|
||||
//all other water
|
||||
// All other water: adjust based on magnitude
|
||||
const waterAdjRGB: number = 11 - Math.min(t.magnitude / 2, 10) - 10;
|
||||
return {
|
||||
r: Math.max(70 + waterAdjRGB, 0),
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { encodePNGToStream } from "pureimage";
|
||||
import sharp from "sharp";
|
||||
import { generateMap } from "./TerrainMapGenerator.js";
|
||||
import path from "path";
|
||||
import fs from "fs/promises";
|
||||
import { WriteStream, createWriteStream } from "fs";
|
||||
|
||||
const maps = [
|
||||
"Africa",
|
||||
@@ -56,17 +55,21 @@ async function loadTerrainMaps() {
|
||||
process.cwd(),
|
||||
"resources",
|
||||
"maps",
|
||||
map + "Thumb.png",
|
||||
);
|
||||
const thumbOutStream: WriteStream = createWriteStream(
|
||||
thumbOutputPath,
|
||||
"binary",
|
||||
map + "Thumb.webp",
|
||||
);
|
||||
|
||||
await Promise.all([
|
||||
fs.writeFile(outputPath, mainMap),
|
||||
fs.writeFile(miniOutputPath, miniMap),
|
||||
encodePNGToStream(thumb, thumbOutStream),
|
||||
sharp(Buffer.from(thumb.data), {
|
||||
raw: {
|
||||
width: thumb.width,
|
||||
height: thumb.height,
|
||||
channels: 4,
|
||||
},
|
||||
})
|
||||
.webp({ quality: 45 })
|
||||
.toFile(thumbOutputPath),
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user