@ -0,0 +1,10 @@ | |||
# pixelate via API | |||
Setup: | |||
```bash | |||
python3 -m venv venv | |||
source venv/bin/activate | |||
pip install -r requirements.txt | |||
uvicorn main:app --reload | |||
``` | |||
and go to http://localhost:8000 |
@ -0,0 +1,7 @@ | |||
from pathlib import Path | |||
VALID_FILE_FORMATS = [".jpg",".jpeg",".png"] | |||
def has_valid_suffix(file): | |||
return Path(file).suffix.lower() in VALID_FILE_FORMATS |
@ -0,0 +1,45 @@ | |||
import numpy as np | |||
from PIL import Image, ImageEnhance | |||
import io | |||
def pixelate(img_name: str, | |||
saturation: float = 1.25, | |||
contrast: float = 1.2, | |||
n_colors: int = 10, | |||
superpixel_size: int = 10): | |||
""" | |||
See: https://github.com/ferretj/pixelate | |||
""" | |||
img = Image.open(img_name) | |||
img_size = img.size | |||
# boost saturation of image | |||
sat_booster = ImageEnhance.Color(img) | |||
img = sat_booster.enhance(saturation) | |||
# increase contrast of image | |||
contr_booster = ImageEnhance.Contrast(img) | |||
img = contr_booster.enhance(contrast) | |||
# reduce the number of colors used in picture | |||
img = img.convert('P', palette=Image.ADAPTIVE, colors=n_colors) | |||
# reduce image size | |||
reduced_size = (img_size[0] // superpixel_size, img_size[1] // superpixel_size) | |||
img = img.resize(reduced_size, Image.BICUBIC) | |||
# resize to original shape to give pixelated look | |||
img = img.resize(img_size, Image.BICUBIC) | |||
return img | |||
def img2byte(img:Image): | |||
imgByteArr = io.BytesIO() | |||
img.save(imgByteArr, format="PNG") | |||
imgByteArr = imgByteArr.getvalue() | |||
return imgByteArr | |||
if __name__ == '__main__': | |||
img = pixelate("img.jpg") | |||
img.save("out.png") |
@ -0,0 +1,44 @@ | |||
from fastapi import FastAPI, File, UploadFile, Response, HTTPException | |||
from fastapi.responses import HTMLResponse | |||
from img_proc import pixelate, img2byte | |||
import fileutils as fu | |||
app = FastAPI() | |||
@app.get("/", response_class=HTMLResponse, include_in_schema=False) | |||
async def root_html(): | |||
return """ | |||
<html> | |||
<head> | |||
<title>pixelate via API</title> | |||
</head> | |||
<body> | |||
<h2>pixelate</h2> | |||
<strong> go to <a href="/docs"> /docs</a> for OpenAPI docs </strong> | |||
<p>based on: <a href="https://github.com/ferretj/pixelate">https://github.com/ferretj/pixelate</a> </p> | |||
</body> | |||
</html> | |||
""" | |||
@app.post("/") | |||
async def root(saturation: float = 1.5, | |||
contrast: float = 1.2, | |||
n_colors: int = 10, | |||
superpixel_size: int = 15, | |||
file: UploadFile = File(...)): | |||
""" | |||
saturation: float = 1.25, | |||
contrast: float = 1.2, | |||
n_colors: int = 10, | |||
superpixel_size: int = 10, | |||
""" | |||
if not fu.has_valid_suffix(file.filename): | |||
raise HTTPException(status_code=400, | |||
detail="Invalid file ending! Only {} accepted".fomrat(fs.VALID_FILE_FORMATS)) | |||
out_img = pixelate(file.file, | |||
saturation = saturation, | |||
contrast = contrast, | |||
n_colors = n_colors, | |||
superpixel_size = superpixel_size) | |||
return Response(content=img2byte(out_img), media_type="image/png") |