142 lines
5.7 KiB
Python
142 lines
5.7 KiB
Python
from pathlib import Path
|
|
from zipfile import ZIP_DEFLATED, ZipFile
|
|
|
|
from PIL import Image, ImageDraw
|
|
|
|
|
|
ROOT = Path("/Users/fengliang/Sites/esun3d")
|
|
OUTPUT = ROOT / "var/export/homepage-design-assets"
|
|
SOURCES = {
|
|
"application": Path(
|
|
"/var/folders/ms/dxgtmtg93ms5kz93_skmkqy40000gn/T/"
|
|
"codex-clipboard-ea205978-fb9f-4986-aa90-4233b9b227cc.png"
|
|
),
|
|
"innovative-materials": Path(
|
|
"/var/folders/ms/dxgtmtg93ms5kz93_skmkqy40000gn/T/"
|
|
"codex-clipboard-aa1bfd89-7e64-4d36-b8d2-5f122a622473.png"
|
|
),
|
|
"awards-reviews": Path(
|
|
"/var/folders/ms/dxgtmtg93ms5kz93_skmkqy40000gn/T/"
|
|
"codex-clipboard-90a1c3dc-9def-42e2-bd7b-cc7a09597eb4.png"
|
|
),
|
|
"resources-downloads": Path(
|
|
"/var/folders/ms/dxgtmtg93ms5kz93_skmkqy40000gn/T/"
|
|
"codex-clipboard-7cb9a493-5b4f-4825-a10f-973958b51144.png"
|
|
),
|
|
}
|
|
|
|
|
|
def crop(source: Image.Image, box: tuple[int, int, int, int], target: Path) -> None:
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
source.crop(box).save(target, optimize=True)
|
|
|
|
|
|
def export() -> None:
|
|
OUTPUT.mkdir(parents=True, exist_ok=True)
|
|
for folder in SOURCES:
|
|
(OUTPUT / folder).mkdir(parents=True, exist_ok=True)
|
|
|
|
application = Image.open(SOURCES["application"]).convert("RGB")
|
|
application.save(OUTPUT / "application/section-reference.png", optimize=True)
|
|
application_cards = [
|
|
(84, 364, 625, 1421),
|
|
(651, 364, 1194, 1421),
|
|
(1217, 364, 1761, 1421),
|
|
(1782, 364, 2325, 1421),
|
|
(2347, 364, 2890, 1421),
|
|
]
|
|
application_icons = [
|
|
(280, 1110, 420, 1250),
|
|
(848, 1110, 988, 1250),
|
|
(1415, 1110, 1555, 1250),
|
|
(1980, 1110, 2120, 1250),
|
|
(2546, 1110, 2686, 1250),
|
|
]
|
|
for index, box in enumerate(application_cards, 1):
|
|
crop(application, box, OUTPUT / f"application/cropped-assets/card-{index}-composite.png")
|
|
for index, box in enumerate(application_icons, 1):
|
|
crop(application, box, OUTPUT / f"application/cropped-assets/icon-{index}-composite.png")
|
|
|
|
innovative = Image.open(SOURCES["innovative-materials"]).convert("RGB")
|
|
innovative.save(OUTPUT / "innovative-materials/section-background-reference.png", optimize=True)
|
|
innovative_photos = [
|
|
(276, 490, 919, 1139),
|
|
(992, 493, 1640, 1139),
|
|
(1708, 490, 2358, 1139),
|
|
(2428, 490, 3078, 1139),
|
|
]
|
|
for index, box in enumerate(innovative_photos, 1):
|
|
crop(innovative, box, OUTPUT / f"innovative-materials/cropped-assets/photo-{index}.png")
|
|
|
|
awards = Image.open(SOURCES["awards-reviews"]).convert("RGB")
|
|
awards.save(OUTPUT / "awards-reviews/section-reference.png", optimize=True)
|
|
crop(awards, (0, 400, 3356, 1000), OUTPUT / "awards-reviews/cropped-assets/background-banner-composite.png")
|
|
crop(awards, (933, 275, 2421, 1121), OUTPUT / "awards-reviews/cropped-assets/feature-card-composite.png")
|
|
crop(awards, (933, 275, 1875, 1121), OUTPUT / "awards-reviews/cropped-assets/feature-image-left.png")
|
|
crop(awards, (1875, 515, 2585, 1000), OUTPUT / "awards-reviews/cropped-assets/review-copy-card-composite.png")
|
|
|
|
resources = Image.open(SOURCES["resources-downloads"]).convert("RGB")
|
|
resources.save(OUTPUT / "resources-downloads/section-reference.png", optimize=True)
|
|
resource_cards = [
|
|
(274, 385, 934, 860),
|
|
(987, 385, 1647, 860),
|
|
(1701, 385, 2360, 860),
|
|
(2415, 385, 3075, 860),
|
|
]
|
|
resource_images = [
|
|
(420, 450, 792, 690),
|
|
(1130, 445, 1505, 690),
|
|
(1844, 445, 2217, 690),
|
|
(2558, 445, 2933, 690),
|
|
]
|
|
for index, box in enumerate(resource_cards, 1):
|
|
crop(resources, box, OUTPUT / f"resources-downloads/cropped-assets/card-{index}-composite.png")
|
|
for index, box in enumerate(resource_images, 1):
|
|
crop(resources, box, OUTPUT / f"resources-downloads/cropped-assets/illustration-{index}-composite.png")
|
|
|
|
previews = []
|
|
for file in sorted(OUTPUT.glob("**/cropped-assets/*.png")):
|
|
image = Image.open(file).convert("RGB")
|
|
image.thumbnail((240, 240))
|
|
previews.append((file, image.copy()))
|
|
|
|
columns = 5
|
|
cell_width = 270
|
|
cell_height = 300
|
|
rows = (len(previews) + columns - 1) // columns
|
|
sheet = Image.new("RGB", (columns * cell_width, rows * cell_height), "white")
|
|
draw = ImageDraw.Draw(sheet)
|
|
for index, (file, image) in enumerate(previews):
|
|
x = (index % columns) * cell_width
|
|
y = (index // columns) * cell_height
|
|
sheet.paste(image, (x + (cell_width - image.width) // 2, y + 8))
|
|
draw.text((x + 8, y + 255), file.stem[:34], fill="black")
|
|
sheet.save(OUTPUT / "contact-sheet.jpg", quality=90, optimize=True)
|
|
|
|
readme = """Homepage design screenshot assets
|
|
|
|
Folders:
|
|
- application: five card composites and five icon composites
|
|
- innovative-materials: four relatively clean photo crops
|
|
- awards-reviews: full section, background banner, feature and review composites
|
|
- resources-downloads: four card composites and four illustration composites
|
|
|
|
Important:
|
|
- These files were cropped from supplied design screenshots.
|
|
- Files ending in "-composite" include text, overlays, shadows, or card backgrounds
|
|
that were already flattened into the screenshot.
|
|
- They are useful for implementation references and temporary assets, but original
|
|
design source files are required for fully clean production assets.
|
|
"""
|
|
(OUTPUT / "README.txt").write_text(readme, encoding="utf-8")
|
|
|
|
archive = OUTPUT.parent / "homepage-design-assets.zip"
|
|
with ZipFile(archive, "w", ZIP_DEFLATED) as zip_file:
|
|
for file in sorted(OUTPUT.rglob("*")):
|
|
if file.is_file():
|
|
zip_file.write(file, file.relative_to(OUTPUT.parent))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
export()
|