It is currently July 14th, 2024, 3:09 pm

Background margins and scaling

Report bugs with the Rainmeter application and suggest features.
User avatar
Yincognito
Rainmeter Sage
Posts: 7723
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Background margins and scaling

Post by Yincognito »

Image:
Background.png
Skin:

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1
BackgroundMode=3
Background=#@#Background.png
BackgroundMargins=1,1,1,1

---Meters---

[Text]
Meter=String
X=150
Y=150
W=300
H=300
FontColor=255,255,255,255
FontFace=Tahoma
FontSize=16
Padding=5,5,5,5
AntiAlias=1
StringAlign=CenterCenter
Text=Background Margins
Result:
Background Margins - Result.jpg
Expected:
Background Margins - Expected.jpg
Is this intentional or a bug? I mean, for the code above, there should be only 1 pixel margin that is not scaled and this is clearly not the case. The background margins need to be set 2 pixels wide (the expected image) to get what should be achieved for 1 pixel wide margins (the result image). Yeah, I know, it sounds crazy to mention a 1 pixel issue in this day and age, but widening the margins decreases the available space for other stuff in the skin, and in some cases this does matter (a similar unwanted effect of enlarging the skin is when adding a blank margin to the image and widening the background margins to 3 pixels). :confused:

P.S. Possible backward compatibility issues on fixing, if you count adjusting margins by 1 pixel as an issue.
You do not have the required permissions to view the files attached to this post.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Brian
Developer
Posts: 2705
Joined: November 24th, 2011, 1:42 am
Location: Utah

Re: Background margins and scaling

Post by Brian »

Hmmm, yeah this a bug.

The issue is the "interpolation" mode when drawing images. Back in the GDI+ days, the unit of measurement was a pixel (or UnitPixel in GDI terms) when drawing images to the screen. Now, since D2D mostly utilizes "device independent pixels", the interpolation setting needs to explicitly set on every image draw. We defaulted to a "high quality cubic" setting to achieve the best possible image quality. Obviously this interpolation mode samples parts of the image "beyond" the defined bounds....at least when scaling.

This is also why you cannot achieve a scaled "pixel art" image with Rainmeter at this time.

This will be fixed for the next version.

-Brian

Edit: Turns out there were similar issues with the GDI+ version in older Rainmeter versions as well. While I can fix it, there may be some backwards-compatibility issues since smaller images would become more pixelated when scaled. I'm thinking a new option might be in order. While I had plans to make a new option for all meters that would address this issue, I may instead add an image option for those meters (and Background) to control the interpolation of the image.
User avatar
Yincognito
Rainmeter Sage
Posts: 7723
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Background margins and scaling

Post by Yincognito »

Sounds good, and it makes sense. I was trying to prepare a pleasant surprise for you and eventually couple the bevel thing in the other thread with fixing this one in an (undefined) future PR, by attempting to adjust the margins coordinates in the scaled image part of the redraw function from the source code, but it didn't seem to make a difference and I was wondering why. What you said explains that.

Since we're at it, I noticed that for bigger dimensions of the background there seem to be interpolation differences between scaled images and equivalent Shape meters, i.e. noticeable "edges" between the gradual tones of a gradient, for example. This isn't a big problem, but it was enough of an issue to convince me to make the source image (aka the image to be scaled) literally made of lines approximating the gradient, which seem to alleviate those less smooth and at times irregular "transitions" between the tones of a gradient. Not necessarily saying it needs fixing as some things are not under the developer's control, I just thought you should know about it.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Yincognito
Rainmeter Sage
Posts: 7723
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Background margins and scaling

Post by Yincognito »

By the way, an easier solution might be possible here. Like I said, the interpolation itself might be the cause of it, but it isn't the real problem. I don't mind setting the margins to be N+1 (in this case, 2), the problem is that the said 1 takes a total of 2 pixels from the available skin size. So, if this can be accounted for (well, actually unaccounted for, so that those 2 pixels are available to the skin designer) then problem solved, no backwards compatibility issues, no additional code or work needed, etc.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Brian
Developer
Posts: 2705
Joined: November 24th, 2011, 1:42 am
Location: Utah

