[CRASH to SUGGESTION] Draw to memory Shape or Image
Posted: April 2nd, 2022, 2:39 pm
I'll spare you of the details of what I want to achieve, but a while ago I found out a way to get the value of all or any pixels in an image, using a simple combination of batch and Python, like this (assuming a [SkinFolder]\@Resources\Image.tif or any other image type exists, of course)...
[SkinFolder]\@Resources\ImagePixelRGB.py:
[SkinFolder]\@Resources\ImagePixelRGB.bat:
which, after running the batch, produces a nice .inc file with the RGB values of all pixels in the image and its resolution as a bonus, similar to...
[SkinFolder]\@Resources\ImagePixelRGB.inc:
With minor editing of the Python code to something like:
and a bit more processing time, one can even get a perfectly valid .inc file like:
that is theoretically, ready to draw in Rainmeter, with a simple code similar to...
[SkinFolder]\ImagePixelRGB.ini:
However, in practice, even though everything is as it's supposed to be, such a skin will crash Rainmeter, due to too many shapes, too much code or something along those lines - so be aware to comment a too large [Foreground] meter content like:
and similar in the case of Lua from the spoiler, to avoid unpleasant surprises. Naturally, all the other ways of drawing such a construct in a skin by automatically building the .inc file using the method above (like using Line shapes with hard stop gradients to simulate pixels, or using 1 px sized Image meters, etc.) will crash as well. Basically, one is not able to draw a "normal" (i.e. larger than an icon sized) image pixel by pixel in Rainmeter.
If you got this far (yeah, I know, it's longer than expected cause I always cover all possibilities, to be sure I'm not halucinating when I say something), this is the point where you may wonder and outright reject any meaningful discussion about it on the grounds that "why don't you just use the Image meter for this" or "Rainmeter was not designed for this" and so on - but the thing is, I considered using these methods because I want to dynamically transform an image in ways that are not possible using the current set of tools available in Rainmeter (this is where I spare you of all the details, like mentioned above). So, forget about those ways to say "no" for a moment and let's focus on ways to possibly say "yes": is or can it be possible to alter specific pixels in an image, or draw an image pixel by pixel using a feasible speed in Rainmeter? And if not, could a "buffer" or "pointer" measure be created for Rainmeter that will do these operations in the very fast RAM/GPU memory and let the user then display the (converted to an image, internally) result in an Image meter?
Thanks, and sorry for taking from your precious time.
[SkinFolder]\@Resources\ImagePixelRGB.py:
Code: Select all
# Needs "pip install pillow" to be run in CMD first, on a new Python installation
from PIL import Image
icon = Image.open('Image.tif')
size = icon.size
data = list(icon.getdata())
print(size, data)
Code: Select all
@echo off
ImagePixelRGB.py > ImagePixelRGB.inc 2>&1
[SkinFolder]\@Resources\ImagePixelRGB.inc:
Code: Select all
(1288, 644) [(12, 16, 29), (7, 10, 25), (4, 8, 22), (4, 7, 22), (3, 7, 22), ... , (242, 242, 242)]
Code: Select all
# Needs "pip install pillow" to be run in CMD first, on a new Python installation
from PIL import Image
icon = Image.open('Image.tif')
size = icon.size
data = list(icon.getdata())
print("[Foreground]")
print("Meter=Shape")
for y in range(0, size[1]):
for x in range(0, size[0]):
print("Shape"+str("" if size[0]*y+x==0 else size[0]*y+x+1)+"=Rectangle "+str(x)+","+str(y)+",1,1 | StrokeWidth 0 | Stroke Color "+str(data[size[0]*y+x][0])+","+str(data[size[0]*y+x][1])+","+str(data[size[0]*y+x][2])+",255")
Code: Select all
[Foreground]
Meter=Shape
Shape=Rectangle 0,0,1,1 | StrokeWidth 0 | Stroke Color 12,16,29,255
Shape2=Rectangle 1,0,1,1 | StrokeWidth 0 | Stroke Color 7,10,25,255
Shape3=Rectangle 2,0,1,1 | StrokeWidth 0 | Stroke Color 4,8,22,255
...
Shape829472=Rectangle 1287,643,1,1 | StrokeWidth 0 | Stroke Color 242,242,242,255
[SkinFolder]\ImagePixelRGB.ini:
Code: Select all
[Variables]
[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
---Meters---
[Background]
Meter=Shape
Shape=Rectangle 0,0,1288,644 | Fill Color 0,0,0,255 | Stroke Color 255,0,0,255 | StrokeWidth 1
UpdateDivider=-1
[Foreground]
@IncludeForeground=#@#Foreground.inc
UpdateDivider=-1
Code: Select all
[Foreground]
; @IncludeForeground=#@#Foreground.inc
If you got this far (yeah, I know, it's longer than expected cause I always cover all possibilities, to be sure I'm not halucinating when I say something), this is the point where you may wonder and outright reject any meaningful discussion about it on the grounds that "why don't you just use the Image meter for this" or "Rainmeter was not designed for this" and so on - but the thing is, I considered using these methods because I want to dynamically transform an image in ways that are not possible using the current set of tools available in Rainmeter (this is where I spare you of all the details, like mentioned above). So, forget about those ways to say "no" for a moment and let's focus on ways to possibly say "yes": is or can it be possible to alter specific pixels in an image, or draw an image pixel by pixel using a feasible speed in Rainmeter? And if not, could a "buffer" or "pointer" measure be created for Rainmeter that will do these operations in the very fast RAM/GPU memory and let the user then display the (converted to an image, internally) result in an Image meter?
Thanks, and sorry for taking from your precious time.