Ah, OK. Thanks. You’re right. I think that’s it.

I had assumed passthrough was a desired optimization because it starts out false and can only be assigned in `setHints`. But looking at the super class confirms your explanation.

So… I still think there are problems here, but now they strike me as less interesting/severe:

1. If an ImageProducer neglects to call setHints(..) AND if it produces pixels in, say, a random order: then AreaAveragingScaleFilter will fail with an exception. (It will enter the branch expecting pixels in a specific order, but it won’t get them in that order.)

Attached is a test case confirming that not calling setHints(..) can lead to an exception.

In practice:

A. OffScreenImageSource doesn’t call setHints(), but it happens to deliver pixels in the desired order: so it works.

B. On my Mac: ToolkitImages use an ImageProducer that calls setHInts() and promises to deliver pixels in the right order, so it works.

2. The AreaAveragingScalingFilter says in its documentation that if it doesn’t get the hints it wants: it will request new image production via `requestTopDownLeftRightResent`. I don’t see any evidence that this class (or any of its ancestors) invoke this.

(The attached test case also confirms.)

Is there any interest in my writing either of these up?

Regards,
 - Jeremy

------ Original Message ------
From "Aleksei Ivanov" <[email protected]>
To "Jeremy Wood" <[email protected]>; "[email protected]" <[email protected]>
Date 4/17/2023 7:43:06 AM
Subject Re: AreaAveragingScalingFilter

Hi Jeremy,

The intention could be to pass through if the value of hints is different from the needed ones. That is the filter activates if and only if hints == neededHints, otherwise it doesn't do anything and forwards calls to its superclass.

--
Regards,
Alexey

On 17/04/2023 09:53, Jeremy Wood wrote:
I could be mistaken, but it looks like AreaAveragingFilter has a typo in it. This method looks suspicious to me:

public void setHints(int hints) {
    passthrough = ((hints & neededHints) != neededHints);
    super.setHints(hints);
}

Later on the passthrough field is used as:

public void setPixels(int x, int y, int w, int h,
                      ColorModel model, byte pixels[], int off,
                      int scansize) {
    if (passthrough) {
        super.setPixels(x, y, w, h, model, pixels, off, scansize);
    }
else {
        accumPixels(x, y, w, h, model, pixels, off, scansize);
    }
}

This makes me think we want passthrough to be true when we match specific hints (“neededHints”) promising to deliver the pixel data in whole scanlines from top-to-bottom. So the “!=“ in setHints(..) should be “==“.

If I set passthrough to true for BufferedImages (which always deliver pixels from top to bottom in entire scanlines), then the execution time of this filter reduces to less than 5% of its current time. But it introduces scaling artifacts and looks lower quality.

So if (?) my theory is correct that there is a typo, and knowing that the AreaAveragingFilter is effectively internally deprecated <https://bugs.openjdk.org/browse/JDK-6196792?jql=status = Open AND text ~ "AreaAveragingScaleFilter" > : is anyone interested in discussing this with me further? I attached my (very rough) test program that demonstrates both the performance difference and the scaling artifacts.

(My broad goal is to create thumbnails of large images. If I used a Graphics2D to scale the image more than 50%, then I also see scaling artifacts with that approach. I know “Filthy Rich Clients” outlined a solution to that problem, but it’s expensive. So I’m dusting off this filter to see if it can work.)

Regards,
 - Jeremy

<<attachment: AreaAveragingScaleFilterTest2.java.zip>>

Reply via email to