Files
szuru-eink-bot/epd/image_processor.py
2025-07-20 16:54:43 +00:00

97 lines
3.3 KiB
Python

from PIL import Image
def getErr(r,g,b,stdCol):
r-=stdCol[0]
g-=stdCol[1]
b-=stdCol[2]
return r*r + g*g + b*b
def getNear(r,g,b, curPal):
ind=0
err=getErr(r,g,b,curPal[0])
for i in range(1,len(curPal)):
cur=getErr(r,g,b,curPal[i])
if (cur<err):
err=cur
ind=i
return ind
def addVal(c,r,g,b,k):
return[c[0]+(r*k)/32,c[1]+(g*k)/32,c[2]+(b*k)/32]
def procImg(img, dW, dH, dX, dY, palInd, isLvl, isRed, palArr):
if isRed and ((palInd & 1) == 0):
raise ValueError('This white-black display')
if not isRed:
palInd = palInd & 0xFE
curPal = palArr[palInd]
sW = img.width
sH = img.height
pDst = Image.new('RGB', (dW, dH))
pixels = pDst.load()
if isLvl:
# Level-based processing
for j in range(dH):
y = dY + j
for i in range(dW):
x = dX + i
if 0 <= x < sW and 0 <= y < sH:
r, g, b = img.getpixel((x, y))
color_index = getNear(r, g, b, curPal)
pixels[i, j] = tuple(curPal[color_index])
else:
pixels[i, j] = tuple(curPal[(i + j) % 2]) # checkerboard for out of bounds
else:
# Dithering
errArr = [[[0, 0, 0] for _ in range(dW)] for _ in range(2)]
aInd = 0
bInd = 1
for j in range(dH):
y = dY + j
aInd, bInd = bInd, aInd # swap buffers
for i in range(dW):
errArr[bInd][i] = [0,0,0]
for i in range(dW):
x = dX + i
if 0 <= x < sW and 0 <= y < sH:
old = errArr[aInd][i]
r_orig, g_orig, b_orig = img.getpixel((x, y))
r = r_orig + old[0]
g = g_orig + old[1]
b = b_orig + old[2]
color_index = getNear(r, g, b, curPal)
colVal = curPal[color_index]
pixels[i, j] = tuple(colVal)
r_err = r - colVal[0]
g_err = g - colVal[1]
b_err = b - colVal[2]
# Propagate error (Floyd-Steinberg-like)
if i == 0:
errArr[bInd][i] = addVal(errArr[bInd][i], r_err, g_err, b_err, 7.0)
if dW > 1:
errArr[bInd][i+1] = addVal(errArr[bInd][i+1], r_err, g_err, b_err, 2.0)
errArr[aInd][i+1] = addVal(errArr[aInd][i+1], r_err, g_err, b_err, 7.0)
elif i == dW - 1:
errArr[bInd][i-1] = addVal(errArr[bInd][i-1], r_err, g_err, b_err, 7.0)
errArr[bInd][i] = addVal(errArr[bInd][i], r_err, g_err, b_err, 9.0)
else:
errArr[bInd][i-1] = addVal(errArr[bInd][i-1], r_err, g_err, b_err, 3.0)
errArr[bInd][i] = addVal(errArr[bInd][i], r_err, g_err, b_err, 5.0)
errArr[bInd][i+1] = addVal(errArr[bInd][i+1], r_err, g_err, b_err, 1.0)
errArr[aInd][i+1] = addVal(errArr[aInd][i+1], r_err, g_err, b_err, 7.0)
else:
pixels[i, j] = tuple(curPal[(i + j) % 2]) # checkerboard
return pDst