On Wed, 2 Apr 2025 12:24:54 GMT, Sergey Bylokhov <s...@openjdk.org> wrote:

>>>The idea of the current approach, as I understand it is that we find the 
>>>last band of the first pixel, be it 3 for pixel-interleaved RGBA, or 30000 
>>>for band-interleaved image, and then add 1 to it, meaning the size 
>>>sufficient to fit that last band:
>>>int size = maxBandOff + 1;
>>>At this point we can already fit the first pixel, so what's left is to fit 
>>>the remaining first scanline (hence width - 1):
>> 
>> This looks suspicious. Let's try calculating the size or pointer to the last 
>> pixel using the formula:
>> "starting offset + pointer to the last pixel + pixelStride" but in reverse 
>> order.
>>    
>>     // This moves the pointer to the start of the last row.
>>     size = scanlineStride * (height - 1); 
>>     // This moves the pointer to the start of the last pixel in the last row.
>>     size += pixelStride * (width - 1);
>> 
>> **Note**: At this point, the size is not necessarily aligned to pixelStride 
>> because scanlineStride may include a gap larger than pixelStride at the end.
>> 
>> Now, we need to account for the last pixel in the last row. In a theoretical 
>> case where the offset is 0, simply adding pixelStride one more time would be 
>> sufficient.
>> 
>> However, in our case, we add maxBandOff + 1, which seems odd since 
>> maxBandOff represents the offset of the largest component, placing it 
>> somewhere within the pixelStride.
>> 
>> To fix this, we should actually add the second part of the pixelStride only 
>> if maxBandOff is smaller than pixelStride.
>> 
>> btw, I'm not sure why we can't use the first component instead of the last 
>> one:
>> 
>> 
>>  int minBandOff = bandOffsets[0];
>>  for (int i = 1; i < bandOffsets.length; i++) {
>>      minBandOff = Math.min(minBandOff, bandOffsets[i]);
>>  }
>> 
>>  long size = 0;
>> 
>>  if (minBandOff >= 0)
>>      size += minBandOff;
>>  if (pixelStride > 0)
>>      size += pixelStride * width;
>>  if (scanlineStride > 0)
>>      size += scanlineStride * (height - 1);         
>>  return (int) size;
>> 
>> 
>> ...Still investigating this.
>
> Or maybe we should modify the code that relies on the current size?
> 
> Why does our code work fine when skipping the end of the scanline in cases 
> where there is a gap, but it cannot skip the pixelStride when there is a gap 
> as well?

> why we can't use the first component instead of the last one

We definitely cannot do that because of the band-interleaved case: imagine if 
there are like 10000 bytes of red samples followed by another 10000 bytes of 
green samples - with `pixelStride=1` and `scanlineStride=100` if we take the 
first component offset (0), our calculated size would only fit the red channel.

In your calculations using "starting offset + pointer to the last pixel + 
pixelStride", you assume only pixel-interleaved variant, but this calculation 
would break with other interleaving modes. Actually, for pixel-interleaved 
layout there is a simple commonly-used formula, like: `size = startingOffset + 
scanlineStride * height`. But the problem is that we don't really know the 
`startingOffset`, we only know offsets of the individual components, which 
leads to the other issue...

> the size is not necessarily aligned to pixelStride because scanlineStride may 
> include a gap larger than pixelStride at the end.

Good point, and because of the way `pixelStride` and `scanlineStride` are 
formulated (offsets between same-band samples of the adjacent 
pixels/scanlines), they don't tell us anything about the alignment. And 
moreover, in the case of unused components, where our `bandOffsets` don't fully 
fill the `pixelStride`, there is an ambiguity:
Consider `bandOffsets = {1, 2, 3}` and `pixelStride=4`, is that a `xRGB` layout 
with `startingOffset=0`, or `RGBx` with `startingOffset=1`? The answer is - we 
don't have enough info as far as I'm concerned...

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/24111#discussion_r2024717944

Reply via email to