Store assets: landscape tablet screenshots (iPad, Android 7/10-inch)
Captured from the app's real sidebar shell at 1024x768; adds landscape compositions to compose.py and the README upload table. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
11b3d535a9
commit
5837464581
@@ -31,7 +31,7 @@ STORIES = [
|
||||
eyebrow='MULTIPLE ACCOUNTS',
|
||||
lines=('Every cloud,', 'one tap apart.'),
|
||||
sub='Personal, work and family servers together.'),
|
||||
dict(key='locks', theme='dark', back='lock', front='security', card_at=.66,
|
||||
dict(key='locks', theme='dark', back='lock', front='security', card_at=.66, card_at_l=.66,
|
||||
eyebrow='LOCKS',
|
||||
lines=('Locks where', 'you want them.'),
|
||||
sub='Protect opening Noo, switching accounts and hidden files with your device PIN or biometrics.'),
|
||||
@@ -56,6 +56,10 @@ TARGETS = [
|
||||
('android/tablet-10in', 'atablet', (1600, 2560), 'tablet'),
|
||||
('ios/iphone', 'iphone', (1290, 2796), 'phone'),
|
||||
('ios/ipad', 'ipad', (2064, 2752), 'tablet'),
|
||||
# Landscape tablets show the app's real sidebar layout.
|
||||
('android/tablet-7in-landscape', 'atabletl', (1920, 1200), 'landscape'),
|
||||
('android/tablet-10in-landscape', 'atabletl', (2560, 1600), 'landscape'),
|
||||
('ios/ipad-landscape', 'ipadl', (2752, 2064), 'landscape'),
|
||||
]
|
||||
|
||||
|
||||
@@ -127,7 +131,51 @@ def paste_panel(canvas, source, box, radius, t, bleed=False):
|
||||
return x, y, sw, sh
|
||||
|
||||
|
||||
def landscape_canvas(story, size, device):
|
||||
"""Text column on the left, the real tablet UI on the right."""
|
||||
t = THEMES[story['theme']]
|
||||
w, h = size
|
||||
im = background(size, t)
|
||||
d = ImageDraw.Draw(im)
|
||||
margin = round(h * .07)
|
||||
colw = round(w * .30)
|
||||
y = round(h * .27)
|
||||
spaced(d, (margin, y), story['eyebrow'], font(round(h * .022), 'Bold', 'InstrumentSans'),
|
||||
t['accent_text'], h * .004)
|
||||
y += round(h * .06)
|
||||
head = round(h * .068)
|
||||
for index, line in enumerate(story['lines']):
|
||||
fnt, _ = fit(d, line, font, head, colw)
|
||||
d.text((margin, y), line, font=fnt, fill=t['accent_text'] if index else t['fg'])
|
||||
y += round(head * 1.12)
|
||||
y += round(head * .2)
|
||||
sub_size = round(h * .030)
|
||||
fnt = body_font(sub_size, 'Regular')
|
||||
for line in textwrap.wrap(story['sub'], max(16, int(colw / (sub_size * .52)))):
|
||||
d.text((margin, y), line, font=fnt, fill=t['fg2'])
|
||||
y += round(sub_size * 1.4)
|
||||
x0 = margin + colw + round(w * .035)
|
||||
src = lambda name: OUT / f'source/{device}/{name}.png'
|
||||
back = Image.open(src(story['back']))
|
||||
aw, ah = w - x0 - margin, h - margin * 2
|
||||
factor = min(aw / back.width, ah / back.height)
|
||||
# Centered vertically; a layered card hangs below the panel's bottom edge.
|
||||
area = (x0, round((h - back.height * factor) / 2) - (round(h * .03) if story['front'] else 0), aw, ah)
|
||||
radius = round(h * .03)
|
||||
bx, by, bw, bh = paste_panel(im, src(story['back']), area, radius, t)
|
||||
if story['front']:
|
||||
card = content_crop(src(story['front']))
|
||||
scale = bw / Image.open(src(story['back'])).width
|
||||
cw, ch = round(card.width * scale), round(card.height * scale)
|
||||
cx = bx + round(bw * .40)
|
||||
cy = by + round(bh * story.get('card_at_l', story['card_at']))
|
||||
paste_panel(im, card, (cx, cy, cw, ch), round(radius * .6), t)
|
||||
return im
|
||||
|
||||
|
||||
def story_canvas(story, size, kind, device):
|
||||
if kind == 'landscape':
|
||||
return landscape_canvas(story, size, device)
|
||||
t = THEMES[story['theme']]
|
||||
w, h = size
|
||||
im = background(size, t)
|
||||
@@ -218,11 +266,12 @@ for asset in manifest:
|
||||
(OUT / 'manifest.json').write_text(json.dumps(manifest, indent=2) + '\n')
|
||||
|
||||
# Review materials (not for upload): contact sheet and a gallery page.
|
||||
contact = Image.new('RGB', (1920, 1500), '#1c1b18')
|
||||
contact = Image.new('RGB', (1920, 2160), '#1c1b18')
|
||||
cd = ImageDraw.Draw(contact)
|
||||
cd.text((32, 20), 'Noo / store listing artwork', font=font(28), fill='#F3EFE6')
|
||||
rows = [('ANDROID PHONE', 'android/phone'), ('ANDROID 10" TABLET', 'android/tablet-10in'),
|
||||
('IPHONE', 'ios/iphone'), ('IPAD', 'ios/ipad')]
|
||||
('IPHONE', 'ios/iphone'), ('IPAD', 'ios/ipad'),
|
||||
('ANDROID 10" LANDSCAPE', 'android/tablet-10in-landscape'), ('IPAD LANDSCAPE', 'ios/ipad-landscape')]
|
||||
for row, (label, folder) in enumerate(rows):
|
||||
cd.text((32, 75 + row * 360), label, font=font(15, 'Bold', 'InstrumentSans'), fill='#CBA5FD')
|
||||
for col, path in enumerate(sorted((OUT / folder).glob('*.png'))):
|
||||
|
||||
Reference in New Issue
Block a user