image scaling types and dynamic monochrome thresholding

redesign
Josef Dabrowski 7 years ago
parent f6b936e37f
commit ecdc4f03a6

@ -47,11 +47,12 @@ strList.append(str3)
def initWidgets():
widgetList = []
widgetList.append(widget.TextWidget(cwidth, cheight, 0, 0, 1, 2, str1))
widgetList.append(widget.TextWidget(cwidth, cheight, 1, 0, 2, 1, str2))
#widgetList.append(widget.ImageWidget(cwidth, cheight, 2, 1, 1, 1, "mono", "faces.jpg"))
widgetList.append(widget.ImageWidget(cwidth, cheight, 1, 1, 2, 2, "mono", "calvin.jpg"))
widgetList.append(widget.ImageWidget(cwidth, cheight, 0, 2, 1, 1, "mono", "img1.jpg"))
widgetList.append(widget.TextWidget(cwidth, cheight, (0, 0), (1, 3), str1))
widgetList.append(widget.TextWidget(cwidth, cheight, (1, 0), (1, 3), str2))
widgetList.append(widget.ImageWidget(cwidth, cheight, (2, 0), (1, 1), "mono", "fill", "img3.jpg"))
widgetList.append(widget.ImageWidget(cwidth, cheight, (2, 1), (1, 1), "mono", "fill", "sun1.jpg"))
widgetList.append(widget.ImageWidget(cwidth, cheight, (2, 2), (1, 1), "mono", "fill", "w.jpg"))
return widgetList
def drawWidget(w):

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

@ -16,7 +16,8 @@ config data --> EinkPaper.py
e.g.
widgetList.append(widget.ImageWidget(cwidth, cheight, 1, 1, 2, 2, "mono", "calvin.jpg"))
Text widget has one 'other argument', it is the string to be displayed on the widget. Image widget has two other args, the type of black and white filter to process the image with, and the location or filename of the image. The two b&w filters are "mono" for monochrome, and "dither" for greyscale dithering.
Text widget has one 'other argument', it is the string to be displayed on the widget. Image widget has three other args, the type of black and white filter to process the image with, the type of image size transformation to be performed, and the location or filename of the image. The two b&w filters are "mono" for monochrome, and "dither" for greyscale dithering. Image transforms are "fill", "resize", and "none".
The threshold limit for calculating the cutoff for black/white pixels in the monochrome function is calculated in autoThresholdLimit(). The limit is: the lowest pixel value + a factor between 0 and 1 x the pixel value range of the image. The pixel value range is found by performing getextrema() on the image. By default the factor is set to 0.4, or 40%.
Widgets will be drawn on the final canvas in the order they are appended to the widgetList array.
@ -28,7 +29,7 @@ widget.py --> EinkPaper.py
The program is built for python2.
$ python EinkPaper.py
If the display package is present, will run with test mode disabled. Will repeatedly update each widget and each iteration will display the latest version on the external display. If the package is missing, will run in test mode, saving the generated canvas images to the working directory.
If the display package is present, will run with test mode disabled. Will periodically update each widget and each iteration will display the latest version on the external display. If the package is missing, will run in test mode, saving the generated canvas images to the working directory.
Or manually enable test mode:
$ python EinkPaper.py -t

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 KiB

BIN
w.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 KiB

