This question is answered.


Permlink Replies: 17 - Pages: 2 [ 1 2 | Next ] - Last Post: 15 Feb 21, 10:30 Last Post By: davidekholm Threads: [ Previous | Next ]
palthe

Posts: 16
Registered: 27-Dec-2009
How to change maxThumbWidth for individual images progammatically
Posted: 21 Jan 21, 20:25
 
  Click to reply to this thread Reply
Attachment screenshot-3.png (214.6 KB)
Attachment screenshot-2.png (405.8 KB)
Attachment screenshot-1.png (294.3 KB)
I have a skin with a main page and sub-pages.
Via Settings > Images I set the image bounds for thumbnails to: 120x120.
I also add the FixedShapeFilter for thumbnails (in init.bsh).
This results in square, equal height thumbnails which align nicely. See screenshot 1.

But sometimes I want the thumbnails on the main page (and only there) to have equal height while retaining their original aspect ratio.

Initially I did this by adding manually two user-variables to each image in the root folder (via the image edit-screen):

  • excludeFilters = FixedShapeFilter
  • maxThumbWidth = 500
(I need the second variable, to make sure that portrait- and landscape-thumbnails get the same height.)

This works as I wanted. See screenshot 2 and my actual album.

But this is no very practical, so I thought I could do this automatically via some code.
After plowing through this forum I created the following in init.bsh:

//	Add two user-variables to all items in the root-folder.
//	This prevents Fixed-Shape cropping of thumbnails on the main page.
//	These thumbnails are scaled to equal height and keep the original aspect-ratio.
 
	void addUserVars(AlbumObject folder) {
		for (AlbumObject ao : folder.getChildren()) {
			if (!ao.isFolder()) {
				imgUserVars = ao.getVars().get("userVariables");
				imgUserVars.put("excludeFilters", "FixedShapeFilter");
				imgUserVars.put("maxThumbWidth", "500");
				System.out.println(" - " + ao.getName());
				System.out.println("- User variables: " + imgUserVars.toString());
				System.out.println(engine.getThumbSize());
			}
		}
	}
 
	if (ThumbFixedShape) {
		// Crop thumbnails to fit the 'image bounds' as set for thumbnails, before scaling
		engine.addFilter(new FixedShapeFilter(), JAFilter.THUMBNAILS_PRESCALE_STAGE);
	}
	if (ThumbExcludeMain) {
		// Exclude main page thumbnails from cropping
		addUserVars(rootFolder);
	}

ThumbFixedShape and ThumbExcludeMain are variables from the skin-settings.

