Task: Bilinear interpolation



C#: using System;
using System.Drawing;

namespace BilinearInterpolation {
    class Program {
        private static float Lerp(float s, float e, float t) {
            return s + (e - s) * t;
        }

        private static float Blerp(float c00, float c10, float c01, float c11, float tx, float ty) {
            return Lerp(Lerp(c00, c10, tx), Lerp(c01, c11, tx), ty);
        }

        private static Image Scale(Bitmap self, float scaleX, float scaleY) {
            int newWidth = (int)(self.Width * scaleX);
            int newHeight = (int)(self.Height * scaleY);
            Bitmap newImage = new Bitmap(newWidth, newHeight, self.PixelFormat);

            for (int x = 0; x < newWidth; x++) {
                for (int y = 0; y < newHeight; y++) {
                    float gx = ((float)x) / newWidth * (self.Width - 1);
                    float gy = ((float)y) / newHeight * (self.Height - 1);
                    int gxi = (int)gx;
                    int gyi = (int)gy;
                    Color c00 = self.GetPixel(gxi, gyi);
                    Color c10 = self.GetPixel(gxi + 1, gyi);
                    Color c01 = self.GetPixel(gxi, gyi + 1);
                    Color c11 = self.GetPixel(gxi + 1, gyi + 1);

                    int red = (int)Blerp(c00.R, c10.R, c01.R, c11.R, gx - gxi, gy - gyi);
                    int green = (int)Blerp(c00.G, c10.G, c01.G, c11.G, gx - gxi, gy - gyi);
                    int blue = (int)Blerp(c00.B, c10.B, c01.B, c11.B, gx - gxi, gy - gyi);
                    Color rgb = Color.FromArgb(red, green, blue);
                    newImage.SetPixel(x, y, rgb);
                }
            }

            return newImage;
        }

        static void Main(string[] args) {
            Image newImage = Image.FromFile("Lenna100.jpg");
            if (newImage is Bitmap oi) {
                Image result = Scale(oi, 1.6f, 1.6f);
                result.Save("Lenna100_larger.jpg");
            } else {
                Console.WriteLine("Could not open the source file.");
            }
        }
    }
}


Go: package main

import (
	"image"
	"image/color"
	"image/jpeg"
	"log"
	"math"
	"os"

	"golang.org/x/image/draw"
)

func scale(dst draw.Image, src image.Image) {
	sr := src.Bounds()
	dr := dst.Bounds()
	mx := float64(sr.Dx()-1) / float64(dr.Dx())
	my := float64(sr.Dy()-1) / float64(dr.Dy())
	for x := dr.Min.X; x < dr.Max.X; x++ {
		for y := dr.Min.Y; y < dr.Max.Y; y++ {
			gx, tx := math.Modf(float64(x) * mx)
			gy, ty := math.Modf(float64(y) * my)
			srcX, srcY := int(gx), int(gy)
			r00, g00, b00, a00 := src.At(srcX, srcY).RGBA()
			r10, g10, b10, a10 := src.At(srcX+1, srcY).RGBA()
			r01, g01, b01, a01 := src.At(srcX, srcY+1).RGBA()
			r11, g11, b11, a11 := src.At(srcX+1, srcY+1).RGBA()
			result := color.RGBA64{
				R: blerp(r00, r10, r01, r11, tx, ty),
				G: blerp(g00, g10, g01, g11, tx, ty),
				B: blerp(b00, b10, b01, b11, tx, ty),
				A: blerp(a00, a10, a01, a11, tx, ty),
			}
			dst.Set(x, y, result)
		}
	}
}

func lerp(s, e, t float64) float64 { return s + (e-s)*t }
func blerp(c00, c10, c01, c11 uint32, tx, ty float64) uint16 {
	return uint16(lerp(
		lerp(float64(c00), float64(c10), tx),
		lerp(float64(c01), float64(c11), tx),
		ty,
	))
}

func main() {
	src, err := readImage("Lenna100.jpg")
	if err != nil {
		log.Fatal(err)
	}
	sr := src.Bounds()
	dr := image.Rect(0, 0, sr.Dx()*16/10, sr.Dy()*16/10)
	dst := image.NewRGBA(dr)

	
	scale(dst, src)
	err = writeJPEG(dst, "Lenna100_larger.jpg")
	if err != nil {
		log.Fatal(err)
	}

	
	
	draw.BiLinear.Scale(dst, dr, src, sr, draw.Src, nil)
	err = writeJPEG(dst, "Lenna100_larger.draw.jpg")
	if err != nil {
		log.Fatal(err)
	}
}

func readImage(filename string) (image.Image, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close() 
	m, _, err := image.Decode(f)
	return m, err
}

func writeJPEG(m image.Image, filename string) error {
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	err = jpeg.Encode(f, m, nil)
	if cerr := f.Close(); err == nil {
		err = cerr
	}
	return err
}