@ -39,13 +39,13 @@ def putImage(imagepath, maskpath, position, colour):
class TextWidget():
#this example widget will have a set size: 3x1 cells (one column)
#an instance of this widget class can be created and pasted to canvas
def __init__(self, cwidth, cheight, x = 0, y = 0, width = 1, height = 1, str = ""):
self.width = width
self.height = height
self.wt = cwidth*width
self.ht = cheight*height
self.cellX = x
self.cellY = y
def __init__(self, cwidth, cheight, xy = (0, 0), dim = (1, 1), str = ""):
self.width = dim[0]
self.height = dim[1]
self.wt = cwidth*dim[0]
self.ht = cheight*dim[1]
self.cellX = xy[0]
self.cellY = xy[1]
self.image_yellow = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame
self.draw_yellow = ImageDraw.Draw(self.image_yellow)
self.image_black = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame
@ -74,18 +74,19 @@ class TextWidget():
class ImageWidget():
#this widget displays an image
#needs to recieve an image file as input. Then resize and convert to monochrome.
def __init__(self, cwidth, cheight, x = 0, y = 0, width = 1, height = 1, mode = "mono", img = ""):
self.width = width
self.height = height
self.wt = cwidth*width
self.ht = cheight*height
self.cellX = x
self.cellY = y
def __init__(self, cwidth, cheight, xy = (0, 0), dim = (1, 1), bwMode = "mono", scaleMode = "fill", img = ""):
self.width = dim[0]
self.height = dim[1]
self.wt = cwidth*dim[0]
self.ht = cheight*dim[1]
self.cellX = xy[0]
self.cellY = xy[1]
self.image_yellow = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame
self.draw_yellow = ImageDraw.Draw(self.image_yellow)
self.image_black = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame
self.draw_black = ImageDraw.Draw(self.image_black)
self.mode = mode
self.bwMode = bwMode
self.scaleMode = scaleMode
self.updateWidget(Image.open(img))
def resizeImg(self, img):
@ -104,7 +105,7 @@ class ImageWidget():
print(" ratios are equal, not limited")
return fixedImg
def zoomImg(self, img):
def fillImg(self, img):
#enlarge the image and crop to fill the widget canvas
iRatio = img.size[0]/img.size[1] #image ratio
cRatio = self.wt/self.ht #canvas ratio
@ -112,30 +113,40 @@ class ImageWidget():
print("new sizes as calcd in resize: "+str(self.wt)+" "+str(self.wt/iRatio))
fixedImg = img.resize((self.wt, int(self.wt/iRatio))) #width = wt, calc new height w/ ratio
offset = 0.5*(fixedImg.size[1] - self.ht) #centre by height
cropped = fixedImg.crop((0, offset, self.wt, offset+self.ht))
cropped.load()
cropped = fixedImg.crop((0, offset, self.wt, offset+self.ht-1))
#cropped.load()
print("zoomed to fill height")
return cropped
if cRatio < iRatio:
fixedImg = img.resize((int(self.ht*iRatio), self.ht)) #height = ht, calc new width w/ ratio
offset = 0.5*(fixedImg.size[0] - self.wt) #centre by width
cropped = fixedImg.crop((offset, 0, offset+self.wt, self.ht))
cropped.load()
cropped = fixedImg.crop((offset, 0, offset+self.wt, self.ht-1))
#cropped.load()
print("zoomed to fill width")
return cropped
print("not zoomed")
return img.resize((self.wt, self.ht))
def autoThresholdLimit(self, img):
gscale = img.convert(mode="L")
gscale.save("greyscale.bmp")
extrema = gscale.getextrema()
print("EXTREMA: "+str(extrema))
limit = extrema[0] + 0.4*(extrema[1]-extrema[0])
print(limit)
self.thresLim = limit
def threshold(self, val):
if(val>100):
if(val>self.thresLim):
return 1
else:
return 0
def bwImg(self, img):
if self.mode is "mono":
self.autoThresholdLimit(img)
if self.bwMode is "mono":
return img.convert('L').point(self.threshold, '1')
if self.mode is "dither":
if self.bwMode is "dither":
return img.convert(mode='1')
def pasteImg(self, img):
@ -154,7 +165,12 @@ class ImageWidget():
self.image_yellow.save("imgYellowWidget.bmp")
def updateWidget(self, img):
rsImg = self.resizeImg(img)
if self.scaleMode is "fill":
rsImg = self.fillImg(img)
if self.scaleMode is "resize":
rsImg = self.resizeImg(img)
if self.scaleMode is "none":
rsImg = img
rsImg.save("rsImg.bmp")
newImg = self.bwImg(rsImg)
newImg.save("bwImg.bmp")

Binary file not shown.
Loading…
Cancel
Save