2022.22.01.1
1
.gitignore
vendored
|
@ -1,5 +1,4 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
.idea
|
||||||
*.pyc
|
*.pyc
|
||||||
./MockupModule/generated/*
|
|
||||||
__pycache__
|
__pycache__
|
|
@ -4,7 +4,7 @@ from importlib import import_module
|
||||||
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from PIL import Image, ImageChops
|
from PIL import Image
|
||||||
|
|
||||||
from MockupModule import templates
|
from MockupModule import templates
|
||||||
from MockupModule.utils import random_string
|
from MockupModule.utils import random_string
|
||||||
|
@ -24,9 +24,24 @@ class MockupEngineer:
|
||||||
import_module(name='MockupModule.templates.' + template,
|
import_module(name='MockupModule.templates.' + template,
|
||||||
package='MockupModule.templates.' + template + '.Device'), 'Device')())
|
package='MockupModule.templates.' + template + '.Device'), 'Device')())
|
||||||
|
|
||||||
def screenshot_resize(self, screenshot: str, width: int, height: int) -> str:
|
def __create_examples__(self, example_path: str) -> None:
|
||||||
name = '{}/screenshot{}.png'.format(generated_path, random_string(16))
|
for template in self.templates:
|
||||||
img = Image.open(screenshot).resize((width, height), Image.ANTIALIAS)
|
if os.path.isfile(template.example_path):
|
||||||
|
os.remove(template.example_path)
|
||||||
|
|
||||||
|
mockup_path = self.generate(template, example_path, orientation='portrait')
|
||||||
|
mockup_img = Image.open(mockup_path)
|
||||||
|
background_img = Image.new('RGBA', mockup_img.size, (255, 255, 255, 255))
|
||||||
|
background_img.paste(mockup_img, (0, 0), mockup_img)
|
||||||
|
|
||||||
|
background_img.save(template.example_path)
|
||||||
|
|
||||||
|
os.remove(mockup_path)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resize(image: str, width: int, height: int) -> str:
|
||||||
|
name = '{}/image{}.png'.format(generated_path, random_string(16))
|
||||||
|
img = Image.open(image).resize((width, height), Image.ANTIALIAS)
|
||||||
img.save(name)
|
img.save(name)
|
||||||
|
|
||||||
return name
|
return name
|
||||||
|
@ -40,9 +55,11 @@ class MockupEngineer:
|
||||||
dicted[template.type] = [template]
|
dicted[template.type] = [template]
|
||||||
return dicted
|
return dicted
|
||||||
|
|
||||||
def generate(self, template: templates.Template, screenshot: str, color: str = None, orientation: str = None):
|
def generate(self, template: templates.Template,
|
||||||
|
screenshot_path: str, color: str = None,
|
||||||
|
orientation: str = None) -> str:
|
||||||
if not orientation:
|
if not orientation:
|
||||||
img = Image.open(screenshot)
|
img = Image.open(screenshot_path)
|
||||||
width, height = img.size
|
width, height = img.size
|
||||||
orientation = 'portrait' if height > width or height == width else 'landscape'
|
orientation = 'portrait' if height > width or height == width else 'landscape'
|
||||||
|
|
||||||
|
@ -59,7 +76,7 @@ class MockupEngineer:
|
||||||
screen_y = template.__landscape_y__
|
screen_y = template.__landscape_y__
|
||||||
screen_mask = template.__landscape_mask__ if template.__use_mask__ else None
|
screen_mask = template.__landscape_mask__ if template.__use_mask__ else None
|
||||||
|
|
||||||
screenshot = self.screenshot_resize(screenshot, screen_width, screen_height)
|
screenshot = self.resize(screenshot_path, screen_width, screen_height)
|
||||||
|
|
||||||
for template_color in template.colors:
|
for template_color in template.colors:
|
||||||
if template_color.color == color:
|
if template_color.color == color:
|
||||||
|
@ -70,7 +87,7 @@ class MockupEngineer:
|
||||||
template_path = template.colors[-1].portrait_path \
|
template_path = template.colors[-1].portrait_path \
|
||||||
if orientation == 'portrait' else template.colors[-1].landscape_path
|
if orientation == 'portrait' else template.colors[-1].landscape_path
|
||||||
|
|
||||||
name = '{}/mockup{}.png'.format(generated_path, random_string(16))
|
mockup_path = '{}/mockup{}.png'.format(generated_path, random_string(16))
|
||||||
|
|
||||||
template_img = Image.open(template_path)
|
template_img = Image.open(template_path)
|
||||||
mask_img = Image.new('RGBA', template_img.size, (0, 0, 0, 0))
|
mask_img = Image.new('RGBA', template_img.size, (0, 0, 0, 0))
|
||||||
|
@ -81,6 +98,6 @@ class MockupEngineer:
|
||||||
if screen_mask:
|
if screen_mask:
|
||||||
screen_mask = Image.open(screen_mask).convert('L')
|
screen_mask = Image.open(screen_mask).convert('L')
|
||||||
mask_img.putalpha(screen_mask)
|
mask_img.putalpha(screen_mask)
|
||||||
mask_img.save(name)
|
mask_img.save(mockup_path)
|
||||||
|
|
||||||
return name
|
return mockup_path
|
||||||
|
|
|
@ -6,6 +6,8 @@ from MockupModule import MockupEngineer
|
||||||
def main():
|
def main():
|
||||||
mockup = MockupEngineer()
|
mockup = MockupEngineer()
|
||||||
|
|
||||||
|
mockup.__create_examples__('/Users/ulbwa/Documents/MockupEngineer/MockupModule/templates/example.jpg')
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for template in mockup.templates:
|
for template in mockup.templates:
|
||||||
print('[{}] {} {} [{}] ({})'.format(i, template.manufacturer, template.name, template.resolution, template.year))
|
print('[{}] {} {} [{}] ({})'.format(i, template.manufacturer, template.name, template.resolution, template.year))
|
||||||
|
|
BIN
MockupModule/templates/example.jpg
Normal file
After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 538 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 540 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 548 KiB |
28
MockupModule/templates/ipadmini5/__init__.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from MockupModule.templates import Template
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Device(Template):
|
||||||
|
def __device_init__(self):
|
||||||
|
self.manufacturer = 'Apple'
|
||||||
|
self.name = 'iPad Mini 5'
|
||||||
|
self.type = 'tablet'
|
||||||
|
self.year = 2021
|
||||||
|
self.resolution = '{width} x {height}'.format(width=2048, height=1536)
|
||||||
|
|
||||||
|
self.__template_path__ = 'ipadmini5'
|
||||||
|
self.__colors__ = {"Gold": 'gold',
|
||||||
|
"Silver": 'silver',
|
||||||
|
"Space Gray": 'spacegray'}
|
||||||
|
|
||||||
|
self.__portrait_width__ = 1536
|
||||||
|
self.__portrait_height__ = 2048
|
||||||
|
self.__portrait_x__ = 150
|
||||||
|
self.__portrait_y__ = 330
|
||||||
|
|
||||||
|
self.__landscape_width__ = 2048
|
||||||
|
self.__landscape_height__ = 1536
|
||||||
|
self.__landscape_x__ = 330
|
||||||
|
self.__landscape_y__ = 150
|
BIN
MockupModule/templates/ipadmini5/example.png
Normal file
After Width: | Height: | Size: 538 KiB |
BIN
MockupModule/templates/ipadmini5/gold/landscape.png
Normal file
After Width: | Height: | Size: 235 KiB |
BIN
MockupModule/templates/ipadmini5/gold/portrait.png
Normal file
After Width: | Height: | Size: 222 KiB |
BIN
MockupModule/templates/ipadmini5/silver/landscape.png
Normal file
After Width: | Height: | Size: 225 KiB |
BIN
MockupModule/templates/ipadmini5/silver/portrait.png
Normal file
After Width: | Height: | Size: 215 KiB |
BIN
MockupModule/templates/ipadmini5/spacegray/landscape.png
Normal file
After Width: | Height: | Size: 279 KiB |
BIN
MockupModule/templates/ipadmini5/spacegray/portrait.png
Normal file
After Width: | Height: | Size: 300 KiB |
27
MockupModule/templates/ipadpro114/__init__.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from MockupModule.templates import Template
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Device(Template):
|
||||||
|
def __device_init__(self):
|
||||||
|
self.manufacturer = 'Apple'
|
||||||
|
self.name = 'iPad Pro 4 11"'
|
||||||
|
self.type = 'tablet'
|
||||||
|
self.year = 2020
|
||||||
|
self.resolution = '{width} x {height}'.format(width=2388, height=1668)
|
||||||
|
|
||||||
|
self.__template_path__ = 'ipadpro114'
|
||||||
|
self.__colors__ = {"Silver": 'silver',
|
||||||
|
"Space Gray": 'spacegray'}
|
||||||
|
|
||||||
|
self.__portrait_width__ = 1668
|
||||||
|
self.__portrait_height__ = 2388
|
||||||
|
self.__portrait_x__ = 200
|
||||||
|
self.__portrait_y__ = 200
|
||||||
|
|
||||||
|
self.__landscape_width__ = 2388
|
||||||
|
self.__landscape_height__ = 1668
|
||||||
|
self.__landscape_x__ = 200
|
||||||
|
self.__landscape_y__ = 200
|
BIN
MockupModule/templates/ipadpro114/example.png
Normal file
After Width: | Height: | Size: 537 KiB |
BIN
MockupModule/templates/ipadpro114/silver/landscape.png
Normal file
After Width: | Height: | Size: 223 KiB |
BIN
MockupModule/templates/ipadpro114/silver/portrait.png
Normal file
After Width: | Height: | Size: 250 KiB |
BIN
MockupModule/templates/ipadpro114/spacegray/landscape.png
Normal file
After Width: | Height: | Size: 217 KiB |
BIN
MockupModule/templates/ipadpro114/spacegray/portrait.png
Normal file
After Width: | Height: | Size: 245 KiB |
27
MockupModule/templates/ipadpro134/__init__.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from MockupModule.templates import Template
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Device(Template):
|
||||||
|
def __device_init__(self):
|
||||||
|
self.manufacturer = 'Apple'
|
||||||
|
self.name = 'iPad Pro 4 12.9"'
|
||||||
|
self.type = 'tablet'
|
||||||
|
self.year = 2020
|
||||||
|
self.resolution = '{width} x {height}'.format(width=2732, height=2048)
|
||||||
|
|
||||||
|
self.__template_path__ = 'ipadpro134'
|
||||||
|
self.__colors__ = {"Silver": 'silver',
|
||||||
|
"Space Gray": 'spacegray'}
|
||||||
|
|
||||||
|
self.__portrait_width__ = 2048
|
||||||
|
self.__portrait_height__ = 2732
|
||||||
|
self.__portrait_x__ = 200
|
||||||
|
self.__portrait_y__ = 200
|
||||||
|
|
||||||
|
self.__landscape_width__ = 2732
|
||||||
|
self.__landscape_height__ = 2048
|
||||||
|
self.__landscape_x__ = 200
|
||||||
|
self.__landscape_y__ = 200
|
BIN
MockupModule/templates/ipadpro134/example.png
Normal file
After Width: | Height: | Size: 612 KiB |
BIN
MockupModule/templates/ipadpro134/silver/landscape.png
Normal file
After Width: | Height: | Size: 275 KiB |
BIN
MockupModule/templates/ipadpro134/silver/portrait.png
Normal file
After Width: | Height: | Size: 299 KiB |
BIN
MockupModule/templates/ipadpro134/spacegray/landscape.png
Normal file
After Width: | Height: | Size: 269 KiB |
BIN
MockupModule/templates/ipadpro134/spacegray/portrait.png
Normal file
After Width: | Height: | Size: 292 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 556 KiB |
Before Width: | Height: | Size: 208 KiB After Width: | Height: | Size: 523 KiB |
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 553 KiB |
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 618 KiB |
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 394 KiB |
Before Width: | Height: | Size: 208 KiB After Width: | Height: | Size: 459 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 348 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 518 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 386 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 514 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 655 KiB |
BIN
MockupModule/templates/watchseries644mm/example.png
Normal file
After Width: | Height: | Size: 250 KiB |
1
requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Pillow>=8.4.0
|
12
setup.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='MockupEngineer',
|
||||||
|
version='2022.22.01.1',
|
||||||
|
packages=['MockupModule', 'MockupModule.templates'],
|
||||||
|
url='https://github.com/ulbwazhine/MockupEngineer',
|
||||||
|
license='',
|
||||||
|
author='ulbwa',
|
||||||
|
author_email='ulbwa@icloud.com',
|
||||||
|
description='An simple library for creating beautiful screenshots.'
|
||||||
|
)
|