unsafe Bitmap downscaling_kernel(Bitmap input, Size newSize, Kernel k) { Bitmap output = new Bitmap(newSize.Width, newSize.Height, input.PixelFormat); float rx = (float)input.Width / newSize.Width; float ry = (float)input.Height / newSize.Height; int kwh = k.Width / 2; int khh = k.Height / 2; using (var o_it = new FLib.BitmapIterator(output, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)) { byte *o_data = (byte *)o_it.PixelData; using (var i_it = new FLib.BitmapIterator(input, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb)) { byte *i_data = (byte *)i_it.PixelData; for (int iy = 0; iy < newSize.Height; iy++) { for (int ix = 0; ix < newSize.Width; ix++) { int cx = (int)((0.5 + ix) * rx); int cy = (int)((0.5 + iy) * ry); int o_idx = 4 * ix + iy * o_it.Stride; double r = 0, g = 0, b = 0; for (int ky = 0; ky < k.Height; ky++) { int py = cy - k.Height / 2 + ky; for (int kx = 0; kx < k.Width; kx++) { int px = cx - k.Width / 2 + kx; int i_idx = 4 * px + py * i_it.Stride; if (0 <= px && px < input.Width && 0 <= py && py < input.Height) { double w = k.Data[kx + ky * k.Width]; b += w * i_data[i_idx + 0] / 255.0; g += w * i_data[i_idx + 1] / 255.0; r += w * i_data[i_idx + 2] / 255.0; } } } o_data[o_idx + 0] = (byte)(255.0 * b); o_data[o_idx + 1] = (byte)(255.0 * g); o_data[o_idx + 2] = (byte)(255.0 * r); o_data[o_idx + 3] = 255; } } } } return(output); }
// return image whose size is [config.wo, config.ho]. public unsafe Bitmap CreateOutputImage(Config config) { var bmp = new Bitmap(config.wo, config.ho, PixelFormat.Format32bppArgb); using (var it = new FLib.BitmapIterator(bmp, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb)) { byte *data = it.Data; For.AllKernels(config, (_, k) => { List <Vec3> debug = new List <Vec3>(); Vec3 sumColor = new Vec3(0, 0, 0); double sumWeight = 0; int count = 0; For.AllPixelsOfRegion(config, k, (_0, i) => { double weight = w(k)[index(config, i, k)]; int x = (int)(i.p.x + m[k.index].x - k.xi - (int)(1.5 * config.rx)); int y = (int)(i.p.y + m[k.index].y - k.yi - (int)(1.5 * config.rx)); if (x < 0 || config.wi <= x || y < 0 || config.hi <= y) { return; } int idx = x + y * config.wi; sumColor += weight * c[idx]; sumWeight += weight; count++; debug.Add(weight * c[idx]); }); Vec3 aveColor = sumColor / sumWeight; System.Diagnostics.Debug.Assert(0 <= aveColor.x && aveColor.x <= 1); System.Diagnostics.Debug.Assert(0 <= aveColor.y && aveColor.y <= 1); System.Diagnostics.Debug.Assert(0 <= aveColor.z && aveColor.z <= 1); byte r = (byte)(255 * aveColor.x); byte g = (byte)(255 * aveColor.y); byte b = (byte)(255 * aveColor.z); data[4 * k.x + k.y * it.Stride + 0] = b; data[4 * k.x + k.y * it.Stride + 1] = g; data[4 * k.x + k.y * it.Stride + 2] = r; data[4 * k.x + k.y * it.Stride + 3] = 255; }); } return(bmp); }
unsafe IMG extractChannel(Bitmap input, int channel) { IMG img = new IMG(input.Width, input.Height); using (var i_it = new FLib.BitmapIterator(input, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb)) { byte *i_data = (byte *)i_it.PixelData; for (int iy = 0; iy < input.Height; iy++) { for (int ix = 0; ix < input.Width; ix++) { int i_idx = 4 * ix + iy * i_it.Stride; img.data[ix + iy * input.Width] = i_data[i_idx + channel] / 255.0; } } } return(img); }
unsafe void initialize(Config config, Bitmap input) { int Rsize = (int)(4 * config.rx + 1) * (int)(4 * config.ry + 1); // copy color c = new Vec3[config.wi * config.hi]; System.Diagnostics.Debug.Assert(c.Length == input.Width * input.Height); using (BitmapIterator iter = new FLib.BitmapIterator(input, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb)) { byte *data = (byte *)iter.PixelData; for (int y = 0; y < input.Height; y++) { for (int x = 0; x < input.Width; x++) { int idx = 4 * x + y * iter.Stride; byte b = data[idx + 0]; byte g = data[idx + 1]; byte r = data[idx + 2]; c[x + y * input.Width] = new Vec3(r / 255.0, g / 255.0, b / 255.0); } } } // init w_ = new List <double[]>(); g_ = new List <double[]>(); m = new Vec2[config.wo * config.ho]; S = new Mat2x2[config.wo * config.ho]; v = new Vec3[config.wo * config.ho]; s = new double[config.wo * config.ho]; For.AllKernels(config, (_, k) => { w_.Add(new double[Rsize]); g_.Add(new double[Rsize]); m[k.index] = new Vec2((0.5 + k.x) * config.rx, (0.5 + k.y) * config.ry); S[k.index] = new Mat2x2(config.rx / 3, 0, 0, config.ry / 3); v[k.index] = new Vec3(0.5, 0.5, 0.5); s[k.index] = 1e-4; }); }
unsafe Bitmap toBitmap(IMG R, IMG G, IMG B, PixelFormat pixelFormat) { int w = R.w; int h = R.h; Bitmap output = new Bitmap(w, h, pixelFormat); using (var o_it = new FLib.BitmapIterator(output, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)) { byte *o_data = (byte *)o_it.PixelData; for (int iy = 0; iy < h; iy++) { for (int ix = 0; ix < w; ix++) { int o_idx = 4 * ix + iy * o_it.Stride; o_data[o_idx + 0] = (byte)(255.0 * B.data[ix + iy * w]); o_data[o_idx + 1] = (byte)(255.0 * G.data[ix + iy * w]); o_data[o_idx + 2] = (byte)(255.0 * R.data[ix + iy * w]); o_data[o_idx + 3] = 255; } } } return(output); }