diff --git a/src/Microsoft.ML.ImageAnalytics/ImagePixelExtractor.cs b/src/Microsoft.ML.ImageAnalytics/ImagePixelExtractor.cs index c91d3b1380..6bcace5b83 100644 --- a/src/Microsoft.ML.ImageAnalytics/ImagePixelExtractor.cs +++ b/src/Microsoft.ML.ImageAnalytics/ImagePixelExtractor.cs @@ -377,77 +377,92 @@ private ValueGetter> GetGetterCore(DataViewRow input, in ImagePixelExtractingEstimator.GetOrder(ex.OrderOfExtraction, ex.ColorsToExtract, out int a, out int r, out int b, out int g); - int h = height; - int w = width; - - if (ex.InterleavePixelColors) + BitmapData bmpData = null; + try { - int idst = 0; - for (int y = 0; y < h; ++y) - for (int x = 0; x < w; x++) + bmpData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadOnly, src.PixelFormat); + int h = height; + int w = width; + byte[] row = new byte[bmpData.Stride]; + int pixelSize = System.Drawing.Image.GetPixelFormatSize(src.PixelFormat) / 8; + Func alpha = pixelSize > 3 ? new Func(ix => row[ix + 3]) : new Func(ix => 255); + + if (ex.InterleavePixelColors) + { + int idst = 0; + for (int y = 0; y < h; ++y) { - var pb = src.GetPixel(x, y); - if (!vb.IsEmpty) - { - if (a != -1) { vb[idst + a] = pb.A; } - if (r != -1) { vb[idst + r] = pb.R; } - if (g != -1) { vb[idst + g] = pb.G; } - if (b != -1) { vb[idst + b] = pb.B; } - } - else if (!needScale) + Marshal.Copy(bmpData.Scan0 + bmpData.Stride * y, row, 0, bmpData.Stride); + for (int x = 0; x < w; x++) { - if (a != -1) { vf[idst + a] = pb.A; } - if (r != -1) { vf[idst + r] = pb.R; } - if (g != -1) { vf[idst + g] = pb.G; } - if (b != -1) { vf[idst + b] = pb.B; } + var ix = x * pixelSize; + if (!vb.IsEmpty) + { + if (a != -1) { vb[idst + a] = alpha(ix); } + if (r != -1) { vb[idst + r] = row[ix + 2]; } + if (g != -1) { vb[idst + g] = row[ix + 1]; } + if (b != -1) { vb[idst + b] = row[ix + 0]; } + } + else if (!needScale) + { + if (a != -1) { vf[idst + a] = alpha(ix); } + if (r != -1) { vf[idst + r] = row[ix + 2]; } + if (g != -1) { vf[idst + g] = row[ix + 1]; } + if (b != -1) { vf[idst + b] = row[ix + 0]; } + } + else + { + + if (a != -1) { vf[idst + a] = (alpha(ix) - offset) * scale; } + if (r != -1) { vf[idst + r] = (row[ix + 2] - offset) * scale; } + if (g != -1) { vf[idst + g] = (row[ix + 1] - offset) * scale; } + if (b != -1) { vf[idst + b] = (row[ix + 0] - offset) * scale; } + } + idst += ex.Planes; } - else - { - - if (a != -1) { vf[idst + a] = (pb.A - offset) * scale; } - if (r != -1) { vf[idst + r] = (pb.R - offset) * scale; } - if (g != -1) { vf[idst + g] = (pb.G - offset) * scale; } - if (b != -1) { vf[idst + b] = (pb.B - offset) * scale; } - } - idst += ex.Planes; } - Contracts.Assert(idst == size); - } - else - { - int idstMin = 0; - for (int y = 0; y < h; ++y) + Contracts.Assert(idst == size); + } + else { - int idst = idstMin + y * w; - for (int x = 0; x < w; x++, idst++) + int idstMin = 0; + for (int y = 0; y < h; ++y) { - if (!vb.IsEmpty) - { - var pb = src.GetPixel(x, y); - if (a != -1) vb[idst + cpix * a] = pb.A; - if (r != -1) vb[idst + cpix * r] = pb.R; - if (g != -1) vb[idst + cpix * g] = pb.G; - if (b != -1) vb[idst + cpix * b] = pb.B; - } - else if (!needScale) + Marshal.Copy(bmpData.Scan0 + bmpData.Stride * y, row, 0, bmpData.Stride); + int idst = idstMin + y * w; + for (int x = 0; x < w; x++, idst++) { - var pb = src.GetPixel(x, y); - if (a != -1) vf[idst + cpix * a] = pb.A; - if (r != -1) vf[idst + cpix * r] = pb.R; - if (g != -1) vf[idst + cpix * g] = pb.G; - if (b != -1) vf[idst + cpix * b] = pb.B; - } - else - { - var pb = src.GetPixel(x, y); - if (a != -1) vf[idst + cpix * a] = (pb.A - offset) * scale; - if (r != -1) vf[idst + cpix * r] = (pb.R - offset) * scale; - if (g != -1) vf[idst + cpix * g] = (pb.G - offset) * scale; - if (b != -1) vf[idst + cpix * b] = (pb.B - offset) * scale; + var ix = x * pixelSize; + if (!vb.IsEmpty) + { + if (a != -1) vb[idst + cpix * a] = alpha(ix); + if (r != -1) vb[idst + cpix * r] = row[ix + 2]; + if (g != -1) vb[idst + cpix * g] = row[ix + 1]; + if (b != -1) vb[idst + cpix * b] = row[ix + 0]; + } + else if (!needScale) + { + if (a != -1) vf[idst + cpix * a] = alpha(ix); + if (r != -1) vf[idst + cpix * r] = row[ix + 2]; + if (g != -1) vf[idst + cpix * g] = row[ix + 1]; + if (b != -1) vf[idst + cpix * b] = row[ix + 0]; + } + else + { + if (a != -1) vf[idst + cpix * a] = (alpha(ix) - offset) * scale; + if (r != -1) vf[idst + cpix * r] = (row[ix + 2] - offset) * scale; + if (g != -1) vf[idst + cpix * g] = (row[ix + 1] - offset) * scale; + if (b != -1) vf[idst + cpix * b] = (row[ix + 0] - offset) * scale; + } } } } } + finally + { + if (bmpData != null) + src.UnlockBits(bmpData); + } dst = editor.Commit(); }; diff --git a/src/Microsoft.ML.ImageAnalytics/VectorToImageTransform.cs b/src/Microsoft.ML.ImageAnalytics/VectorToImageTransform.cs index ab69e889eb..cfd4f74f46 100644 --- a/src/Microsoft.ML.ImageAnalytics/VectorToImageTransform.cs +++ b/src/Microsoft.ML.ImageAnalytics/VectorToImageTransform.cs @@ -5,7 +5,9 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Drawing.Imaging; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using Microsoft.ML; using Microsoft.ML.CommandLine; @@ -370,47 +372,64 @@ private ValueGetter GetterFromType(PrimitiveDataViewType srcType int position = 0; ImagePixelExtractingEstimator.GetOrder(ex.Order, ex.Colors, out int a, out int r, out int b, out int g); - for (int y = 0; y < height; ++y) - for (int x = 0; x < width; x++) + BitmapData bmpData = null; + try + { + bmpData = dst.LockBits(new Rectangle(0, 0, dst.Width, dst.Height), ImageLockMode.WriteOnly, dst.PixelFormat); + for (int y = 0; y < height; ++y) { - float red = ex.DefaultRed; - float green = ex.DefaultGreen; - float blue = ex.DefaultBlue; - float alpha = ex.DefaultAlpha; - if (ex.InterleavedColors) - { - if (ex.Alpha) - alpha = Convert.ToSingle(values[position + a]); - if (ex.Red) - red = Convert.ToSingle(values[position + r]); - if (ex.Green) - green = Convert.ToSingle(values[position + g]); - if (ex.Blue) - blue = Convert.ToSingle(values[position + b]); - position += ex.Planes; - } - else - { - position = y * width + x; - if (ex.Alpha) alpha = Convert.ToSingle(values[position + cpix * a]); - if (ex.Red) red = Convert.ToSingle(values[position + cpix * r]); - if (ex.Green) green = Convert.ToSingle(values[position + cpix * g]); - if (ex.Blue) blue = Convert.ToSingle(values[position + cpix * b]); - } - Color pixel; - if (!needScale) - pixel = Color.FromArgb((int)alpha, (int)red, (int)green, (int)blue); - else + byte[] row = new byte[bmpData.Stride]; + int ix = 0; + for (int x = 0; x < width; x++) { - pixel = Color.FromArgb( - ex.Alpha ? (int)Math.Round(alpha * scale - offset) : 0, - (int)Math.Round(red * scale - offset), - (int)Math.Round(green * scale - offset), - (int)Math.Round(blue * scale - offset)); + float red = ex.DefaultRed; + float green = ex.DefaultGreen; + float blue = ex.DefaultBlue; + float alpha = ex.DefaultAlpha; + if (ex.InterleavedColors) + { + if (ex.Alpha) + alpha = Convert.ToSingle(values[position + a]); + if (ex.Red) + red = Convert.ToSingle(values[position + r]); + if (ex.Green) + green = Convert.ToSingle(values[position + g]); + if (ex.Blue) + blue = Convert.ToSingle(values[position + b]); + position += ex.Planes; + } + else + { + position = y * width + x; + if (ex.Alpha) alpha = Convert.ToSingle(values[position + cpix * a]); + if (ex.Red) red = Convert.ToSingle(values[position + cpix * r]); + if (ex.Green) green = Convert.ToSingle(values[position + cpix * g]); + if (ex.Blue) blue = Convert.ToSingle(values[position + cpix * b]); + } + if (!needScale) + { + row[ix++] = (byte)blue; + row[ix++] = (byte)green; + row[ix++] = (byte)red; + row[ix++] = (byte)alpha; + } + else + { + row[ix++] = (byte)Math.Round(blue * scale - offset); + row[ix++] = (byte)Math.Round(green * scale - offset); + row[ix++] = (byte)Math.Round(red * scale - offset); + row[ix++] = (byte)(ex.Alpha ? Math.Round(alpha * scale - offset) : 0); + } } - dst.SetPixel(x, y, pixel); - dst.Tag = nameof(VectorToImageConvertingTransformer); + Marshal.Copy(row, 0, bmpData.Scan0 + y * bmpData.Stride, bmpData.Stride); } + dst.Tag = nameof(VectorToImageConvertingTransformer); + } + finally + { + if (bmpData != null) + dst.UnlockBits(bmpData); + } }; }