public override ExpressionDrawer.IDrawable Load(MemoryReader mreader, Debugger debugger, string name, string type, LoadCallback callback) { // NOTE: If the image is not created at the point of debugging, so the variable is // uninitialized, the size may be out of bounds of int32 range. In this case the // exception is thrown here and this is ok. However if there is some garbage in // memory random size could be loaded here. Then also the memory probably points // to some random place in memory (maybe protected?) so the result will probably // be another exception which is fine or an image containing noise from memory. ulong dataStart = ExpressionParser.GetPointer(debugger, name + ".DataStart"); ulong dataEnd = ExpressionParser.GetPointer(debugger, name + ".DataEnd"); ulong length = dataEnd - dataStart; int cols = ExpressionParser.LoadSize(debugger, name + ".Cols"); int rows = ExpressionParser.LoadSize(debugger, name + ".Rows"); EnvDTE.Expression exp = debugger.GetExpression("(int)(" + name + ".Type())"); MatType mType = MatType.CV_8UC1; if (exp.IsValidValue) { mType = (MatType)int.Parse(exp.Value); } byte[] memory = new byte[length]; bool isLoaded = false; if (mreader != null) { ulong address = ExpressionParser.GetValueAddress(debugger, name + ".DataPointer[0]"); if (address == 0) { return(null); } isLoaded = mreader.ReadBytes(address, memory); } var pixelFormat = MatTypeToPixelFormat(mType); Bitmap bmp = new Bitmap( cols, rows, pixelFormat); BitmapData data = bmp.LockBits( new Rectangle(System.Drawing.Point.Empty, bmp.Size), ImageLockMode.WriteOnly, pixelFormat); Marshal.Copy(memory, 0, data.Scan0, (int)length); bmp.UnlockBits(data); return(new ExpressionDrawer.Image(bmp)); }
public override ExpressionDrawer.IDrawable Load(MemoryReader mreader, Debugger debugger, string name, string type, LoadCallback callback) { // NOTE: If the image is not created at the point of debugging, so the variable is // uninitialized, the size may be out of bounds of int32 range. In this case the // exception is thrown here and this is ok. However if there is some garbage in // memory random size could be loaded here. Then also the memory probably points // to some random place in memory (maybe protected?) so the result will probably // be another exception which is fine or an image containing noise from memory. int width = ExpressionParser.LoadSize(debugger, name + "._view._dimensions.x"); int height = ExpressionParser.LoadSize(debugger, name + "._view._dimensions.y"); if (width < 1 || height < 1) { return(null); } string pixelType, isPlanarStr; if (!Util.Tparams(type, out pixelType, out isPlanarStr)) { return(null); } string pixelId = Util.TypeId(pixelType); if (pixelId != "boost::gil::pixel") { return(null); } bool isPlanar = (isPlanarStr == "1"); string channelValueType, layoutType; if (!Util.Tparams(pixelType, out channelValueType, out layoutType)) { return(null); } string layoutId = Util.TypeId(layoutType); if (layoutId != "boost::gil::layout") { return(null); } string colorSpaceType, channelMappingType; if (!Util.Tparams(layoutType, out colorSpaceType, out channelMappingType)) { return(null); } ChannelValueKind channelValueKind = ChannelValueKind.Unknown; int channelValueSize = 0; ParseChannelValue(debugger, channelValueType, out channelValueKind, out channelValueSize); if (channelValueKind == ChannelValueKind.Unknown || channelValueSize == 0) { return(null); } string colorSpaceId = Util.TypeId(colorSpaceType); ColorSpace colorSpace = ParseColorSpace(colorSpaceType); int colorSpaceSize = ColorSpaceSize(colorSpace); if (colorSpace == ColorSpace.Unknown || colorSpaceSize == 0) { return(null); } Layout layout = ParseChannelMapping(colorSpace, channelMappingType); if (layout == Layout.Unknown) { return(null); } if (channelValueSize != 1 && channelValueSize != 2 && channelValueSize != 4 && channelValueSize != 8) { return(null); } // TODO: size_t? ulong? int bytesCount = width * height * colorSpaceSize * channelValueSize; byte[] memory = new byte[bytesCount]; bool isLoaded = false; if (mreader != null) { ulong address = ExpressionParser.GetValueAddress(debugger, name + "._memory[0]"); if (address == 0) { return(null); } isLoaded = mreader.ReadBytes(address, memory); } if (!isLoaded) { // Parsing the memory byte by byte may take very long time // even for small images. So don't do it. return(null); } LayoutMapper layoutMapper = GetLayoutMapper(layout); if (layoutMapper == null) { return(null); } // Use Pixel format native to Gil Image? System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height); for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { int pixelIndex = (j * width + i); // The raw bytes are converted into channel values pixel by pixel. // It could be more efficient to convert all channel values at once first // and only create pixels from array of channels in this loop. // Another thing is that when channels are always converted to byte // the information is lost. This information could be used during potential // conversion in GetColor() below (cmyk->rgb). Channels could be returned // as float[]. In practice the eye will probably not notice the difference. byte[] channels = isPlanar ? GetChannelsPlanar(memory, pixelIndex, channelValueKind, channelValueSize, colorSpaceSize) : GetChannelsInterleaved(memory, pixelIndex, channelValueKind, channelValueSize, colorSpaceSize); if (channels == null) { return(null); } System.Drawing.Color c = layoutMapper.GetColor(channels); bmp.SetPixel(i, j, c); // TODO: Checked per pixel. Too often? // But it's the same for geometries (ForEachMemoryBlock). if (!callback()) { return(null); } } } return(new ExpressionDrawer.Image(bmp)); }