This repository has been archived by the owner on Jul 22, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
kubinka0505
committed
Mar 1, 2021
0 parents
commit 567d4bb
Showing
14 changed files
with
905 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
## 0.1 | ||
Alpha development. | ||
|
||
## 0.3 | ||
Re-write. | ||
|
||
## 0.4 | ||
Initial release. | ||
|
||
## 2.0 | ||
Bug-fixing. | ||
Added GIF support. | ||
Changed fonts. | ||
|
||
## 2.1 | ||
Modified several functions. | ||
Optimized creation time (ffmpeg >= 4.0.0) | ||
Added font. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"Image": { | ||
"URL": "", | ||
"Max_Width": 300, | ||
"Crop": false | ||
}, | ||
"Font": { | ||
"Type": 2 | ||
}, | ||
"Settings": { | ||
"Speed": 28 | ||
}, | ||
"Text": "", | ||
"Wrap": 14 | ||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<a href="https://ifunny.co/"><img src="https://cdn.discordapp.com/attachments/312993895887929355/714526409468412004/iFunny_Captions.png"></img></a> | ||
<center> <a href="https://www.python.org/downloads/release/python-375/"><img alt="Python 3.7.5" src="https://img.shields.io/badge/Python-3.7.5-brightgreen?style=for-the-badge&link=https://www.python.org/&https://www.python.org/downloads/&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAMAAAAMCGV4AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABVlBMVEUAAAA5e7Q3ebA3eK43dak3dKY2dKI5gLg4ebA1eq83d6s3caI8aaU5e7M3eK42eKs4cJsAgIA4eK85d7A2dqs2dKk2dKc3cqR2koD/10v/20k2ebU4ebDRvlz/1UX/00Q4erDbxFf/0UA2eK42aZb/1ET/zz83d6s3cqQ6c6GZpXuprXCpq2y8s2P900X/00M3cKL/3lH/zDs2dKZVg5L/yjk3c6U3caJihoz/yTn/xzg7dp03bpuqqnH/0kP/0kD/0D7/zjz/yzz/wzz//wD/2E7/zj7/yDf/41X/1Ub/zj3/zTz/yjn/yDf/1Ub/00L/0ED/zj3/zDv/yTr/xzg3d6s3dak3dKc3cqQ3caI3cJ82bp03eK42bZr/10c2a5j/1UX/00P/0UE3dKb/zz//zT3/3U7/20z/2Ur/10j/1Ub/zj3/zDv/00T/0D//0kL/1ET///8twZG5AAAAVXRSTlMAVcbw67tCEuhD9/YRG/ukKQIgLYiIiL44MxUm3HX1QKxwwuqzlfj6/oVudnZvhf2fq/aydbYz7njbKQ0zLb13d3ciEQEaoSoJ7vxN4Rw3suj27MNWkzfuJAAAAAFiS0dEca8HXOIAAAAHdElNRQfkBQcLNhpsHcMTAAAAuklEQVQI12NgAAJGJuZQFlY2Bihg5+DkCguP4OaB8nn5+IHcyCgBME9QSFhEVEw8MipaQlKKgUFaJiYULBsdKxsnJ8+gAOfGKyYkKjEow7kqqolJagzqYckamlraOjq6evpJKakMLMkRBoZp6RmZWYlArhGDcUSkCYybnWPKYGYeZQHi5iblZedYWjEwWNvYArl29g6OTs4uYBe5AmXz89yM3KHu9fAsyM/z8vbxhXnIzz8gMCg4BMQEAKy7MbtksegJAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTA1LTA3VDExOjU0OjI2KzAwOjAw1j8VsQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0wNS0wN1QxMTo1NDoyNiswMDowMKdirQ0AAAAASUVORK5CYII="></center></a> | ||
|
||
## Description | ||
I was very unsatisfied that there was only a mobile app caption tool so I've decided to create one. | ||
|
||
## Completed & Planned Features | ||
- [x] Completed | ||
- [ ] In Development | ||
--- | ||
- [x] PNG Captions | ||
- [x] GIF Captions | ||
- [ ] Offline support | ||
- [x] <code>Giphy</code> URLs support* | ||
- [x] <code>Tenor</code> URLs support* | ||
- [x] Optimization | ||
- [ ] GIF size reduction | ||
- [ ] Transparent GIF support | ||
- [ ] *[Program Showcase]()* | ||
|
||
* - Beta | ||
|
||
## Requirements | ||
- <code>Python 3.5</code> + | ||
- <code>PIL</code> | ||
- <code>requests</code> | ||
- <code>textwrap</code> | ||
- **<code>ffmpeg static executable binary >= 4.0.0</code>** | ||
- [Windows](https://www.videohelp.com/software/ffmpeg/old-versions "Windows: win") (Move <code>ffmpeg.exe</code> from <code>bin</code> to main folder) | ||
- [Linux](https://www.johnvansickle.com/ffmpeg/old-releases/) | ||
|
||
## Usage | ||
1. Modify the parameters in the <code>Config.json</code>: | ||
- <code>Image</code> : | ||
- <code>URL</code> : **Direct** media URL. __[Can be any Image/Video format that <code>ffmpeg</code> supports](https://en.wikipedia.org/wiki/FFmpeg#Supported_formats "Supported ffmpeg formats")__. | ||
- <code>Max_Width</code> : Maximum single frame width. Height is relatively scaled, same as font size. *Formula: Max Width ÷ 10*. **Default is 300**. | ||
- <code>Crop</code> : Crops transparent pixels around the **__every frame__**. **Default is <code>false</code>**. | ||
- <code>Font</code> : | ||
- <code>Type</code> : Defines font style used as caption text. **Default is <code>2</code>**. | ||
- <code>1</code> : <code>Roboto Black</code> (otf) | ||
- <code>2</code> : <code>Futura Condensed Extra Bold</code> (otf) | ||
- <code>3</code> : <code>Futura BT Pro Condensed Extra Black</code> (ttf)* | ||
- <code>Settings</code> : | ||
- <code>Speed</code> : Single frame display time. (in milliseconds). **Default is 28**. | ||
- <code>Text</code> : Image caption text. | ||
- <code>Wrap</code> : Text-wrap, used to break the words. **Default is 14**. | ||
2. Open <code>Run.sh</code> | ||
3. ...or go to Your command prompt and type following: | ||
```bash | ||
git clone https://github.com/kubinka0505/iFunny-Captions | ||
cd iFunny-Captions | ||
py __init__.py | ||
``` | ||
4. Share Your image from <code>Captions</code> directory. | ||
|
||
* - TrueType fonts (ttf) are poorly resized and will look bad on small images. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
python __init__.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
Image_Base = Image.new("RGBA", (2000, 1500), (255,) * 3) # White | ||
Image_Trans = Image.new("RGBA", (2000, 1500), (255, 255, 255, 0)) # Transparent | ||
|
||
Draw = ImageDraw.Draw(Image_Trans) | ||
|
||
if Config()["Font"]["Type"] == 1: | ||
__Path = "{0}\\Fonts\\Roboto Black.otf".format(os.getcwd()) | ||
if Config()["Font"]["Type"] == 2: | ||
__Path = "{0}\\Fonts\\Futura Condensed Extra Bold.otf".format(os.getcwd()) | ||
if Config()["Font"]["Type"] == 3: | ||
__Path = "{0}\\Fonts\\Futura BT Pro Condensed Extra Black.ttf".format(os.getcwd()) | ||
|
||
if system() != "Windows": | ||
__Path = __Path.replace("\\", "/") | ||
|
||
Font = ImageFont.truetype(__Path, Config()["Image"]["Max_Width"] // 10) | ||
Draw.text((0,) * 2, text = "\n".join(wrap(Config()["Text"], Config()["Wrap"])), fill = (0,) * 3, font = Font, align = "center") | ||
|
||
Image_Trans = Image_Trans.crop(Image_Trans.getbbox()) # Cropped Text | ||
|
||
Pasted = Image.new("RGBA", (Config()["Image"]["Max_Width"], Image_Trans.size[1] + Config()["Image"]["Max_Width"] // 10 * 2), (255,) * 3) | ||
Pasted = Trans_Paste(Pasted, Image_Trans) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Caption = Image.open(Frame) | ||
if Config()["Image"]["Crop"] == True: Caption = Caption.crop(Caption.getbbox()) | ||
|
||
Width = Pasted.size[0] | ||
Percentage = (Width / float(Caption.size[0])) | ||
Height_Size = int((float(Caption.size[1]) * float(Percentage))) | ||
Caption = Caption.resize((Width, Height_Size), Image.LANCZOS) | ||
|
||
Captionized = Margin(Caption, Pasted.size[1]) | ||
Captionized.paste(Pasted) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
def Trans_Paste(Background: Image, Foreground: Image) -> Image: | ||
"""Pasting transparent `Foreground` to `Background`.""" | ||
FRGRND_TRNS = Image.new("RGBA", Background.size) | ||
#---# | ||
Background_Width, Background_Height = Background.size | ||
Foreground_Width, Foreground_Height = Foreground.size | ||
#---# | ||
FRGRND_TRNS.paste(Foreground, ((Background_Width - Foreground_Width) // 2, (Background_Height - Foreground_Height) // 2), mask = Foreground) | ||
#---# | ||
IMG_RET = Image.alpha_composite(Background, FRGRND_TRNS) | ||
return IMG_RET | ||
|
||
def __Get_Service(URL: str): | ||
"""Converting raw URL to direct Image. | ||
Supported Services: | ||
- Tenor | ||
- Giphy""" | ||
if "tenor.com/view" in URL: | ||
return get(URL).text.split('contentUrl')[1].split("content")[0][2:].split('"')[1].replace("\\u002F", "/") | ||
if "giphy.com/gifs" in URL: | ||
return "https://media"+str(get(URL).text).split("https://media")[2].split('"')[0] | ||
else: | ||
return URL | ||
|
||
def Margin(Picture: Image, Top: int, Color: ImageColor = "#FFF") -> Image: | ||
"""Adds margin to an `Picture`.""" | ||
Width, Height = Picture.size | ||
Height = Height + Top + 0 | ||
#---# | ||
Field = Image.new(Picture.mode, (Width, Height), Color) | ||
Field.paste(Picture, (0, Top)) | ||
return Field | ||
|
||
def Config(): | ||
"""Loading values from JSON file.""" | ||
__Path = "{0}\Config.json" | ||
#---# | ||
if system() != "Windows": | ||
__Path = __Path.replace("\\", "/") | ||
#---# | ||
return load(open(__Path.format(os.getcwd()), encoding = "utf-8")) | ||
|
||
def Random_String(Length: int = 16): | ||
"""Random string creation used in saving files.""" | ||
return "".join(choice(printable[0:62]) for String in range(Length)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import os | ||
from json import load | ||
from requests import get | ||
from random import choice | ||
from textwrap import wrap | ||
from platform import system | ||
from string import printable | ||
from PIL import Image, ImageDraw, ImageFont, ImageColor | ||
|
||
__author__ = "kubinka0505" | ||
__copyright__ = __author__ | ||
__credits__ = [__author__, "SuperCuber"] | ||
__version__ = "2.1" | ||
__date__ = "14.11.2020" | ||
__status__ = "Development" | ||
__license__ = "GPL V3" | ||
|
||
__FORMAT = "png" | ||
print("Setting up utils...") | ||
exec(open("{0}{1}Scripts{1}Utils.py".format(os.getcwd(), "\\" if system == "Windows" else "/")).read()) | ||
|
||
print("Converting URL Image to Frames... This can take a while.") | ||
os.system('ffmpeg.exe -i {0} Frame_%06d.{1} -hide_banner -loglevel panic'.format(__Get_Service(Config()["Image"]["URL"]), __FORMAT)) | ||
Frames = [File for File in os.listdir(os.getcwd()) if File.endswith(__FORMAT)] | ||
Frames.sort(key = str) | ||
|
||
print("Making {0}...".format("PNG" if len(Frames) == 1 else "GIF")) | ||
for Frame in Frames: | ||
Caption = Image.open(Frame) | ||
#---# | ||
exec(open("{0}{1}Scripts{1}Caption.py".format(os.getcwd(), "\\" if system == "Windows" else "/")).read()) | ||
exec(open("{0}{1}Scripts{1}Gifer.py".format(os.getcwd(), "\\" if system == "Windows" else "/")).read()) | ||
#---# | ||
Captionized.save(Frame) | ||
|
||
GIF = Image.open(Frames[0]) | ||
print("Saving {0}...".format("PNG" if len(Frames) == 1 else "GIF")) | ||
GIF.save("{0}{1}Captions{1}{2}_{3}.{4}".format( | ||
os.getcwd(), | ||
"\\" if system == "Windows" else "/", | ||
Config()["Text"].\ | ||
replace(" ", "_").\ | ||
replace("\\", "_").\ | ||
replace("/", "_").\ | ||
replace(":", "_").\ | ||
replace("*", "_").\ | ||
replace("?", "_").\ | ||
replace("<", "_").\ | ||
replace(">", "_").\ | ||
replace("|", "_").\ | ||
encode().decode("utf-8", errors = "strict"), | ||
Random_String(8), | ||
"png" if len(Frames) == 1 else "gif" | ||
), | ||
save_all = True, | ||
loop = 0, | ||
append_images = [Image.open(Frame) for Frame in Frames[1:]], | ||
duration = Config()["Settings"]["Speed"], | ||
) | ||
|
||
print("Removing {0}...".format("Image" if len(Frames) == 1 else "Frames")) | ||
[os.remove("{0}{1}{2}".format(os.getcwd(), "\\" if system == "Windows" else "/" , Frame)) for Frame in os.listdir(os.getcwd()) if Frame.endswith(__FORMAT)] | ||
print("Done!") |