This only works partlally: the FixedShapeFilter is not used for the main-page thumbnails :-), but the maxThumbWidth = 500 is not applied :-(. See screenshot 3.

In the System Console I see that both user-variables are added (ignore the dummy=1):
image - dscn0610.jpg
- User variables: {dummy=1, excludeFilters=FixedShapeFilter, maxThumbWidth=500}
120x120

What is wrong/missing in my code and how can I solve this?

Maybe the solution is hidden somewhere in this post, but it is beyond my very limited programming skills to find it. I'm more a CPTE-programmer...

(CPTE = Copy, Paste, Trial and Error)

Edited by: palthe on 21-Jan-2021 20:30

Edited by: RobM on 22-Jan-2021 09:35
Removed control character from link which was stopping it working.
JeffTucker

Posts: 8,037
Registered: 31-Jan-2006
Re: How to change maxThumbWidth for individual images progammatically
Posted: 22 Jan 21, 00:23   in response to: palthe in response to: palthe
 
  Click to reply to this thread Reply
You're almost there. What you've got is probably actually working better than you suspect!

After making the album, open the output directory, and check the actual dimensions of the thumbnails at the top level. I think you'll discover that the ones that you've tagged with excludeFilters and maxThumbWidth are, indeed, not square.

I suspect the problem is with your index page layout. If you're relying on thumbWidth and thumbHeight, you'll find that the jAlbum core is reporting them incorrectly for the images that have been excluded from square cropping. So, a line like this will reflect the fixed shape dimensions, instead of the actual dimensions:
<div><a href='slides/mydog.html'><img src='thumbs/mydog.jpg' width='160' height='160' alt='mydog' title=''></a></div>
The easy solution is to skip the width and height attributes on the <img> tag. They're usually not strictly necessary for the HTML layout.
JeffTucker

Posts: 8,037
Registered: 31-Jan-2006
Re: How to change maxThumbWidth for individual images progammatically
Posted: 22 Jan 21, 00:31   in response to: JeffTucker in response to: JeffTucker
 
  Click to reply to this thread Reply
There is one nasty complication if you don't use thumbHeight and thumbWidth. If you have chosen HiDPI thumbnails, and you don't tell the HTML layout what the dimensions are, you're going to get thumbnails displayed at twice the desired size. The HiDPI settings work by doubling the stated bounds, then lying to the HTML about the size, so that, for example, a 400x400 thumbnail is displayed in 200x200 pixels on the page.
palthe

Posts: 16
Registered: 27-Dec-2009
Re: How to change maxThumbWidth for individual images progammatically
Posted: 22 Jan 21, 13:37   in response to: JeffTucker in response to: JeffTucker
 
  Click to reply to this thread Reply
Thanks for your reply.

My problem is not that the FixedShapeFilter is not excluded (it is, as you can see in screenshot 3), but that the maximum thumbnail width has not changed. That is why the landscape-oriented thumbnails are too small. They have the "default" width of 120 px. In screenshot 3 the tumbs have their actual height; I temporarily disabled the height: ${maxThumbHeight} style in the skin stylesheet.
This proves that my added variable maxThumbWidth=500 is ignored.
Note: The opton to enable the height: ${maxThumbHeight} style in the skin stylesheet is not possible, because then the browser will enlarge the landscape-oriented thumbnails and they get blurry. (In fact, that is how I initially noticed that someting was wrong.)

So the question remains: How to change the maxThumbWith variable for individual images?

Edited by: palthe on 22-Jan-2021 13:38
JeffTucker

Posts: 8,037
Registered: 31-Jan-2006
Re: How to change maxThumbWidth for individual images progammatically
Posted: 22 Jan 21, 14:05   in response to: palthe in response to: palthe
 
  Click to reply to this thread Reply
Attachment outputThumbs.png (17.6 KB)
Attachment variables.png (136.4 KB)
Attachment imageBounds.png (20.1 KB)
Attachment fixedShapeSetting.png (18.9 KB)
Works when I do it. Here's a complete, zipped-up demo album to play with:

(demo removed)

And I've attached some screenshots.

  • The thumbnail image bounds are set to 124x124 (bounds.png).
  • The skin is set to produce fixed shape thumbnails (fixedShapeSetting.png).
  • The excludeFilters and maxThumbWidth variables are set for one image (variables.png).
  • The output thumbnail for that one image is using the object-specific maxThumbWidth (outputThumbs.png).

The index page display, of course, is still not right, because of what the jAlbum core is doing. The index.htt is calling for thumbWidth and thumbHeight, and it's returning the wrong values for that one, wider thumbnail.
palthe

Posts: 16
Registered: 27-Dec-2009
Re: How to change maxThumbWidth for individual images progammatically
Posted: 22 Jan 21, 14:07   in response to: palthe in response to: palthe
 
  Click to reply to this thread Reply
I think I found my mistake!

Instead of adding maxThumbWidth=500 to the user-variables, I should have added it to the "normal" variables. See the maked lines in the revised code:
	void addUserVars(AlbumObject folder) {
		for (AlbumObject ao : folder.getChildren()) {
			if (!ao.isFolder()) {
				Category imgCat = ao.getCategory();
/**/				imgVars = ao.getVars();
				imgUserVars = imgVars.get("userVariables");
				imgUserVars.put("excludeFilters", "FixedShapeFilter");
/**/				imgVars.put("maxThumbWidth", "500");
				System.out.println(imgCat + " - " + ao.getName());
				System.out.println("- User variables: " + imgUserVars);
				System.out.println(engine.getThumbSize());
			}
		}
	}

Now it works as expected: the thumbs are all 120px heigh (= +maxThumbHeight+) with the original aspect-ratio.
Can someone confirm that this is indeed the correct solution?

As I often noticed, writing down your problem helps you in finding the answer :-)
palthe

Posts: 16
Registered: 27-Dec-2009
Re: How to change maxThumbWidth for individual images progammatically
Posted: 22 Jan 21, 14:17   in response to: JeffTucker in response to: JeffTucker
 
  Click to reply to this thread Reply
JeffTucker wrote:
Works when I do it. Here's a complete, zipped-up demo album to play with:

(demo removed)

And I've attached some screenshots.

  • The thumbnail image bounds are set to 124x124 (bounds.png).
  • The skin is set to produce fixed shape thumbnails (fixedShapeSetting.png).
  • The excludeFilters and maxThumbWidth variables are set for one image (variables.png).
  • The output thumbnail for that one image is using the object-specific maxThumbWidth (outputThumbs.png).

The index page display, of course, is still not right, because of what the jAlbum core is doing. The index.htt is calling for thumbWidth and thumbHeight, and it's returning the wrong values for that one, wider thumbnail.


