Code: Select all
[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1
[Metadata]
Name=ImageSize
Author=JSMorley
Information=Demonstrates ImageSize plugin.||Set ImageName to the path and name of an image file.|Set Dimension to either "Width" or "Height".
License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0
Version=Feb 18, 2019
[Variables]
ImageName=#@#Images\laughing.jpg
[MeasureWidth]
Measure=Plugin
Plugin=ImageSize
ImageName=#ImageName#
Dimension=Width
UpdateDivider=-1
[MeasureHeight]
Measure=Plugin
Plugin=ImageSize
ImageName=#ImageName#
Dimension=Height
UpdateDivider=-1
[MeterImage]
Meter=Image
ImageName=#ImageName#
W=200
PreserveAspectRatio=2
[MeterDimensions]
Meter=String
Y=3R
MeasureName=MeasureWidth
MeasureName2=MeasureHeight
FontSize=13
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=Meter Size: [MeterImage:W] X [MeterImage:H]#CRLF#Image Size: %1 X %2
DynamicVariables=1
A note on "efficiency" with this plugin
This plugin will only read and measure the file in the Reload() function of the plugin, and not on every Update() of the measure. This is to eliminate reading the file from disk on every update of the measure, when the file doesn't change. On each update of the measure, the existing value is just returned.
Reload() is only called when the skin is loaded or refreshed, or on each update when a measure is made "dynamic".
In order to change the file name dynamically, and fire Reload() again, I strongly recommend that you don't just use ImageName=[MeasureName] and DynamicVariables=1, or ImageName=#VariableName# and DynamicVariables=1. Using DynamicVariables on the measure will force Reload() to be called on each update of the measure, and that will be inefficient. What you want to do is have FinishAction on WebParser measures or OnChangeAction on other types of measures, and use !SetOption to set the ImageName option on the plugin measure. The use of !SetOption will force Reload() to be called just one time on the next update.
So the key to efficiency with this plugin is not so much using UpdateDivider=-1 on the measure, that's ok, but it doesn't have a large impact. The key is for YOU to control things when you dynamically change the ImageName value on the measure.
So that's all a little "inside baseball", and to be honest, no matter how you do things the plugin is reasonably efficient, as Windows itself will cache "reads" of a file and it won't ever just hammer your hard drive even if you do evaluate the image file on every update. But it never hurts to fine-tune things as much as possible.
Plugin code:
Code: Select all
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Drawing;
using Rainmeter;
namespace PluginImageSize
{
class Measure
{
static public implicit operator Measure(IntPtr data)
{
return (Measure)GCHandle.FromIntPtr(data).Target;
}
public IntPtr buffer = IntPtr.Zero;
public IntPtr rm = IntPtr.Zero;
public double width, height;
public Bitmap ImageBitmap;
public string ImageName;
public string Dimension;
public bool fileErrorShown = false;
public bool dimErrorShown = false;
}
public class Plugin
{
[DllExport]
public static void Initialize(ref IntPtr data, IntPtr rm)
{
data = GCHandle.ToIntPtr(GCHandle.Alloc(new Measure()));
Measure measure = (Measure)data;
Rainmeter.API api = (Rainmeter.API)rm;
measure.rm = rm;
}
[DllExport]
public static void Reload(IntPtr data, IntPtr rm, ref double maxValue)
{
Measure measure = (Measure)data;
Rainmeter.API api = (Rainmeter.API)rm;
measure.width = 0.0;
measure.height = 0.0;
measure.ImageName = api.ReadString("ImageName", "");
measure.Dimension = api.ReadString("Dimension", "WIDTH").ToUpper();
int isDisabled = api.ReadInt("Disabled", 0);
int isPaused = api.ReadInt("Paused", 0);
if (isDisabled == 0 && isPaused == 0)
{
try
{
measure.ImageBitmap = new Bitmap(@measure.ImageName, true);
measure.width = measure.ImageBitmap.Width;
measure.height = measure.ImageBitmap.Height;
measure.ImageBitmap.Dispose();
measure.fileErrorShown = false;
}
catch
{
if (!measure.fileErrorShown)
{
api.Log(API.LogType.Error, "ImageSize.dll: File error for " + measure.ImageName);
measure.fileErrorShown = true;
}
}
}
}
[DllExport]
public static double Update(IntPtr data)
{
Measure measure = (Measure)data;
Rainmeter.API api = (Rainmeter.API)measure.rm;
if (measure.Dimension == "WIDTH")
{
measure.dimErrorShown = false;
return measure.width;
}
else if (measure.Dimension == "HEIGHT")
{
measure.dimErrorShown = false;
return measure.height;
}
else
{
if (!measure.dimErrorShown)
{
api.Log(API.LogType.Error, "ImageSize.dll: Dimension option " + measure.Dimension + " invalid");
measure.dimErrorShown = true;
}
return 0.0;
}
}
[DllExport]
public static void Finalize(IntPtr data)
{
Measure measure = (Measure)data;
if (measure.buffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(measure.buffer);
}
GCHandle.FromIntPtr(data).Free();
}
}
}
Edit: February 18, 2019: Version 4.0 released to fix an issue where the plugin measure would not respond properly to being "Disabled" or "Paused".
Edit: July 4, 2015: Version 3.0 released to fix an issue where a dynamic change to the image being measured from a valid to an invalid image name would not reset the width and height parameters to "0".