scaling down matrix

Roman Thilenius's icon

while displaying images scaled up is not a big problem (the first quick and dirty solution already begins with the "interp" of jit pwindow), scaling down seems more difficult.

how would you display an image which is 400*400 in a 100*100 pwindow?

nearest neighbour/line skipping like present in pwindow, rota, resamp and others is out of question.

i´d be willing to put the image on a GL plane if you show me how i can get a square figure pixel-exact into a pwindow and apply an existing jitter matrix.

a solution using a pixel matrix would be preferred though. CPU or scheduler load is not an issue.

Roman Thilenius's icon

25% in photoshop - that quality would be sufficient.

Rob Ramirez's icon

you can perform trilinear sampling using the GPU and a simple shader around the textureLod function. We actually ship with this shader.

Max Patch
Copy patch and select New From Clipboard in Max.

Roman Thilenius's icon

thanks rob, that works fine and will be my to go solution.

if anyone has an idea how to do it completely different, incl. more inefficiently (jit op? pixel matrix?) let me know.

Rob Ramirez's icon

for what it's worth here's chatgpt's pseudocode for this:

function trilinearSample(image, x, y, level):
    if level == 0:
        return image[x, y]  // Return the pixel value at the current level

    levelWidth = image.width / (2^level)
    levelHeight = image.height / (2^level)

    // Calculate coordinates in the current level
    currentX = x / (2^level)
    currentY = y / (2^level)

    // Calculate coordinates in the neighboring levels
    lowerLevelX = floor(currentX)
    lowerLevelY = floor(currentY)
    upperLevelX = ceil(currentX)
    upperLevelY = ceil(currentY)

    // Calculate fractional values for interpolation
    fracX = currentX - lowerLevelX
    fracY = currentY - lowerLevelY

    // Sample pixels from neighboring mipmaps
    lowerLevelSample00 = trilinearSample(image, lowerLevelX, lowerLevelY, level - 1)
    lowerLevelSample10 = trilinearSample(image, upperLevelX, lowerLevelY, level - 1)
    lowerLevelSample01 = trilinearSample(image, lowerLevelX, upperLevelY, level - 1)
    lowerLevelSample11 = trilinearSample(image, upperLevelX, upperLevelY, level - 1)

    // Perform trilinear interpolation in both dimensions
    interpolatedX0 = lowerLevelSample00 * (1 - fracX) + lowerLevelSample10 * fracX
    interpolatedX1 = lowerLevelSample01 * (1 - fracX) + lowerLevelSample11 * fracX
    interpolatedValue = interpolatedX0 * (1 - fracY) + interpolatedX1 * fracY

    return interpolatedValue

function downsampleImage(image, targetWidth, targetHeight):
    resultImage = new Image(targetWidth, targetHeight)

    for y = 0 to targetHeight - 1:
        for x = 0 to targetWidth - 1:
            // Calculate the level to sample from based on target size
            level = log2(image.width / targetWidth)
            resultImage[x, y] = trilinearSample(image, x, y, level)

    return resultImage
Roman Thilenius's icon

if jit.fastblur had a radial mode and allowed 4 instead of only 3 pixels distance, it would be ok, too. (except for the image borders, but i know how to deal with this, as i had to do the same in PS.... not above, but for actual image size changes)

Pedro Santos's icon

another CPU solution would be "jit.dimop @op avg @step 4 4".

Max Patch
Copy patch and select New From Clipboard in Max.