Maybe I was not clear enough, but this is exactly what I did initially, setting the variables for each image via the user-interface (see the third paragraph of my original post). And yes, that worked.
davidekholm

Posts: 3,440
Registered: 18-Oct-2002
Re: How to change maxThumbWidth for individual images progammatically
Posted: 22 Jan 21, 16:52   in response to: palthe in response to: palthe
Helpful
  Click to reply to this thread Reply
Great that you sorted it out. Another option is to extend the FixedShapeFilter and apply the needed logic, for instance (top of init.bsh):
import java.awt.image.*;
 
class SubfoldersFixedShapeFilter extends FixedShapeFilter {
 
	private isSubFolder(Map vars) {
		AlbumObject ao = vars.get("currentObject");
		return ao.getParent() != null && ao.getParent().getParent() != null;
	}
 
	public BufferedImage filter(BufferedImage im, Map vars) {
		return isSubFolder(vars) ? super.filter(im, vars)  :  im;
	}
 
    public Dimension getModifiedSize(Dimension originalSize, Map vars) {
    		return isSubFolder(vars) ? super.getModifiedSize(originalSize, vars) : originalSize;
    }	
}

Now use this variant instead of FixedShapeFilter.
JeffTucker

Posts: 8,037
Registered: 31-Jan-2006
Re: How to change maxThumbWidth for individual images progammatically
Posted: 22 Jan 21, 17:17   in response to: davidekholm in response to: davidekholm
 
  Click to reply to this thread Reply
Yes, I was headed in that direction, having done something similar in Matrix with the XBorderFilter. That takes care of the sizing problems nicely. I'm not sure about the HiDPI case - I haven't tested that.
palthe

Posts: 16
Registered: 27-Dec-2009
Re: How to change maxThumbWidth for individual images progammatically
Posted: 22 Jan 21, 22:01   in response to: davidekholm in response to: davidekholm
 
  Click to reply to this thread Reply
Initially I got an error message when an image had no user variables. I solved this by adding a null-test condition:
if (imgVars.get("userVariables") == null) {
	imgVars.put("userVariables", new HashMap());
}

This is my final code (I hope) in init.bsh:
//	Add two user-variables to all items in the root-folder.
//	This prevents fixed-shape cropping of thumbnails on the main page.
//	These thumbnails are scaled to equal height and keep the original aspect-ratio.
 
	void addUserVars(AlbumObject folder) {
		for (AlbumObject ao : folder.getChildren()) {
			if (!ao.isFolder() && !ao.isHidden() && ao.isIncluded()) {
				imgVars = ao.getVars();
				if (imgVars.get("userVariables") == null) {
					imgVars.put("userVariables", new HashMap()); //add an empty "userVariables"-variable if it does not exist
				}
				imgUserVars = imgVars.get("userVariables");
				imgVars.put("maxThumbWidth", "500");
				imgUserVars.put("excludeFilters", "FixedShapeFilter");
			}
		}
	}
	
	if (ThumbFixedShape) {  // ThumbFixedShape is an option in the skin-UI
		// Crop thumbnails to the size of the 'image bounds' as set for thumbnails, before scaling
		engine.addFilter(new FixedShapeFilter(), JAFilter.THUMBNAILS_PRESCALE_STAGE);
	}
	if (ThumbFixedShape && ThumbExcludeMain) {  // ThumbExcludeMain is an option in the skin-UI
		// Exclude main page thumbnails from cropping and scale them to equal height (maxThumbHeight)
		addUserVars(rootFolder);
	}
palthe

Posts: 16
Registered: 27-Dec-2009
Re: How to change maxThumbWidth for individual images progammatically
Posted: 4 Feb 21, 16:35   in response to: davidekholm in response to: davidekholm
 
  Click to reply to this thread Reply
At first I did not try David's suggestion for an extended filter because that was new territory for me.
But now I found it is the key to a solution of my initial problem:

I made a similar extension for the ConstrainRatioFilter and added the following code to my init.bsh:
import java.awt.image.*;
class SubfoldersConstrainRatioFilter extends ConstrainRatioFilter {
	private isSubFolder(Map vars) {
		AlbumObject ao = vars.get("currentObject");
		return ao.getParent() != null && ao.getParent().getParent() != null;
	}
	public SubfoldersConstrainRatioFilter(float minRatio, float maxRatio) {
		setMinRatio(minRatio);
		setMaxRatio(maxRatio);
	}
	public BufferedImage filter(BufferedImage im, Map vars) {
		return isSubFolder(vars) ? super.filter(im, vars)  :  im;
	}
	public Dimension getModifiedSize(Dimension originalSize, Map vars) {
			return isSubFolder(vars) ? super.getModifiedSize(originalSize, vars) : originalSize;
	}
}
 
