"Smart" image sizing in viewer

Is there a "smart" sizing option for the image viewer, or if not can we have one please?

I recently upgraded to a 4k monitor and now some images are rather small. Normally I use "fit to page" scaling but what I'm looking for is a minimum size as well. E.g. if the image is less than say 500 pixels in any one dimension it automatically get scaled up to 2x.

I know there is "grow to page" but I don't really want images scaled up all the time, only very small ones.

Not built-in. You could make a script which decides when / how much to zoom using those rules if you wanted to.

Thanks. Any hints on where to start with a script like that?

FWIW I think this would be a good feature. Some other apps have it, e.g. Media Player Classic and derivatives have an "auto size" mode.

A script which does things after files load in the viewer: Viewer Select - Make file display track standalone viewer

1 Like

Thanks Leo. From my understanding you can't have a script run when the image in the viewer is first opened or changes though, so you can't use it to override the selected zoom level that way.

The script I linked to does that.

Sorry, yes it does. So I am looking at how to implement this. With OnViewerEvent you get a Viewer object, but looking at it there isn't any information about the image dimensions or the current zoom level.

https://www.gpsoft.com.au/help/opus12/index.html#!Documents/Scripting/Viewer11.htm

It looks like the image dimensions could be captured from a custom Viewer window title, but that still leaves the current zoom level. When the level is set to 100% I don't want it to change it, only toggle between "auto fit" and "200%" as needed.

Essentially what I want is a new sizing mode that is like auto fit but also has a minimum size, while not interfering with other zoom levels as selected by the user.

function OnInit(initData)
{
	initData.name = "Test";
	initData.default_enable = true;
}

function OnViewerEvent(viewerEventData)
{
	if (viewerEventData.event == "load")
	{
		var viewer = viewerEventData.viewer;
		var item = viewer.current;
		var meta = item.metadata;

		if (meta == "image")
		{
			DOpus.Output(item.name + ": " + meta.image.picwidth + " x " + meta.image.picheight);
		}
	}
}
1 Like

Thanks, that's helpful. It's the zoom level that is the main issue though, I don't think there is a solution.

For now I'll have to do it manually with hotkeys.

You can use command.IsSet to see if a button for a command would appear active, which includes commands like "zoom 100%".

https://www.gpsoft.com.au/help/opus12/index.html#!Documents/Scripting/Command.htm

1 Like

Ah, thanks, that may just do it! I'll work on the script when I have time. Thanks for the support.

1 Like

I'm having trouble getting the test to work. I tried this:

var cmd = DOpus.Create.Command();
if (cmd.IsSet("Show","VIEWERCMD=zoom,fit"))

But it always evaluates to false. I tried zoom,100 and a few other things, none of them seem to work.

Is creating a command this way the right way to do it? It seems like unlike the OnClick event you don't get a Command passed in, you have to make one and when I look at sourcetab it's not been set, so I'm wondering if that is the issue. I couldn't see a way to associate the Command with the Viewer.

BTW I'm on the latest Opus 12.21 x64, for some reason it's not linked to my account.

