In part 2, when you use methods B and D, the output of the decimator can be negative or even exceed 255 at some pixels (since an ideal LPF is used). In such cases, don't bother with scaling, just threshold pixels, so that all the negative ones are set to zero and all the ones which exceeded 255 are set to 255.
Some differences among the output images are rather subtle, so you need to
properly view the images to compare them. Netscape does not grab all entries in
your video display's colormap and has to resort to dithering. XV does a better
job, but still does some dithering by default. To force xv to use all 256
entries in the color map to avoid dithering, run it with the
xv -perfect out_3a.pgm).
A detail about the boundaries when you are doing bilinear interpolation. It turns out that the last 4 columns and the last 4 rows cannot be interpolated since there are no other data to fit 1st order polynomial with. For these cases you can use your own judgement. The solution uses zero-order hold at the boundaries.