if (ThumbFixedShape) {
	String[] sRatio = ThumbAspectRatio.toLowerCase().replaceAll(" ", "").split("x");
	float fRatio = Float.parseFloat(sRatio[0]) / Float.parseFloat(sRatio[1]);  
	if (ThumbExcludeMain) {
		engine.addFilter(new SubfoldersConstrainRatioFilter(fRatio, fRatio), JAFilter.THUMBNAILS_PRESCALE_STAGE);
	} else {
		engine.addFilter(new ConstrainRatioFilter(fRatio, fRatio), JAFilter.THUMBNAILS_PRESCALE_STAGE);
	}
}

ThumbFixedShape (true|false), ThumbAspectRatio ("w x h") and ThumbExcludeMain (true|false) are variables from the skin-settings, See screenshot.

This works as follows:

  • On the Image-settings tab I set the image bounds for thumbnails to 1000 x 120 (WxH). This ensures that the thumbnails always get a fixed height of 120px.
  • If I don't select "Create fixed-shaped thumbnails" in the skin-settings, no filtering is applied and the thumbnails keep their original aspect-ratio.
  • If I do select "Create fixed-shaped thumbnails" and choose an aspect-ratio from the "Aspect-ratio" drop-down box, all thumbnails are cropped to the same aspect-ratio. This is realized by applying the ConstrainRatioFilter with equal values for the minRatio and maxRatio parameters.
  • I can exclude the root-folder by using the extended SubfoldersConstrainRatioFilter in stead of the normal ConstrainRatioFilter.

My questions:

  • Is my code correct?
  • Would it be wise to add something like
    engine.removeFilter(...)
    
    somewhere?
davidekholm

Posts: 3,440
Registered: 18-Oct-2002
Re: How to change maxThumbWidth for individual images progammatically
Posted: 5 Feb 21, 00:08   in response to: palthe in response to: palthe
 
  Click to reply to this thread Reply
Seems ok. I'd just adjust the variable name from ThumbAspectRatio to thumbAspectRatio as InitialCapitalLetters is used for class references only (by convention). And, no, you don't need to remove the filter. The filter pipeline is being cleared at the initialization of each album build.
palthe

Posts: 16
Registered: 27-Dec-2009
Re: How to change maxThumbWidth for individual images progammatically
Posted: 13 Feb 21, 17:15   in response to: davidekholm in response to: davidekholm
 
  Click to reply to this thread Reply
My apologies that I keep coming back on this topic, but I noticed a possible disadvantage of using an extended filter in this way:

When I add the extended filter, it seems that jAlbum will always re-process the images, even when I click on Make album for a second time without changing any settings. The System Console reports each time: "Make all'.
This also happens when I add the extended filter directly, without the skin-variables and the if-then-else stuff:
engine.addFilter(new SubfoldersConstrainRatioFilter(1f, 1f), JAFilter.THUMBNAILS_PRESCALE_STAGE);

I didn't notice this before, because I was testing it on an album with only a few images, so the time difference for creating the album with or without re-processing is not very large.

Maybe because (part of) the code for the extended filter is in init.bsh, jAlbum sees this each time as a "new" filter and therefore thinks it has to re-process the images?

Note: This disadvantage doesn't bother me very much. I just wanted to mention it for other users who might read this post.
davidekholm

Posts: 3,440
Registered: 18-Oct-2002
Re: How to change maxThumbWidth for individual images progammatically
Posted: 13 Feb 21, 19:44   in response to: palthe in response to: palthe
 
  Click to reply to this thread Reply
It shouldn't behave like that. The Minimal skin for instance adds a FixedShapeFilter in init.bsh, and this doesn't trigger a "Make all" operation every time, only when you initially switch to this skin. Try making the album several times. Does it really perform a "Make all" every time?
palthe

Posts: 16
Registered: 27-Dec-2009
Re: How to change maxThumbWidth for individual images progammatically
Posted: 13 Feb 21, 20:57   in response to: davidekholm in response to: davidekholm
 
  Click to reply to this thread Reply
Yes, it does "Make all" each time.

Be aware that I'm talking about the extended SubfoldersConstrainRatioFilter, See my post on 04-Feb-2021 16:35.
When I add the normal ConstrainRatioFilter, everything works as expected.

The extended filter has uncompiled code in init.bsh, maybe that makes the difference?
Legend
Forum admins
Helpful Answer
Correct Answer

Point your RSS reader here for a feed of the latest messages in all forums