Re: Background margins and scaling

Post by Brian »

Yincognito wrote: July 21st, 2023, 4:13 pm Since we're at it, I noticed that for bigger dimensions of the background there seem to be interpolation differences between scaled images and equivalent Shape meters, i.e. noticeable "edges" between the gradual tones of a gradient, for example. This isn't a big problem, but it was enough of an issue to convince me to make the source image (aka the image to be scaled) literally made of lines approximating the gradient, which seem to alleviate those less smooth and at times irregular "transitions" between the tones of a gradient. Not necessarily saying it needs fixing as some things are not under the developer's control, I just thought you should know about it.
This might have to do with anti-aliasing since we don't provide that option for Background images, but not sure. Could you post a simple test skin showing the differences in "edges"?


Yincognito wrote: July 21st, 2023, 5:10 pm By the way, an easier solution might be possible here. Like I said, the interpolation itself might be the cause of it, but it isn't the real problem. I don't mind setting the margins to be N+1 (in this case, 2), the problem is that the said 1 takes a total of 2 pixels from the available skin size. So, if this can be accounted for (well, actually unaccounted for, so that those 2 pixels are available to the skin designer) then problem solved, no backwards compatibility issues, no additional code or work needed, etc.
I'm not sure if your saying that internally we can just manually adjust by 1 to account for the this, or if the skin author can do it by adjusting it in their skin. Either way, I don't think it will work in all cases, especially on scaled images where differing colors are directly adjacent to the defined margins.

The root of the issue is the sampling of scaled data from a relatively small image. The center-most part of the image (the non-BackgroundMargins part) is sampling the entire image instead of just defined rectangle to be drawn. The most proper fix would be to create an entire new image for every section of that is to be drawn, so that any sampling while scaling does not use portions outside of its defined section. If that makes sense.

But...that might create a performance issue. Creating (and possibly caching) 9 different sections (4 corners, 4 borders, and center image) of a scaled image just to get it exact might be somewhat overkill for this. Especially if that background image changes on every update. Having an interpolation option for images will give us at least 6 different options. Nearest Neighbor, Linear, Cubic, Multi-Sample Linear, Anisotropic, and High Quality Cubic (what we use now). Here is a link to their description.



Just some quick testing, use a modified version of your original image:
Background_1.png
Note the little green dots.

Rainmeter 4.0 produced this:
Rainmeter_4.0.0.png
Wow, that is really bad on this small of an image. I suspect the image size was a major issue. The image coordinates seem off as well. Oh well, obviously some of that has been fixed.


Current release Rainmeter 4.5.17 (High Quality Cubic):
Rainmeter_4.5.17.png
This is usually provides the best image quality, but obviously samples the entire image instead of the defined rectangle drawn.


"Nearest Neighbor" method of interpolation (you might have open this in a new tab/window to see the border):
Rainmeter_Latest_NearestNeighbor.png
Provides the best "border", but center-most image is pixelated. This is probably what most users would use for "stretched border" effect that BackgroundMargins was originally designed for.


"Linear":
Rainmeter_Latest_Linear.png
Seems to sample in horizontal and vertical directions.


"Cubic":
Rainmeter_Latest_Cubic.png
Similar to "High Quality Cubic". Might have different results in more complex images.


"Multi-Sample Linear":
Rainmeter_Latest_MultiSampleLinear.png
Similar to "Linear".


"Anisotropic":
Rainmeter_Latest_Anisotropic.png
Similar to "Linear". Might be different on transformed images which is not done for the Background option.


The small modified image might not be the best to demonstrate all the differences in interpolation. Setting anti-aliasing on this might have some effects as well.

But anyway....this all might be overkill. Getting this "perfect" might just be sacrificing resources and time. We could go the route of creating a 9 new images to prevent sampling outside of the drawn rectangle (or maybe just 1 of the center-most image), or we could provide this interpolation option for all meters that use images (and the Background option)....but, in my opinion, I think manipulating the coordinates is the wrong way to do this. Not sure what other options we have.

-Brian
You do not have the required permissions to view the files attached to this post.
User avatar
Yincognito
Rainmeter Sage
Posts: 7723
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Background margins and scaling

