Compare commits

...
2 Commits
Author SHA1 Message Date
yyc12345 42a2b08abf feat: support image-png/bmp/gif 2026-09-09 12:09:33 +08:00
yyc12345 61e003c741 fix: fix fatal source link issue 2026-09-08 22:29:50 +08:00
11 changed files with 308 additions and 99 deletions
+20
View File
@@ -13,3 +13,23 @@ I, Jonathan Zander, CC BY-SA 3.0 <http://creativecommons.org/licenses/by-sa/3.0/
https://commons.wikimedia.org/wiki/File:Daisy_(Argyranthemum_frutescens).jpg
Fir0002, CC BY-SA 3.0 <http://creativecommons.org/licenses/by-sa/3.0/>, via Wikimedia Commons
https://commons.wikimedia.org/wiki/File:Nycticorax_nycticorax12.jpg
This file is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported, 2.5 Generic, 2.0 Generic and 1.0 Generic license.
Calibas
https://commons.wikimedia.org/wiki/File:Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg
This work is in the public domain in its country of origin and other countries and areas where the copyright term is the author's life plus 100 years or fewer.
Vincent van Gogh
Google Arts & Culture
https://commons.wikimedia.org/wiki/File:Tulipa_suaveolens_floriade_to_Canberra.jpg
This file is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license.
John O'Neill
https://commons.wikimedia.org/wiki/File:International_hot_air_balloon_festival_in_leon_guanajuato_mexico_2012.jpg
This file is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license.
Tomascastelazo
https://commons.wikimedia.org/wiki/File:Hot-air_balloon_in_Tambov_-_02.jpg
This file is licensed under the Creative Commons Attribution-Share Alike 4.0 International license.
Alexander Novikov
+19 -1
View File
@@ -1,5 +1,23 @@
[[licenses]]
file = 'Niinsaare_järv.jpg'
license = "CC-BY-SA-3.0"
authors = ["Ivar Leidus", "Wikimedia Commons"]
authors = ["Ivar Leidus"]
source = 'https://commons.wikimedia.org/wiki/File:Niinsaare_j%C3%A4rv.jpg'
[[licenses]]
file = 'Tulipa_suaveolens_floriade_to_Canberra.jpg'
license = "CC-BY-SA-3.0"
authors = ["John O'Neill"]
source = 'https://commons.wikimedia.org/wiki/File:Tulipa_suaveolens_floriade_to_Canberra.jpg'
[[licenses]]
file = 'Hot-air_balloon_in_Tambov_-_02.jpg'
license = "CC-BY-SA-4.0"
authors = ["Alexander Novikov"]
source = 'https://commons.wikimedia.org/wiki/File:Hot-air_balloon_in_Tambov_-_02.jpg'
[[licenses]]
file = 'Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg'
license = "CC0-1.0" # Public Domain actually.
authors = ["Vincent van Gogh", "Google Arts & Culture"]
source = 'https://commons.wikimedia.org/wiki/File:Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg'
Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

