It is currently March 19th, 2024, 6:50 am

ImageSize 4.0

Plugins and Addons popular with the Community
User avatar
jsmorley
Developer
Posts: 22632
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

ImageSize 4.0

Post by jsmorley »

Sometimes it can be useful to know the size of an image file that you are using in an image meter in Rainmeter. The following little plugin will return the pixel size in Width or Height of a defined image:

ImageSize_Feb 18, 2019.rmskin
(75.47 KiB) Downloaded 641 times

PluginImageSize.zip
(7.72 KiB) Downloaded 529 times

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
ImageSize.jpg


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".
User avatar
jsmorley
Developer
Posts: 22632
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ImageSize

Post by jsmorley »

Someone asked about scaling an image by half in another thread, and this plugin might be the best way to do that.

Get the plugin from the first post in this thread, and then:

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1

[Variables]
ImageName=#@#Images\500x200.jpg

[MeasureWidth]
Measure=Plugin
Plugin=ImageSize
ImageName=#ImageName#
Dimension=Width
UpdateDivider=-1

[MeterHalfSizeImage]
Meter=Image
ImageName=#ImageName#
W=([MeasureWidth]/2)
PreserveAspectRatio=1
DynamicVariables=1
2014-07-21_094242.jpg
User avatar
Dank420
Posts: 145
Joined: April 3rd, 2013, 1:04 am
Location: O-High-O

Re: ImageSize

Post by Dank420 »

nice , added functionality for picture skins, i use one to set wallpaper and this will help decide between, fit, stretch, center , what have you... thanks
User avatar
jsmorley
Developer
Posts: 22632
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ImageSize

Post by jsmorley »

There is also a way to do this without using the plugin. You need to load the unscaled image in question into an Image meter, then you can use the [MeterName:W] and / or [MeterName:H] in a formula as you wish.

Note the huge negative X and Y values on the meter loading the image. This is to stick the image someplace outside of any possible bounds of the screen(s) so there is no impact on "Stay on Screen" or "Snap to Edges" settings on the skin.

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1

[Variables]
ImageName=#@#Images\500x200.jpg

[MeterFileImage]
Meter=Image
X=-100000
Y=-100000
ImageName=#ImageName#
ImageAlpha=0
UpdateDivider=-1

[MeterHalfImage]
Meter=Image
ImageName=#ImageName#
W=([MeterFileImage:W]/2)
PreserveAspectRatio=1
DynamicVariables=1
suixin812
Posts: 13
Joined: November 19th, 2012, 5:28 am
Location: China

Re: ImageSize

Post by suixin812 »

There is another plugin called PicInfo can return the size of an image file.

Code: Select all

[GetWidth]
Measure=Plugin
Plugin=PicInfo
ImagePath=a.png
Type=Width

[GetHeight]
Measure=Plugin
Plugin=PicInfo
Parent=GetWidth
Type=Height

[Info]
Meter=String
MeasureName=GetWidth
MeasureName2=GetHeight
Text=Width  is: %1px #CRLF#Height is: %2px
FontSize=20
FontColor=255,255,255,200
FontEffectColor=0,0,0,150
StringEffect=Shadow
AntiAlias=1
Attachments
PicInfo.rar
(18.09 KiB) Downloaded 387 times
User avatar
moshi
Posts: 1740
Joined: November 13th, 2012, 9:53 pm

Re: ImageSize

Post by moshi »

both could be pretty useful with the new mask feature.

for the use with photos UseExifOrientation=1 would be essential though.

just in case, here are two images for testing purposes:
https://yadi.sk/i/tEiz7BFDbAF8E
https://yadi.sk/i/N2YHWan-bAFHg

yes, i know how to work around this with either a dummy meter or exiftool, but then the plugins would be pointless. :)
User avatar
jsmorley
Developer
Posts: 22632
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ImageSize

Post by jsmorley »

Fixed an issue with the plugin in the .rmskin and .zip in the first post of this thread.

The plugin was not properly reacting to a dynamic change of ImageName from a valid to an invalid image name, and was not resetting the values to "0" when this happened.
User avatar
rm_lion
Posts: 93
Joined: December 27th, 2013, 4:04 pm
Location: Switzerland

Re: ImageSize

Post by rm_lion »

I installed Windows 10 and the newest Version of Rainmeter.
Now the PicInfo.dll doesn't work anymore. I allways get the following error:
Plugin: Unable to load "PicInfo" (error 126)
The Plugin is in the correct Folder and it is listed in Rainmeter.
Can anyone help. Or did anyone have the same Problem?

I am using this plugin for my dynaWebcam Skin. I also tried the ImageSize.dll but with this one I allways did get error messages which i didn't with the PicInfo.dll.
drakulaboy
Posts: 165
Joined: June 29th, 2014, 8:35 pm

Re: ImageSize

Post by drakulaboy »

rm_lion wrote:I installed Windows 10 and the newest Version of Rainmeter.
Now the PicInfo.dll doesn't work anymore.
strange, i'm on Win 10 too, on 10532 Insider Preview, the skin is working fine, no errors
User avatar
rm_lion
Posts: 93
Joined: December 27th, 2013, 4:04 pm
Location: Switzerland

Re: ImageSize

Post by rm_lion »

It works again.
Installed the newest driver for the gpu.
Post Reply