You're right. It's harder than I thought to test viewer state from scripts at the moment. (I'll put this on the list of things to improve.)

There is a workaround if you only need to run different commands in reaction to different states. In that case, you can pass the viewer a list of commands (in the Command object you already have) which it will run from its own context:

function OnInit(initData)
{
	initData.name = "Test";
	initData.default_enable = true;
}

function OnViewerEvent(viewerEventData)
{
	if (viewerEventData.event == "load")
	{
		var viewer = viewerEventData.viewer;
		var cmd = DOpus.Create.Command();
		cmd.AddLine("@if:Show VIEWERCMD=zoom,fit");
		cmd.AddLine("Help ABOUT"); // Command you want to run if it was in Fit mode.
		cmd.AddLine("@if:Show VIEWERCMD=zoom,reset");
		cmd.AddLine("Help LICENCEMANAGER"); // Command you want to run if it was in 100% zoom mode.
		viewer.Command(cmd);
	}
}

That works from a quick test. (Shows the About dialog if in Fit mode and the Licence Manager dialog if in 100% zoom ("reset") mode. Nothing special about the two dialogs; they're just useful for testing stuff like this by seeing which one opens.)

2 Likes

Thanks, nearly there. I have incorporated a bit of logic but the Show command doesn't seem to work reliably. If I do Show VIEWERCMD=zoom,grow it works but Show VIEWERCMD=zoom,200, Show VIEWERCMD=zoom,+ and Show VIEWERCMD=zoom,+200 don't have any effect.

function OnViewerEvent(viewerEventData)
{
	if (viewerEventData.event == "load")
	{
		var viewer = viewerEventData.viewer;
		var item = viewer.current;
		var meta = item.metadata;

		if (meta == "image")
		{
			DOpus.Output(item.name + ": " + meta.image.picwidth + " x " + meta.image.picheight);
			
			if ((meta.image.picwidth < 960) && (meta.image.picheight < 960))
			{
				DOpus.Output("logic");
				var cmd = DOpus.Create.Command();
				cmd.AddLine("@if:Show VIEWERCMD=zoom,fit");
				cmd.AddLine("Show VIEWERCMD=zoom,+");
				cmd.AddLine("@if:Show VIEWERCMD=zoom,reset");
				cmd.AddLine("Show VIEWERCMD=zoom,200");
				viewer.Command(cmd);
			}
		}
	}
}

Well there is one other issue but I think I know how to solve it. I need to set a persistent variable to remember the previous state for when the next image is opened. Seems like the only way to do that is to Run another script that sets the Var.

They seem to work on their own, at least here. For example, this zooms to 200% after each image is loaded:

function OnInit(initData)
{
	initData.name = "Test";
	initData.default_enable = true;
}

function OnViewerEvent(viewerEventData)
{
	if (viewerEventData.event == "load")
	{
		var viewer = viewerEventData.viewer;
		var cmd = DOpus.Create.Command();
		cmd.AddLine("Show VIEWERCMD=zoom,200");
		viewer.Command(cmd);
	}
}

I haven't tried more complex logic, but maybe the problem is in which commands are being run, not the commands not working?

I couldn't work out a good way to set a variable based on the viewer's current zoom state, unfortunately.

Sorry, I meant to reply to that earlier. The forum should automatically update the version number if you upgrade your old licence, but if you instead buy a completely new licence then it won't notice that. If you've got two separate licences like that, let me know and I can unlink your account, which will then let you link it to the newer licence.

Thanks for all your help Leo. This script seems to do the trick, needs more extensive testing but so far seems to work as desired.

  • Images under the minimum size of 960x960 are scaled to 200% when the previous mode was either "fit" or "100%".
  • When opening a new image if it is over the minimum size the zoom level is restored to "fit" or "100%" as previously set.
// Viewer Auto Size
// 

function OnInit(initData)
{
	initData.name = "Viewer Auto Size";
	initData.version = "1.0";
	initData.copyright = "GPLv3";
	initData.desc = "Automatically scale up viewer window for very small images";
	initData.default_enable = true;
	initData.min_version = "12.0";
}

function OnViewerEvent(viewerEventData)
{
	if (viewerEventData.event == "load")
	{
		var viewer = viewerEventData.viewer;
		var item = viewer.current;
		var meta = item.metadata;
		var varName = "PreviousZoomLevel";

		if (meta == "image")
		{
			if ((meta.image.picwidth < 960) && (meta.image.picheight < 960))
			{
				// see if we need to save the old state
				if (!DOpus.Vars.Exists(varName))
				{
					var cmd = DOpus.Create.Command();
					cmd.AddLine("@if:Show VIEWERCMD=zoom,fit");
					cmd.AddLine("@set glob:PreviousZoomLevel=fit");
					cmd.AddLine("@if:Show VIEWERCMD=zoom,reset");
					cmd.AddLine("@set glob:PreviousZoomLevel=reset");
					viewer.Command(cmd);
				}

				// scale image up
				var cmd = DOpus.Create.Command();
				cmd.AddLine("@if:Show VIEWERCMD=zoom,fit");
				cmd.AddLine("Show VIEWERCMD=zoom,200");
				cmd.AddLine("@if:Show VIEWERCMD=zoom,reset");
				cmd.AddLine("Show VIEWERCMD=zoom,200");
				viewer.Command(cmd);
			}
			
			else
			{
				// restore old state if it exists
				if (DOpus.Vars.Exists(varName))
				{
					var val = DOpus.Vars.Get(varName);
					var cmd = DOpus.Create.Command();
					if (val == "fit")
					{
						cmd.AddLine("Show VIEWERCMD=zoom,fit");
					}
					else if (val == "reset")
					{
						cmd.AddLine("Show VIEWERCMD=zoom,reset");
					}
					viewer.Command(cmd);
					DOpus.Vars.Delete(varName);
				}
			}
		}
	}
}
1 Like