Post by Yincognito »

Brian wrote: July 21st, 2023, 8:20 pmCould you post a simple test skin showing the differences in "edges"?
Sorry, my non-native English failed here. What I meant was there is irregular / sinusoidal color banding when the image is built using a gradient, while when replicating the gradient using lines, the color banding is at least regular, i.e. following straight lines.

Test skin:

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1
BackgroundMode=3
Background=#@#Background - Gradient.png
BackgroundMargins=2,2,2,2
SkinWidth=600
SkinHeight=600

---Meters---

[Image]
Meter=Image
X=1
Y=1
W=10
H=10
SolidColor=255,0,0,255
Resources (1st: using gradient; 2nd: using lines; 3rd: the .psd source):
Background - Gradient.png
Background - Lines.png
Background.zip

Results (1st: using gradient; 2nd: using lines; best viewed when over a dark theme background, like the one in Notepad++, Photoshop, or Chrome):
Gradient - Bands.png
Lines - Bands.png
The sinusoidal banding can be noticed towards the middle right and towards the bottom of the 1st preview. That being said, I was remembering this the wrong way, it's not Rainmeter's fault, it's Photoshop's, and the scaling done by Rainmeter simply emphasizes it. For some reason, even though I set up the gradient correctly at a 90 degrees angle, the banding turns out sinusoidal and not straight. Anyway, not a big deal, considering there is a solution, at least for small images like in my case (this is my actual scenario).
Brian wrote: July 21st, 2023, 8:20 pmI'm not sure if your saying that internally we can just manually adjust by 1 to account for this.
Something like that, but not quite. Comment out the SkinWidth and SkinHeight lines in the above code, and refresh the skin. What will happen is something like this, that I can see in Photoshop on magnifying stuff:
Background.png
Notice how the W and H of the selected skin area are both 13 pixels. Now, normally, if the posted issue would not be present, I'd go with a background margin of 1 pixel all around, and end up with a nice 10 x 10 pixels red square having the 1 pixel faded bevel (the equivalent of the 0.5 wide bevel mentioned in the other somewhat related thread) adjacent to the square on all sides, giving a total of 12 x12 pixels skin.

However, since a background margin of 1 causes the earlier interpolation (and because using a Shape background requires additional meter toggling and redraws, and because the standard bevel can't be less than 2 pixels wide, i.e. all my possible 3 avenues are cut short by various drawbacks, at least until I'll rework the bevel thing as you advised), I have to use a 2 pixel margin, which increases the skin size to 13 x 13 pixels (not sure why 13 and not 14, since 10 + 2 + 2 = 14, but anyway) of which I can't use the right and bottom 1 pixel wide area seen above between the red square and the dark part of the bevel.

The idea I referred to earlier was to not bother touching the color related stuff in this case (irrespective if you add the interpolation option eventually or not) and just make that part available for drawing, or, even better, not increase the skin size by it to begin with. It seems to me that while the top left part which is reserved for the margin is curiously available for drawing here, i.e. I can put the square at 0,0 and not cause the skin to enlarge from the desired 12 pixels to 13, the bottom right part is not and "steals" pixels from the available drawing area for the user. You can try to set the margin to 10 pixels and place the square at 5,5 to better see what I mean.
Brian wrote: July 21st, 2023, 8:20 pmThe center-most part of the image (the non-BackgroundMargins part) is sampling the entire image instead of just defined rectangle to be drawn.
Ah. This. Indeed.
Brian wrote: July 21st, 2023, 8:20 pmJust some quick testing, use a modified version of your original image:
Very nice showcasing and explanation, I appreciate it. Unfortunately, as you said, the nearest neighbour variant, while producing the desired margin / bevel, will probably pixelate the gradient...
Brian wrote: July 21st, 2023, 8:20 pmThe small modified image might not be the best to demonstrate all the differences in interpolation.
Yes, but it's excellent to demonstrate where those interpolations might not give the expected result.
Brian wrote: July 21st, 2023, 8:20 pmNot sure what other options we have.
Well, there are always options, just not always feasible, of course.
You do not have the required permissions to view the files attached to this post.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth