mswhite commited on
Commit
918c38e
·
verified ·
1 Parent(s): 3a3b41e

Upload 2 files

Browse files
Files changed (2) hide show
  1. Sid_Dithers.py +694 -0
  2. weather_icon.bmp +0 -0
Sid_Dithers.py ADDED
@@ -0,0 +1,694 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # =======================
3
+ # Imports
4
+ # =======================
5
+
6
+ import os, sys, time, re
7
+ from datetime import datetime as dt
8
+ from itertools import chain, filterfalse
9
+
10
+ from urllib.request import urlopen
11
+ from urllib.request import Request
12
+ import urllib.error
13
+
14
+ import numpy as np
15
+ from PIL import Image
16
+
17
+
18
+ # =======================
19
+ # Functions
20
+ # =======================
21
+
22
+ # Internet Functions
23
+
24
+ def check_site_redirected(starturl):
25
+
26
+ res = urllib.request.urlopen(starturl)
27
+ finalurl = res.geturl()
28
+ return finalurl
29
+
30
+ def get_links(start_html, c_regex):
31
+
32
+ html_links = []
33
+
34
+ try:
35
+ # Spoof Header to look like regular user browser
36
+ req = Request(start_html)
37
+ req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 AOL/9.8 AOLBuild/4346.2019.US Safari/537.36')
38
+ start_file = urlopen(req)
39
+
40
+ except urllib.error.HTTPError as e:
41
+ print('Download Failed for',start_html)
42
+ print('Status', e.code,' - Reason', e.reason,' - Url', e.url)
43
+ return html_links
44
+
45
+ start_text = str(start_file.read(),encoding="utf-8",errors="ignore") # is there an encoding problem -- eg utf-8 -- or errors="replace" - replaces the unencodable unicode to a question mark ?
46
+ start_file.close()
47
+
48
+ #print("DEBUG - sleep on link download")
49
+ #time.sleep(0.5) # DEBUG
50
+
51
+ if start_text != "": # If content exists
52
+ html_links = c_regex.findall(start_text)
53
+
54
+ return html_links
55
+
56
+ # Data Pipe functions
57
+
58
+ def pipe_inspector(link_input):
59
+ print("'",link_input,"',")
60
+ yield link_input
61
+
62
+ # ----------------
63
+
64
+ def link_from_list(link_list):
65
+ for link_input in link_list:
66
+ yield link_input
67
+
68
+ def get_test_links(link_input, c_regex):
69
+ html_links = c_regex.findall(str(link_input))
70
+ return html_links
71
+
72
+ def link_text_replace_filter(file_link):
73
+ return [file_link.replace("vids","highres")]
74
+
75
+ def link_prefix_adder(file_link):
76
+ return [prefix_adder+file_link]
77
+
78
+
79
+ def file_name_filter(file_link,c_regex):
80
+ file_name = file_link[file_link.rfind("/")+1:]
81
+ file_name = file_name[:-4]
82
+ #print(file_name)
83
+ link_filter = c_regex.findall(str(file_name))
84
+ if link_filter == []:
85
+ return ""
86
+ else:
87
+ return [file_link]
88
+
89
+ def file_name_generator(file_link):
90
+
91
+ str_template = "%2d"
92
+ file_list = []
93
+
94
+ for c in range(1,10+1):
95
+ file_name = str_template % (c)
96
+ file_list.append(file_name)
97
+
98
+ return file_list
99
+
100
+
101
+ # ========================
102
+
103
+ class link_prefix():
104
+
105
+ def __init__(self, file_prefix):
106
+ self.file_prefix = file_prefix
107
+ return
108
+
109
+ def add(self, file_link):
110
+ #print("'" + self.file_prefix + file_link + "',")
111
+ return [self.file_prefix + file_link]
112
+
113
+ class link_two_string():
114
+
115
+ def __init__(self, string_format, func1=None, func2=None):
116
+ self.string_format = string_format
117
+ self.func1 = func1
118
+ self.func2 = func2
119
+ return
120
+
121
+ def add(self, file_link):
122
+
123
+ if (self.func1 == None and self.func2 != None):
124
+ return [self.string_format % (file_link,self.func2(file_link))]
125
+ elif (self.func1!=None and self.func2==None):
126
+ return [self.string_format % (self.func1(file_link),file_link)]
127
+ elif (self.func1!=None and self.func2!=None):
128
+ return [self.string_format % (self.func1(file_link),self.func2(file_link))]
129
+ else:
130
+ return [self.string_format % (file_link,file_link)]
131
+
132
+ class link_generator():
133
+
134
+ def __init__(self, file_ext,header,start,end):
135
+ self.file_ext = file_ext
136
+ self.header = header
137
+ self.start = start
138
+ self.end = end
139
+ self.filelist = []
140
+ return
141
+
142
+ def add(self, file_link):
143
+ self.filelist = []
144
+ for c in range(self.start,self.end+1):
145
+ #filename = file_link + "/" + self.header % (c) + self.file_ext
146
+ filename = file_link + self.header % (c) + self.file_ext
147
+ self.filelist.append(filename)
148
+ return self.filelist
149
+
150
+ # Iterator Functions
151
+
152
+ def html_cal_iter(html_str,start_year,end_year,end_month):
153
+ for tgt_year in range(start_year, end_year+1):
154
+ for tgt_month in range(1,12+1):
155
+ if tgt_year < end_year or (tgt_year == end_year and tgt_month <= end_month):
156
+ yield html_str % (tgt_year,tgt_month)
157
+
158
+ def html_num_iter(html_str,start_page,end_page):
159
+ for tgt_page in range(start_page, end_page+1):
160
+ yield html_str % (tgt_page)
161
+
162
+ def html_list_iter(iter_list):
163
+ for tgt_page in iter_list:
164
+ yield tgt_page
165
+
166
+ def html_alpha_iter(html_str,start_letter=0,end_letter=26,use_upper=True):
167
+
168
+ alpha = "abcdefghijklmnopqrstuvwxyz"
169
+ alpha = alpha[start_letter:end_letter]
170
+
171
+ if use_upper:
172
+ alpha = alpha.upper()
173
+
174
+ for tgt_page in alpha:
175
+ yield html_str % (tgt_page)
176
+
177
+
178
+ # =========================
179
+ # Classes
180
+ # =========================
181
+
182
+ # Wrapper classes used for data pipes
183
+
184
+ class cDownloader:
185
+
186
+ def __init__(self, file_namer, file_extension, file_prefix="", file_start_counter=0, pause=0.2, dead_link_kill=3, snap_page=False):
187
+
188
+ # Parameters to set for processing by the data pipes
189
+
190
+ self.file_namer = file_namer
191
+ self.file_ext = file_extension
192
+ self.prefix = file_prefix
193
+ #self.html_level_prefix = html_level_prefix
194
+ self.file_count = file_start_counter
195
+ self.pause = pause
196
+
197
+ self.dead_link_kill = dead_link_kill
198
+ self.dead_links = 0
199
+ self.last_dead_link = ""
200
+ self.snap_page = snap_page
201
+
202
+ if self.snap_page:
203
+
204
+ options = webdriver.ChromeOptions()
205
+ options.add_argument("headless")
206
+ options.add_argument("window-size=2500,1200")
207
+
208
+ self.browser = webdriver.Chrome(chrome_options=options)
209
+
210
+ def __del__(self):
211
+
212
+ if self.snap_page:
213
+ self.browser.quit() # close() ?
214
+
215
+ def download(self, file_link): # This gets called externally by the data pipes
216
+
217
+ if file_link is None:
218
+ pass
219
+
220
+ else:
221
+
222
+ self.file_count += 1
223
+ add_prefix = ""
224
+
225
+ if self.file_namer == "FILENAME":
226
+
227
+ trim_file_link = file_link[:file_link.rfind(self.file_ext)+len(self.file_ext)] # Clip name if filelink has parameters after the filename
228
+ file_name = self.prefix + add_prefix + trim_file_link[trim_file_link.rfind("/")+1:] # Extract file name from link
229
+
230
+ else: # defaults to file counter
231
+ file_name = (self.prefix + add_prefix + "%06d" + self.file_ext) % self.file_count
232
+
233
+ # Attempt to download the file but check if we have exceeded the dead link count
234
+
235
+ if (self.dead_links >= self.dead_link_kill and self.last_dead_link == file_link[:file_link.rfind("/")]):
236
+
237
+ #print('ERROR: cDownloader - REASON: Exceeded dead links')
238
+ pass
239
+
240
+ elif os.path.exists(file_name):
241
+ print("WARNING: File exists ",file_name," skipping")
242
+ pass
243
+
244
+
245
+ # Begin download
246
+
247
+ if self.snap_page: # Take a snapshot of the webpage instead of downloading a file
248
+
249
+ self.browser.get(file_link)
250
+ self.browser.save_screenshot(file_name+".png") # always a png ext
251
+ time.sleep(self.pause)
252
+
253
+ else: # download the file
254
+
255
+ try:
256
+ req = Request(file_link)
257
+ req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 AOL/9.8 AOLBuild/4346.2019.US Safari/537.36')
258
+ remotefile = urlopen(req)
259
+
260
+ localfile = open(file_name, 'wb')
261
+ localfile.write(remotefile.read())
262
+ localfile.close()
263
+ remotefile.close()
264
+
265
+ #print("DEBUG - sleep on file download")
266
+ #time.sleep(0.5) # DEBUG
267
+
268
+ self.dead_links = 0 # successful download, reset dead link count to zero
269
+ self.last_dead_link = ""
270
+
271
+ except urllib.error.HTTPError as e:
272
+
273
+ print('ERROR: ',e.code,' REASON: ',e.reason, " => ",file_link) # Url = e.url
274
+
275
+ self.dead_links += 1 # unsuccessful download, add dead link data
276
+ self.last_dead_link = file_link[:file_link.rfind("/")] # root of file attempted
277
+
278
+
279
+
280
+ ## END class cDownloader
281
+
282
+
283
+ # Data Pipe Class
284
+
285
+ class cDataPipe:
286
+
287
+ def __init__(self):
288
+
289
+ self.nLayers = 0
290
+ self.DataPipes = []
291
+
292
+ def new_pipe(self, data_pump):
293
+ self.DataPipes.append([data_input for data_input in data_pump])
294
+
295
+ def end_pipe(self, data_downloader):
296
+ self.nLayers += 1
297
+ self.DataPipes.append([data_downloader(data_input) for data_input in self.DataPipes[self.nLayers-1]])
298
+
299
+ def add_pipe(self, data_processor, c_regex=""):
300
+
301
+ self.nLayers += 1
302
+
303
+ if c_regex == "":
304
+ self.DataPipes.append(self.unique_items(self.flatten([data_processor(data_input) for data_input in self.DataPipes[self.nLayers-1]])))
305
+ else:
306
+ self.DataPipes.append(self.unique_items(self.flatten([data_processor(data_input,c_regex) for data_input in self.DataPipes[self.nLayers-1]])))
307
+
308
+ def output(self):
309
+ return list(self.DataPipes[self.nLayers])
310
+
311
+ def flow(self):
312
+ yield self.DataPipes[self.nLayers]
313
+
314
+ def flatten(self, list_of_lists):
315
+
316
+ flat_list = []
317
+
318
+ try:
319
+ flat_list = list(chain.from_iterable(list_of_lists)) # Note -- this will fail if any item is not an iterable - oth params ??
320
+ except:
321
+ print("ERROR - Non-iterable in flatten chain")
322
+ return []
323
+
324
+ return flat_list
325
+
326
+ def unique_items(self, iterable):
327
+
328
+ seen = set()
329
+
330
+ for element in filterfalse(seen.__contains__,iterable):
331
+ seen.add(element)
332
+ yield element
333
+
334
+
335
+ # ===================
336
+ # Image Processing Functions
337
+ # ===================
338
+
339
+
340
+
341
+
342
+ '''
343
+
344
+ Floyd-Steinberg Dithering Example
345
+ https://scipython.com/blog/floyd-steinberg-dithering/
346
+
347
+ Also see:
348
+
349
+ https://tannerhelland.com/2012/12/28/dithering-eleven-algorithms-source-code.html
350
+ https://en.wikipedia.org/wiki/Ordered_dithering
351
+ https://archive.ph/71e9G
352
+
353
+ Adjusted for ePaper colours - which are 7
354
+
355
+ Supported Colours
356
+
357
+ Brown R - 255 G - 128 B - 0
358
+ Green R - 0 G - 255 B - 0
359
+ White R - 255 G - 255 B - 255
360
+ Black R - 0 G - 0 B - 0
361
+ Red R - 255 G -0 B - 0
362
+ Blue R - 0 G - 0 B - 255
363
+ Yellow R - 255 G 255 B - 0
364
+
365
+ Not Supported (but would be normal 2 channel colours)
366
+
367
+ Purple R - 255 G 0 B - 255
368
+ Turq R - 0 G 255 B - 255
369
+
370
+ '''
371
+
372
+
373
+
374
+ # =================================
375
+ # Constants
376
+ # =================================
377
+
378
+
379
+
380
+ colour_map = [np.array([0,0,0]), # Black
381
+ np.array([255,0,0]), # Red
382
+ np.array([0,255,0]), # Green
383
+ np.array([0,0,255]), # Blue
384
+ np.array([255,255,0]), # Yellow
385
+ np.array([255,128,0]), # Brown
386
+ np.array([255,255,255]), # White
387
+ ]
388
+
389
+ NUMBER_COLOURS = len(colour_map)
390
+
391
+
392
+ # =================================
393
+ # FUNCTIONS
394
+ # =================================
395
+
396
+
397
+ def get_new_val(old_val, nc):
398
+ """
399
+ Get the "closest" colour to old_val in the range [0,1] per channel divided
400
+ into nc values.
401
+
402
+ """
403
+
404
+ return np.round(old_val * (nc - 1)) / (nc - 1)
405
+
406
+ '''
407
+
408
+ Floyd-Steinberg algo dithers the image into a palette with fixed colours per channel
409
+
410
+ F = 1/16 | _ * 7 |
411
+ | 3 5 1 |
412
+
413
+ Stucki
414
+ | * 8 4 |
415
+ = 1/42 | 2 4 8 4 2 |
416
+ | 1 2 4 2 1 |
417
+
418
+ where * is the current pixel
419
+
420
+ '''
421
+
422
+ def fs_dither(img, height=448, width=600):
423
+
424
+ arr = np.array(img, dtype=int)
425
+
426
+ for ir in range(height-1): #new_height):
427
+
428
+ for ic in range(width-1): # new_width):
429
+
430
+ matches = colour_map - np.tile(arr[ir, ic],(NUMBER_COLOURS,1))
431
+ dist_match = np.apply_along_axis(np.linalg.norm,1,matches)
432
+ best_match = np.argmin(dist_match)
433
+ best_colour = colour_map[best_match]
434
+ diff_best = arr[ir,ic] - best_colour
435
+ dist_best = np.linalg.norm(diff_best)
436
+
437
+ # Clamp to best colour
438
+
439
+ arr[ir,ic] = best_colour
440
+
441
+ # Error spread to adjacent pixels
442
+
443
+ if dist_best > 88: # Error threshold to prevent unnecessary dithering - 88 = ~20% error 45 ~ 10% 66 - 15%
444
+
445
+ for factor,ir_d,ic_d in [(7,0,1),(3,1,-1),(5,1,0),(1,1,1)]:
446
+
447
+ arr[ir+ir_d, ic+ic_d][0] = min(arr[ir+ir_d, ic+ic_d][0] + round(diff_best[0] * factor/16,0),255)
448
+ arr[ir+ir_d, ic+ic_d][1] = min(arr[ir+ir_d, ic+ic_d][1] + round(diff_best[1] * factor/16,0),255)
449
+ arr[ir+ir_d, ic+ic_d][2] = min(arr[ir+ir_d, ic+ic_d][2] + round(diff_best[2] * factor/16,0),255)
450
+
451
+
452
+ return Image.fromarray(np.uint8(arr))
453
+
454
+
455
+
456
+ # Create a new white image with the specified dimensions.
457
+ # Load the JPEG image.
458
+ # Rescale the JPEG image to have a height of 448 pixels while maintaining its aspect ratio.
459
+ # Paste the rescaled image onto the white image, aligning it to the left.
460
+
461
+ # from PIL import Image
462
+
463
+ def load_image(input_image):
464
+
465
+ new_image = Image.new("RGB", (600, 448), "white") # Create a new white image with a width of 600 pixels and a height of 448 pixels
466
+
467
+ jpeg_image = Image.open(input_image) # Load the JPEG image
468
+
469
+ aspect_ratio = jpeg_image.width / jpeg_image.height # Rescale the JPEG image to have a height of 448 pixels and calculate the new width to maintain the aspect ratio
470
+ new_height = 448
471
+ new_width = int(aspect_ratio * new_height)
472
+ rescaled_image = jpeg_image.resize((new_width, new_height)) #, Image.ANTIALIAS)
473
+
474
+ new_image.paste(rescaled_image, (0, 0)) # Paste the rescaled image onto the white image, aligning it to the left
475
+
476
+ return new_image
477
+
478
+ # Save or display the result
479
+ # new_image.show() # To display the image
480
+ # white_image.save("output.jpg") # To save the image
481
+
482
+
483
+
484
+ # =================================
485
+ # MAIN PROGRAM
486
+ # =================================
487
+
488
+ '''
489
+
490
+ The display dimensions of the ePaper device is
491
+
492
+ width - 600
493
+ height - 448
494
+
495
+ We need to adjust according
496
+
497
+ TODO - rotate image based on best fit
498
+
499
+ '''
500
+
501
+ # rename files
502
+
503
+ ##input_files = [file.name for file in os.scandir() if file.name[-3:]=="jpg"]
504
+ ##
505
+ ##for idx,input_file in enumerate(input_files):
506
+ ## day_of_year = (idx % 365) + 1
507
+ ## file_number = idx // 365
508
+ ## new_file_name = "%03d%03d.jpg" % (day_of_year, file_number)
509
+ ## print(new_file_name)
510
+ ##
511
+
512
+
513
+
514
+
515
+
516
+ sys.exit()
517
+
518
+
519
+
520
+
521
+
522
+ start_time = dt.now()
523
+ print("Running",start_time)
524
+
525
+ input_files = [file.name for file in os.scandir() if file.name[-3:]=="jpg" and not os.path.exists(file.name[:-3]+"bmp")]
526
+
527
+ for input_image in input_files:
528
+
529
+ print("Processing:",input_image)
530
+
531
+ img = load_image(input_image)
532
+ dim = fs_dither(img)
533
+
534
+ if dim is not None:
535
+ dim.save(input_image[:-3]+"bmp")
536
+ else:
537
+ print("ERROR: No image returned for",input_image)
538
+
539
+
540
+ print("Finished",dt.now()-start_time)
541
+
542
+
543
+
544
+
545
+
546
+
547
+
548
+
549
+
550
+
551
+
552
+
553
+
554
+ '''
555
+
556
+ from PIL import Image
557
+
558
+ # Open the larger calendar image
559
+ calendar = Image.open("calendar.bmp")
560
+
561
+ # Open the smaller weather image
562
+ weather = Image.open("weather.bmp")
563
+
564
+ # Get the dimensions of the calendar image
565
+ calendar_width, calendar_height = calendar.size
566
+
567
+ # Get the dimensions of the weather image
568
+ weather_width, weather_height = weather.size
569
+
570
+ # Calculate the position to paste the weather image
571
+ position = (calendar_width - weather_width, calendar_height - weather_height)
572
+
573
+ # Paste the weather image onto the calendar image at the calculated position
574
+ calendar.paste(weather, position)
575
+
576
+ # Save the modified calendar image
577
+ calendar.save("calendar_with_weather.bmp")
578
+
579
+ # Optionally, show the result
580
+ calendar.show()
581
+
582
+
583
+
584
+
585
+
586
+
587
+
588
+
589
+
590
+
591
+
592
+
593
+
594
+
595
+
596
+
597
+
598
+
599
+
600
+ # test calendar code
601
+
602
+ from datetime import datetime
603
+
604
+ # Get the current date
605
+ current_date = datetime.now()
606
+
607
+ # Extract the current year and month as integers
608
+ current_year = current_date.year
609
+ current_month = current_date.month
610
+
611
+ # Print the year and month
612
+ print("Year:", current_year)
613
+ print("Month:", current_month)
614
+
615
+ current_date = datetime.now()
616
+
617
+ print(current_date.strftime("%A"))
618
+
619
+ print(current_date.strftime("%b %d, %Y"))
620
+
621
+ import calendar
622
+
623
+ yy = 2025
624
+ mm = 1
625
+
626
+ cal = calendar.month(yy, mm)
627
+ cal_lines = cal.split(chr(10))
628
+
629
+ for cal_line in cal_lines[1:]:
630
+ print(cal_line)
631
+
632
+ #print(cal)
633
+ #print(cal_lines)
634
+
635
+ #for char in cal:
636
+ # print(ord(char))
637
+
638
+
639
+
640
+
641
+ # Downloader
642
+
643
+ ##pipe = cDataPipe()
644
+ ##pipe.new_pipe(html_list_iter([r"https://creator.nightcafe.studio/"]))
645
+ ##pipe.add_pipe(get_links,re.compile(r"(https:\/\/images\.nightcafe\.studio\/(?!\/assets)[A-z0-9\/\.\-]*jpg)"))
646
+ ##pipe.add_pipe(pipe_inspector)
647
+ ###pipe.end_pipe(cDownloader(file_namer="COUNTER",file_extension=".jpg").download)
648
+ ##pipe.flow()
649
+ ##
650
+ ##sys.exit()
651
+
652
+
653
+
654
+
655
+
656
+ # width, height = img.size
657
+ #print(img.__dict__) #, width, height)
658
+ #new_width = 600
659
+ #new_height = int(height * new_width / width)
660
+ #img = img.resize((new_width, new_height), Image.ANTIALIAS)
661
+
662
+ def fs_dither_old(img, nc=2):
663
+
664
+ arr = np.array(img, dtype=float) / 255
665
+
666
+ for ir in range(new_height):
667
+
668
+ for ic in range(new_width):
669
+
670
+ # NB need to copy here for RGB arrays otherwise err will be (0,0,0)!
671
+
672
+ old_val = arr[ir, ic].copy()
673
+ new_val = get_new_val(old_val, nc)
674
+ arr[ir, ic] = new_val
675
+ err = old_val - new_val
676
+
677
+ # In this simple example, we will just ignore the border pixels.
678
+
679
+ if ic < new_width - 1:
680
+ arr[ir, ic+1] += (err * 7/16)
681
+ if ir < new_height - 1:
682
+ if ic > 0:
683
+ arr[ir+1, ic-1] += (err * 3/16)
684
+ arr[ir+1, ic] += (err * 5/16)
685
+ if ic < new_width - 1:
686
+ arr[ir+1, ic+1] += (err / 16)
687
+
688
+ carr = np.array(arr/np.max(arr, axis=(0,1)) * 255, dtype=np.uint8)
689
+
690
+ return Image.fromarray(carr)
691
+
692
+
693
+
694
+ '''
weather_icon.bmp ADDED