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(): def initWidgets():
widgetList = [] widgetList = []
widgetList.append(widget.TextWidget(cwidth, cheight, 0, 0, 1, 2, str1)) widgetList.append(widget.TextWidget(cwidth, cheight, (0, 0), (1, 3), str1))
widgetList.append(widget.TextWidget(cwidth, cheight, 1, 0, 2, 1, str2)) widgetList.append(widget.TextWidget(cwidth, cheight, (1, 0), (1, 3), str2))
#widgetList.append(widget.ImageWidget(cwidth, cheight, 2, 1, 1, 1, "mono", "faces.jpg")) widgetList.append(widget.ImageWidget(cwidth, cheight, (2, 0), (1, 1), "mono", "fill", "img3.jpg"))
widgetList.append(widget.ImageWidget(cwidth, cheight, 1, 1, 2, 2, "mono", "calvin.jpg")) widgetList.append(widget.ImageWidget(cwidth, cheight, (2, 1), (1, 1), "mono", "fill", "sun1.jpg"))
widgetList.append(widget.ImageWidget(cwidth, cheight, 0, 2, 1, 1, "mono", "img1.jpg")) widgetList.append(widget.ImageWidget(cwidth, cheight, (2, 2), (1, 1), "mono", "fill", "w.jpg"))
return widgetList return widgetList
def drawWidget(w): 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. e.g.
widgetList.append(widget.ImageWidget(cwidth, cheight, 1, 1, 2, 2, "mono", "calvin.jpg")) 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. 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. The program is built for python2.
$ python EinkPaper.py $ 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: Or manually enable test mode:
$ python EinkPaper.py -t $ 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(): class TextWidget():
#this example widget will have a set size: 3x1 cells (one column) #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 #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 = ""): def __init__(self, cwidth, cheight, xy = (0, 0), dim = (1, 1), str = ""):
self.width = width self.width = dim[0]
self.height = height self.height = dim[1]
self.wt = cwidth*width self.wt = cwidth*dim[0]
self.ht = cheight*height self.ht = cheight*dim[1]
self.cellX = x self.cellX = xy[0]
self.cellY = y self.cellY = xy[1]
self.image_yellow = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame self.image_yellow = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame
self.draw_yellow = ImageDraw.Draw(self.image_yellow) self.draw_yellow = ImageDraw.Draw(self.image_yellow)
self.image_black = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame self.image_black = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame
@ -74,18 +74,19 @@ class TextWidget():
class ImageWidget(): class ImageWidget():
#this widget displays an image #this widget displays an image
#needs to recieve an image file as input. Then resize and convert to monochrome. #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 = ""): def __init__(self, cwidth, cheight, xy = (0, 0), dim = (1, 1), bwMode = "mono", scaleMode = "fill", img = ""):
self.width = width self.width = dim[0]
self.height = height self.height = dim[1]
self.wt = cwidth*width self.wt = cwidth*dim[0]
self.ht = cheight*height self.ht = cheight*dim[1]
self.cellX = x self.cellX = xy[0]
self.cellY = y self.cellY = xy[1]
self.image_yellow = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame self.image_yellow = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame
self.draw_yellow = ImageDraw.Draw(self.image_yellow) self.draw_yellow = ImageDraw.Draw(self.image_yellow)
self.image_black = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame self.image_black = Image.new('1', (self.wt, self.ht), 255) #255: clear the frame
self.draw_black = ImageDraw.Draw(self.image_black) self.draw_black = ImageDraw.Draw(self.image_black)
self.mode = mode self.bwMode = bwMode
self.scaleMode = scaleMode
self.updateWidget(Image.open(img)) self.updateWidget(Image.open(img))
def resizeImg(self, img): def resizeImg(self, img):
@ -104,7 +105,7 @@ class ImageWidget():
print(" ratios are equal, not limited") print(" ratios are equal, not limited")
return fixedImg return fixedImg
def zoomImg(self, img): def fillImg(self, img):
#enlarge the image and crop to fill the widget canvas #enlarge the image and crop to fill the widget canvas
iRatio = img.size[0]/img.size[1] #image ratio iRatio = img.size[0]/img.size[1] #image ratio
cRatio = self.wt/self.ht #canvas 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)) 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 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 offset = 0.5*(fixedImg.size[1] - self.ht) #centre by height
cropped = fixedImg.crop((0, offset, self.wt, offset+self.ht)) cropped = fixedImg.crop((0, offset, self.wt, offset+self.ht-1))
cropped.load() #cropped.load()
print("zoomed to fill height") print("zoomed to fill height")
return cropped return cropped
if cRatio < iRatio: if cRatio < iRatio:
fixedImg = img.resize((int(self.ht*iRatio), self.ht)) #height = ht, calc new width w/ ratio 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 offset = 0.5*(fixedImg.size[0] - self.wt) #centre by width
cropped = fixedImg.crop((offset, 0, offset+self.wt, self.ht)) cropped = fixedImg.crop((offset, 0, offset+self.wt, self.ht-1))
cropped.load() #cropped.load()
print("zoomed to fill width") print("zoomed to fill width")
return cropped return cropped
print("not zoomed") print("not zoomed")
return img.resize((self.wt, self.ht)) 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): def threshold(self, val):
if(val>100): if(val>self.thresLim):
return 1 return 1
else: else:
return 0 return 0
def bwImg(self, img): 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') return img.convert('L').point(self.threshold, '1')
if self.mode is "dither": if self.bwMode is "dither":
return img.convert(mode='1') return img.convert(mode='1')
def pasteImg(self, img): def pasteImg(self, img):
@ -154,7 +165,12 @@ class ImageWidget():
self.image_yellow.save("imgYellowWidget.bmp") self.image_yellow.save("imgYellowWidget.bmp")
def updateWidget(self, img): 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") rsImg.save("rsImg.bmp")
newImg = self.bwImg(rsImg) newImg = self.bwImg(rsImg)
newImg.save("bwImg.bmp") newImg.save("bwImg.bmp")

Binary file not shown.
Loading…
Cancel
Save