@@ -78,7 +78,7 @@ class Rectangle:
width: int, height: int, top: int, right: int, bottom: int, left: int
) -> "Rectangle":
"""
TODO
Create the rectangle with the size of this region's parent, and the margin between this region and its parent.
:param width: The width of parent.
:param height: The height of parent.
@@ -94,7 +94,7 @@ class Rectangle:
pos: Point, top: int, right: int, bottom: int, left: int
) -> "Rectangle":
"""
TODO
Create the rectangle with the central point in this region's parent, and the padding between this point and region's border.
:param x: The X factor of reference point.
:param y: The Y factor of reference point.
@@ -103,7 +103,9 @@ class Rectangle:
:param bottom: The distance from reference point to this rectangle's bottom border.
:param left: The distance from reference point to this rectangle's left border.
"""
return Rectangle(Point(pos.x - left, pos.y - top), Point(pos.x + right, pos.y + bottom))
return Rectangle(
Point(pos.x - left, pos.y - top), Point(pos.x + right, pos.y + bottom)
)
@property
def width(self) -> int:
@@ -23,13 +23,13 @@ class FdArtSource(Source):
sink_hint = fd_sink.push_hint()
LOGGER.info(
'Duplicating FreeDesktop artifact from kind "%s" name "%s" to kind "%s" name "%s".',
sink_hint.kind,
sink_hint.name,
self.__kind,
self.__name,
sink_hint.kind,
sink_hint.name,
)
for hw in FD_THUMBNAIL_HWS:
artio.link_artifact(
env.fd_output_artifact(hw, sink_hint.kind, sink_hint.name),
env.fd_output_artifact(hw, self.__kind, self.__name),
env.fd_output_artifact(hw, sink_hint.kind, sink_hint.name),
)
@@ -23,12 +23,12 @@ class MacArtSource(Source):
sink_hint = mac_sink.push_hint()
LOGGER.info(
'Duplicating macOS-only artifact from kind "%s" name "%s" to kind "%s" name "%s".',
sink_hint.kind,
sink_hint.name,
self.__kind,
self.__name,
sink_hint.kind,
sink_hint.name,
)
artio.link_artifact(
env.mac_output_artifact(sink_hint.kind, sink_hint.name),
env.mac_output_artifact(self.__kind, self.__name),
env.mac_output_artifact(sink_hint.kind, sink_hint.name),
)
@@ -23,12 +23,12 @@ class WinArtSource(Source):
sink_hint = win_sink.push_hint()
LOGGER.info(
'Duplicating Windows-only artifact from kind "%s" name "%s" to kind "%s" name "%s".',
sink_hint.kind,
sink_hint.name,
self.__kind,
self.__name,
sink_hint.kind,
sink_hint.name,
)
artio.link_artifact(
env.win_output_artifact(sink_hint.kind, sink_hint.name),
env.win_output_artifact(self.__kind, self.__name),
env.win_output_artifact(sink_hint.kind, sink_hint.name),
)
@@ -1,75 +1,8 @@
import PIL.Image
import PIL.ImageEnhance
from ..types import AuroraContext, AuroraEnvironment
from ..assemblicon.highlevel.utils import FdContext, WinCategory, MacCategory
from ..assemblicon.highlevel.source import SvgSource, BitmapSource, TempArtSource
from ..assemblicon.highlevel.source import SvgSource, TempArtSource
from ..assemblicon.highlevel.sink import TempArtSink, FdArtSink, WinArtSink, MacArtSink
from ..assemblicon.geometry import Rectangle, Point
from ..assemblicon.lowlevel.artproc import (
aspect_ratio_scale_and_crop,
VerticalAnchor,
HorizontalAnchor,
)
def register(ctx: AuroraContext) -> None:
ctx.register(
"nostd/mimetype/image-jpeg",
(
TempArtSource("component", "image-base.png"),
BitmapSource("bitmap", "Niinsaare_järv.jpg"),
TempArtSink("image-jpeg.png"),
FdArtSink(FdContext.MimeTypes, "image-jpeg"),
WinArtSink(WinCategory.Extension, "jpg"),
MacArtSink(MacCategory.Extension, "jpg"),
),
build_image_jpeg_icon,
)
IMAGE_INNER_RECT = Rectangle(Point(20 * 4, 52 * 4), Point(236 * 4, 204 * 4))
def build_image_jpeg_icon(
env: AuroraEnvironment,
base_src: TempArtSource,
bitmap_src: BitmapSource,
temp_sink: TempArtSink,
fd_sink: FdArtSink,
win_sink: WinArtSink,
mac_sink: MacArtSink,
) -> None:
jpg_image = base_src.pull(env)
jpg_image_inner = bitmap_src.pull(env)
with jpg_image_inner:
# crop the area which is interested by ourselves
interest_area = Rectangle.from_pos_size_rect(Point(2700, 0), 5016, 3888)
crop_jpg_image_inner = jpg_image_inner.crop(interest_area.to_tuple())
# do a flip
flip_jpg_image_inner = crop_jpg_image_inner.transpose(
PIL.Image.Transpose.FLIP_LEFT_RIGHT
)
# enhance its saturation
enhancer = PIL.ImageEnhance.Color(flip_jpg_image_inner)
saturated_jpg_image_inner = enhancer.enhance(1.4)
# fit to inner rect
bestfit_jpg_image_inner = aspect_ratio_scale_and_crop(
saturated_jpg_image_inner,
IMAGE_INNER_RECT.width,
IMAGE_INNER_RECT.height,
PIL.Image.Resampling.NEAREST,
HorizontalAnchor.Center,
VerticalAnchor.Center,
)
# paste into inner rect
jpg_image.paste(bestfit_jpg_image_inner, IMAGE_INNER_RECT.to_tuple())
# build artifacts
# save as temporary for future use
temp_sink.push(env, jpg_image)
# save for FD
fd_sink.push(env, jpg_image)
# save for windows and mac
win_sink.push(env, jpg_image)
mac_sink.push(env, jpg_image)
pass
@@ -18,14 +18,6 @@ def register(ctx: AuroraContext) -> None:
),
build_generic_background,
)
ctx.register(
"component/image-base",
(
SvgSource("component", "image-base.svg"),
TempArtSink("component", "image-base.png"),
),
build_image_base_icon,
)
ctx.register(
"component/triangles",
(
@@ -67,12 +59,6 @@ def build_generic_background(
src.pull_to_temp(env, sink)
def build_image_base_icon(
env: AuroraEnvironment, src: SvgSource, sink: TempArtSink
) -> None:
src.pull_to_temp(env, sink)
def build_triangle_icons(
env: AuroraEnvironment,
tri_src: SvgSource,
@@ -1,10 +1,32 @@
import PIL.Image
import PIL.ImageEnhance
from ..types import AuroraContext, AuroraEnvironment
from ..assemblicon.highlevel.utils import FdContext
from ..assemblicon.highlevel.source import FdArtSource
from ..assemblicon.highlevel.sink import FdArtSink
from ..assemblicon.highlevel.utils import FdContext, WinCategory, MacCategory
from ..assemblicon.highlevel.source import (
SvgSource,
BitmapSource,
TempArtSource,
FdArtSource,
)
from ..assemblicon.highlevel.sink import TempArtSink, FdArtSink, WinArtSink, MacArtSink
from ..assemblicon.geometry import Rectangle, Point
from ..assemblicon.lowlevel.artio import new_artifact
from ..assemblicon.lowlevel.artproc import (
aspect_ratio_scale_and_crop,
VerticalAnchor,
HorizontalAnchor,
)
def register(ctx: AuroraContext) -> None:
ctx.register(
"component/image-base",
(
SvgSource("component", "image-base.svg"),
TempArtSink("component", "image-base.png"),
),
build_image_base_icon,
)
ctx.register(
"std/mimetype/image-x-generic",
(
@@ -13,6 +35,59 @@ def register(ctx: AuroraContext) -> None:
),
build_image_x_generic,
)
ctx.register(
"std/mimetype/image-jpeg",
(
TempArtSource("component", "image-base.png"),
BitmapSource("bitmap", "Niinsaare_järv.jpg"),
TempArtSink("image-jpeg.png"),
FdArtSink(FdContext.MimeTypes, "image-jpeg"),
WinArtSink(WinCategory.Extension, "jpg"),
MacArtSink(MacCategory.Extension, "jpg"),
),
build_image_jpeg_icon,
)
ctx.register(
"std/mimetype/image-png",
(
TempArtSource("component", "image-base.png"),
BitmapSource("bitmap", "Tulipa_suaveolens_floriade_to_Canberra.jpg"),
BitmapSource("bitmap", "Tulipa_suaveolens_floriade_to_Canberra-mask.png"),
SvgSource("image-png-checkerboard.svg"),
FdArtSink(FdContext.MimeTypes, "image-png"),
WinArtSink(WinCategory.Extension, "png"),
MacArtSink(MacCategory.Extension, "png"),
),
build_image_png_icon,
)
ctx.register(
"std/mimetype/image-bmp",
(
TempArtSource("component", "image-base.png"),
BitmapSource("bitmap", "Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg"),
FdArtSink(FdContext.MimeTypes, "image-bmp"),
WinArtSink(WinCategory.Extension, "bmp"),
MacArtSink(MacCategory.Extension, "bmp"),
),
build_image_bmp_icon,
)
ctx.register(
"std/mimetype/image-gif",
(
TempArtSource("component", "image-base.png"),
BitmapSource("bitmap", "Hot-air_balloon_in_Tambov_-_02.jpg"),
FdArtSink(FdContext.MimeTypes, "image-gif"),
WinArtSink(WinCategory.Extension, "gif"),
MacArtSink(MacCategory.Extension, "gif"),
),
build_image_gif_icon,
)
def build_image_base_icon(
env: AuroraEnvironment, src: SvgSource, sink: TempArtSink
) -> None:
src.pull_to_temp(env, sink)
def build_image_x_generic(
@@ -20,3 +95,176 @@ def build_image_x_generic(
) -> None:
# use image/jpeg as the default image icon
src.link_to(env, sink)
IMAGE_INNER_RECT = Rectangle(Point(20 * 4, 52 * 4), Point(236 * 4, 204 * 4))
"""The valid region of image-base for putting inner image."""
def build_image_jpeg_icon(
env: AuroraEnvironment,
base_src: TempArtSource,
bitmap_src: BitmapSource,
temp_sink: TempArtSink,
fd_sink: FdArtSink,
win_sink: WinArtSink,
mac_sink: MacArtSink,
) -> None:
jpg_image = base_src.pull(env)
jpg_image_inner = bitmap_src.pull(env)
with jpg_image_inner:
# crop the area which is interested by ourselves
interest_area = Rectangle.from_pos_size_rect(Point(2700, 0), 5016, 3888)
crop_jpg_image_inner = jpg_image_inner.crop(interest_area.to_tuple())
# do a flip
flip_jpg_image_inner = crop_jpg_image_inner.transpose(
PIL.Image.Transpose.FLIP_LEFT_RIGHT
)
# enhance its saturation
enhancer = PIL.ImageEnhance.Color(flip_jpg_image_inner)
saturated_jpg_image_inner = enhancer.enhance(1.4)
# fit to inner rect
bestfit_jpg_image_inner = aspect_ratio_scale_and_crop(
saturated_jpg_image_inner,
IMAGE_INNER_RECT.width,
IMAGE_INNER_RECT.height,
PIL.Image.Resampling.NEAREST,
HorizontalAnchor.Center,
VerticalAnchor.Center,
)
# paste into inner rect
jpg_image.paste(bestfit_jpg_image_inner, IMAGE_INNER_RECT.to_tuple())
# build artifacts
# save as temporary for future use
temp_sink.push(env, jpg_image)
# save for FD
fd_sink.push(env, jpg_image)
# save for windows and mac
win_sink.push(env, jpg_image)
mac_sink.push(env, jpg_image)
def build_image_png_icon(
env: AuroraEnvironment,
base_src: TempArtSource,
bitmap_src: BitmapSource,
bitmap_mask_src: BitmapSource,
checkerboard_src: SvgSource,
fd_sink: FdArtSink,
win_sink: WinArtSink,
mac_sink: MacArtSink,
) -> None:
png_image = base_src.pull(env)
bitmap = bitmap_src.pull(env)
bitmap_mask = bitmap_mask_src.pull(env)
checkerboard = checkerboard_src.pull(env)
with bitmap, bitmap_mask, checkerboard:
# mask bitmap first
# force mask as grayscale format to apply black-white mask instead of alpha channel mask
bitmap_masked = new_artifact(bitmap.size)
bitmap_masked.paste(bitmap, (0, 0), bitmap_mask.convert("L"))
# we use the whole image as the inner,
# so we directly fit it to inner.
bestfit_bitmap = aspect_ratio_scale_and_crop(
bitmap_masked,
IMAGE_INNER_RECT.width,
IMAGE_INNER_RECT.height,
PIL.Image.Resampling.NEAREST,
HorizontalAnchor.Center,
VerticalAnchor.Top,
)
# TODO: When bestfit this checkerboard, the border of this checkerboard aer lost.
# We may need resolve this in future but currently it is so subtle to notice.
bestfit_checkerboard = aspect_ratio_scale_and_crop(
checkerboard,
IMAGE_INNER_RECT.width,
IMAGE_INNER_RECT.height,
PIL.Image.Resampling.NEAREST,
HorizontalAnchor.Center,
VerticalAnchor.Center,
)
# composite them together
png_image.alpha_composite(
bestfit_checkerboard, IMAGE_INNER_RECT.pos1.to_tuple()
)
png_image.alpha_composite(bestfit_bitmap, IMAGE_INNER_RECT.pos1.to_tuple())
# build artifacts
# save for FD
fd_sink.push(env, png_image)
# save for windows and mac
win_sink.push(env, png_image)
mac_sink.push(env, png_image)
def build_image_bmp_icon(
env: AuroraEnvironment,
base_src: TempArtSource,
bitmap_src: BitmapSource,
fd_sink: FdArtSink,
win_sink: WinArtSink,
mac_sink: MacArtSink,
) -> None:
bmp_image = base_src.pull(env)
bmp_image_inner = bitmap_src.pull(env)
with bmp_image_inner:
# we use the whole image as the inner,
# so we directly fit it to inner.
bestfit_inner = aspect_ratio_scale_and_crop(
bmp_image_inner,
IMAGE_INNER_RECT.width,
IMAGE_INNER_RECT.height,
PIL.Image.Resampling.NEAREST,
HorizontalAnchor.Center,
VerticalAnchor.Center,
)
# paste into inner rect
bmp_image.paste(bestfit_inner, IMAGE_INNER_RECT.to_tuple())
# build artifacts
# save for FD
fd_sink.push(env, bmp_image)
# save for windows and mac
win_sink.push(env, bmp_image)
mac_sink.push(env, bmp_image)
def build_image_gif_icon(
env: AuroraEnvironment,
base_src: TempArtSource,
bitmap_src: BitmapSource,
fd_sink: FdArtSink,
win_sink: WinArtSink,
mac_sink: MacArtSink,
) -> None:
gif_image = base_src.pull(env)
gif_image_inner = bitmap_src.pull(env)
with gif_image_inner:
# we use the whole image as the inner,
# so we directly fit it to inner.
bestfit_inner = aspect_ratio_scale_and_crop(
gif_image_inner,
IMAGE_INNER_RECT.width,
IMAGE_INNER_RECT.height,
PIL.Image.Resampling.NEAREST,
HorizontalAnchor.Center,
VerticalAnchor.Center,
)
# paste into inner rect
gif_image.paste(bestfit_inner, IMAGE_INNER_RECT.to_tuple())
# build artifacts
# save for FD
fd_sink.push(env, gif_image)
# save for windows and mac
win_sink.push(env, gif_image)
mac_sink.push(env, gif_image)
@@ -64,6 +64,8 @@ def build_dialog_warning_icon(
def build_dialog_error_icon(
env: AuroraEnvironment, src: SvgSource, temp_sink: TempArtSink, fd_sink: FdArtSink
) -> None:
# TODO: update this icon from rectangle to circle
# save dialog icon with FreeDesktop icon and temp icon for reuse.
src.pull_to_temp(env, temp_sink)
with temp_sink.repull(env) as art: