Jason Summers writes about image processing, including resampling and grayscale conversion, and makes tools like ImageWorsener and Deark.
Commenters call ImageWorsener's pages an excellent reference on resizing and linear versus sRGB color, and some use the tool in their own projects.
These shaders are *.bin resources embedded in dwmcore.dll.
This tool can extract https://www.nirsoft.net/utils/resources_extract.html Then, cmd_decompiler.exe from there https://github.com/bo3b/3Dmigoto can either disassemble or decompile these binaries.
The pixel shaders there include both ps_4_0 code for new GPUs, and ps_2_0 for running on DirectX 9 GPUs. This makes the disassembler slightly more useful than the decompiler, the *.asm will contain both programs.
They first sample from 4 locations of the source texture. The sample locations are computed by vertex shaders somehow, and passed in TEXCOORD1 and TEXCOORD2 input registers. 2D sampler needs 2 floats for UV on input, texture coordinate vectors have up to 4 components on GPUs, so they’re packing 4 2D vectors into two 4D ones, and using xy and zw slices of these vectors. Because they probably using bilinear sampling (these are setup by CPU-running code, I have not looked), these 4 sample instructions are actually reading from 16 texels of the source texture.
Then, they compute the average of the 4 colors.
At this stage, they’re using pre-multiplied alpha.
For the next step of the pixel shader, they compare alpha with zero. If not zero, they convert the color to straight alpha, apply this formula https://entropymine.com/imageworsener/srgbformula/ to convert from sRGB to linear, then convert back to pre-multiplied alpha.
For the last step, they’re applying linear transformation to the color using input values…
When you're using a ringing filter, sRGB is often a better colorspace for upscaling than linear RGB, because it distorts the ringing artifacts to make them less noticeable by putting them mostly in the highlights, not the shadows. It's not mathematically "correct", but it's better suited to human perception, similar to how minimum phase filters can perceptually outperform linear phase in audio processing, where pre-ringing is more noticeable than post-ringing.
See "Catch #3" here:
https://entropymine.com/imageworsener/gamma/
And you can sometimes get even better results using a sigmoidized colorspace. See:
https://legacy.imagemagick.org/Usage/filter/nicolas/#detailed
Is doing lanczos really faster and/or better quality for scaling down than just doing a simple pixel mixing:
http://entropymine.com/imageworsener/pixelmixing/
I implemented this for my image pipeline:
https://github.com/pedrocr/rawloader/blob/230432a403a9febb5e5c004780211f7e765130b9/src/imageops/demosaic.rs#L155-L190
Makes for simple enough code and even before any serious effort at optimization or SIMD it can convert a 3680x2456x4 image in 32bit float (source article is 3x8bit) to 320x200x4 also in 32bit float in about 60ms (across 4 threads in 2 cores on a i5-6200U).
You may want to look at http://fileformats.archiveteam.org/wiki/Category:Graphics. Collecting sample files from there is a bit of a hassle, but there's quite some obscure formats.
On the same site, http://fileformats.archiveteam.org/wiki/Encyclopedia_of_Graphics_File_Formats points to an archive.org copy of a CD ROM with sample images.
Via its BMP page, I found http://entropymine.com/jason/bmpsuite/, which looks like the definite resource on that format.
Nice! I think it should be the default. Some software might treats as a compromise between correctness and cost (doing the rescaling in linear space is usually more costly). In my view it should be correctness first.
The ImageWorsener's website as an excellent reading material on image resizing and other transformations. ImageWorsener is a "correctness first" image resizing software.
http://entropymine.com/imageworsener/
Linear arithmetic in sRGB strikes again. Although calculating perceived brightness in a linear colorspace is also just an approximation, but it's still significantly better than doing linear arithmetic in sRGB.
Imageworsener has a nice page about this issue in the context of converting to grayscale:
https://entropymine.com/imageworsener/grayscale/