private Bitmap ReadRegion(SizeL location, int level, SizeL size) { Stopwatch sw = new Stopwatch(); sw.Start(); OpenSlide.TraceMsg("start ReadRegion " + level + "/" + location.Height + "_" + location.Width + ": " + GetBytesReadable(size.Width * size.Height * 3)); Bitmap bmp = new Bitmap((int)size.Width, (int)size.Height); bmp.SetPixel(0, 0, Color.AliceBlue); var bmpdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); OpenSlide.TraceMsg("bmp locked " + level + "/" + location.Height + "_" + location.Width); unsafe { void *p = bmpdata.Scan0.ToPointer(); openslide_read_region(handle, p, location.Width, location.Height, level, size.Width, size.Height); } OpenSlide.TraceMsg("read finished " + level + "/" + location.Height + "_" + location.Width + ": " + GetBytesReadable(size.Width * size.Height * 3 / Math.Max(sw.ElapsedMilliseconds, 1)) + "/ms"); bmp.UnlockBits(bmpdata); OpenSlide.TraceMsg("unlock bits " + level + "/" + location.Height + "_" + location.Width); if (bmp.GetPixel(0, 0) == Color.Black) { var error = CheckForLastError(); if (error != null) { throw new ArgumentException($"error reading region loc:{location}, level:{level}, size:{size}" + error); } //else just a black image? } OpenSlide.TraceMsg("end ReadRegion " + level + "/" + location.Height + "_" + location.Width); return(bmp); }
private SKBitmap ReadRegion(SizeL location, int level, SizeL size) { Stopwatch sw = new Stopwatch(); sw.Start(); OpenSlide.TraceMsg("start ReadRegion " + level + "/" + location.Height + "_" + location.Width + ": " + GetBytesReadable(size.Width * size.Height * 3)); SKBitmap bmp = new SKBitmap((int)size.Width, (int)size.Height); bmp.SetPixel(0, 0, SKColors.AliceBlue); bmp.LockPixels(); var bmpdata = bmp.GetPixels(); OpenSlide.TraceMsg("bmp locked " + level + "/" + location.Height + "_" + location.Width); unsafe { void *p = bmpdata.ToPointer(); Import.openslide_read_region(handle, p, location.Width, location.Height, level, size.Width, size.Height); } OpenSlide.TraceMsg("read finished " + level + "/" + location.Height + "_" + location.Width + ": " + GetBytesReadable(size.Width * size.Height * 3 / Math.Max(sw.ElapsedMilliseconds, 1)) + "/ms"); bmp.UnlockPixels(); OpenSlide.TraceMsg("unlock bits " + level + "/" + location.Height + "_" + location.Width); if (bmp.GetPixel(0, 0) == SKColors.Black) { var error = CheckForLastError(); if (error != null) { throw new ArgumentException($"error reading region loc:{location}, level:{level}, size:{size}" + error); } //else just a black image? } OpenSlide.TraceMsg("end ReadRegion " + level + "/" + location.Height + "_" + location.Width); return(bmp); }
private IList <SizeL> GetLimitedLevelDimensions() { //Slide level dimensions scale factor in each axis float.TryParse(Osr.Properties[OpenSlide.PROPERTY_NAME_BOUNDS_WIDTH], out float scaledWidth); float.TryParse(Osr.Properties[OpenSlide.PROPERTY_NAME_BOUNDS_HEIGHT], out float scaledHeight); var level0Limits = Osr.LevelDimensions[0]; scaledWidth = scaledWidth / level0Limits.Width; scaledHeight = scaledHeight / level0Limits.Height; var sizeScale = new SizeF(scaledWidth, scaledHeight); // Dimensions of active area var levelDimensions = new List <SizeL>(); foreach (var levelSize in Osr.LevelDimensions) { var newScaledWidth = (long)Math.Ceiling((double)levelSize.Width * sizeScale.Width); var newScaledHeight = (long)Math.Ceiling((double)levelSize.Height * sizeScale.Height); var scaledLevelSize = new SizeL(newScaledWidth, newScaledHeight); levelDimensions.Add(scaledLevelSize); } return(levelDimensions); }
public override Image GetThumbnail(SizeL maxSize) { var thumbSize = image.GetProportionateResize(maxSize.ToSize()); var callback = new Image.GetThumbnailImageAbort(ThumbnailCallback); var thumbnail = image.GetThumbnailImage(thumbSize.Width, thumbSize.Height, callback, new IntPtr()); return(thumbnail); }
public MemoryStream GetTile(int level, long row, long col) { OpenSlide.TraceMsg("start gettile " + level + "/" + col + "_" + row); if (level < 0 || level >= max_dz_level) { throw new ArgumentException($"wrong level level {level}, row {row}, col {col}"); } if (t_dimensions[level].Width <= col || t_dimensions[level].Height <= row || 0 > col || 0 > row) { throw new ArgumentException($"wrong address level {level}, row {row}, col {col}"); } var os_level = os_level_for_dz_level[level]; //Calculate top/ left and bottom/ right overlap var z_overlap_tl = new SizeL(col == 0 ? 0 : 1, row == 0 ? 0 : 1); var z_overlap_br = new SizeL(col == t_dimensions[level].Width ? 0 : 1, row == t_dimensions[level].Height ? 0 : 1); var z_size = new SizeL(Math.Min(TILE_DOWNSAMPLE, z_dimensions[level].Width - TILE_DOWNSAMPLE * col) + z_overlap_tl.Width + z_overlap_br.Width, Math.Min(TILE_DOWNSAMPLE, z_dimensions[level].Height - TILE_DOWNSAMPLE * row) + z_overlap_tl.Height + z_overlap_br.Height); if (z_size.Width < 0 || z_size.Height < 0) { throw new ArgumentException($"out of bounds level {level}, row {row}, col {col}"); } var z_location = new SizeL(TILE_DOWNSAMPLE * col, TILE_DOWNSAMPLE * row); var l_location = new System.Drawing.SizeF((float)l_z_downsamples[level] * (z_location.Width - z_overlap_tl.Width), (float)l_z_downsamples[level] * (z_location.Height - z_overlap_tl.Height)); //Round location down and size up, and add offset of active area var l0_location = new SizeL((long)(downsamples[os_level] * l_location.Width), (long)(downsamples[os_level] * l_location.Height)); var l_size = new SizeL((long)Math.Min(Math.Ceiling(l_z_downsamples[level] * z_size.Width), dimensions[os_level].Width), (long)Math.Min(Math.Ceiling(l_z_downsamples[level] * z_size.Height), dimensions[os_level].Height)); OpenSlide.TraceMsg("calcs done " + level + "/" + col + "_" + row); var bmp = ReadRegion(l0_location, os_level, l_size); if (l_size.Width != z_size.Width || l_size.Height != z_size.Height) { //only resize when necessary OpenSlide.TraceMsg("resize " + level + "/" + col + "_" + row); var oldbmp = bmp; bmp = new SKBitmap((int)z_size.Width, (int)z_size.Height); oldbmp.Resize(bmp, SKBitmapResizeMethod.Box); } OpenSlide.TraceMsg("new bmp " + level + "/" + col + "_" + row); var stream = new MemoryStream(); //Prints tile coords for testing //var g = Graphics.FromImage(resizedbmp); //g.DrawString(level + "/" + col + "_" + row, new Font(FontFamily.GenericSansSerif, 18), new SolidBrush(Color.Black), resizedbmp.Width / 2, resizedbmp.Height / 2); bmp.Encode(new SKManagedWStream(stream), SKEncodedImageFormat.Jpeg, 80); OpenSlide.TraceMsg("end gettile " + level + "/" + col + "_" + row); stream.Position = 0; return(stream); }
private void InitZDimensions() { ///size on a current dz_level var z_size = dimensions[0]; z_dimensions.Add(z_size); while (z_size.Width > 1 || z_size.Height > 1) { z_size = new SizeL((long)Math.Max(1, Math.Ceiling(z_size.Width / 2.0)), (long)Math.Max(1, Math.Ceiling(z_size.Height / 2.0))); z_dimensions.Add(z_size); } z_dimensions.Reverse(); }
private void CheckParameters(int level, SizeL adress) { var col = adress.Width; var row = adress.Height; if (level < 0 || level >= LevelCount) { throw new ArgumentException($"wrong level level {level}, row {row}, col {col}"); } if (TileDimensions[level].Width <= col || TileDimensions[level].Height <= row || 0 > col || 0 > row) { throw new ArgumentException($"wrong address level {level}, row {row}, col {col}"); } }
public Header(MetafileReader reader) { Bounds = new RectL(reader); Frame = new RectL(reader); Signature = reader.ReadUInt32(); Version = reader.ReadUInt32(); NumberOfBytes = reader.ReadUInt32(); NumberOfRecords = reader.ReadUInt32(); NumberOfObjects = reader.ReadUInt16(); Reserved = reader.ReadUInt16(); DescriptionLength = reader.ReadUInt32(); DescriptionOffset = reader.ReadUInt32(); NumberOfPaletteEntries = reader.ReadUInt32(); ReferenceDeviceSizePixels = new SizeL(reader); ReferenceDeviceSizeMillimeters = new SizeL(reader); }
private IList <SizeL> GetDeepZoomLevels() { var deepZoomSize = Level0Dimensions; var dzLevelDimensions = new List <SizeL> { deepZoomSize }; while (deepZoomSize.Width > 1 || deepZoomSize.Height > 1) { var width = (long)Math.Max(1, Math.Ceiling(deepZoomSize.Width / 2.0)); var height = (long)Math.Max(1, Math.Ceiling(deepZoomSize.Height / 2.0)); deepZoomSize = new SizeL(width, height); dzLevelDimensions.Add(deepZoomSize); } dzLevelDimensions.Reverse(); return(dzLevelDimensions); }
/*Returns an image containing the contents of the region. * location: (x, y) tuple giving the top left pixel in the level 0 reference frame. * level: the level number. * maxSize: (width, height) tuple giving the region maxSize.*/ public override Image ReadRegion(SizeL location, int level, SizeL size) { if (image == null) { throw new ArgumentNullException(); } if (level != 0) { throw new OpenSlideException("Invalid level"); } if (size.Width < 0 || size.Height < 0) { throw new OpenSlideException($"Size {size} must be non-negative"); } /* Any corner of the requested region may be outside the bounds of * the image. Create a transparent tile of the correct maxSize and * paste the valid part of the region into the correct location.*/ var imageTopLeft = new SizeL(Math.Max(0, Math.Min(location.Width, Dimensions.Width)), Math.Max(0, Math.Min(location.Height, Dimensions.Height))); var imageBottomRight = new SizeL(Math.Max(0, Math.Min(location.Width + size.Width - 1, Dimensions.Width - 1)), Math.Max(0, Math.Min(location.Height + size.Height - 1, Dimensions.Height - 1))); var tile = new Bitmap((int)size.Width, (int)size.Height); // Crop maxSize is greater than zero in both dimensions. if (imageBottomRight.Width - imageTopLeft.Width < 0 && imageBottomRight.Height - imageTopLeft.Height < 0) { return(tile); } var crop = new Rectangle((int)imageTopLeft.Width, (int)imageTopLeft.Height, (int)(imageTopLeft.Width + imageBottomRight.Width + 1), (int)(imageTopLeft.Height + imageBottomRight.Height + 1)); var g = Graphics.FromImage(tile); g.DrawImage(image, 0, 0, crop, GraphicsUnit.Pixel); return(tile); }
static void Main(string[] args) { string filename = "CMU-1-Small-Region"; var openSlide = new OpenSlide(); //var test = openSlide.GetMPP("CMU-1-Small-Region.svs"); //MPP = microns per pixel SizeL[] levels = openSlide.Levels($"{filename}.svs"); List <SizeL> dimensions = openSlide.Dimensions($"{filename}.svs"); SizeL maxDimensions = dimensions[dimensions.Count - 1]; //Loads DZI file GetDZI(openSlide, maxDimensions.Width, maxDimensions.Height, $"{filename}.svs", filename); for (int level = 0; level < levels.Length; level++) { Directory.CreateDirectory($"{filename}_files/{level}"); SizeL levelInfo = levels[level]; for (int row = 0; row < levelInfo.Width; row++) { for (int col = 0; col < levelInfo.Height; col++) { GetJpg(openSlide, level, row, col, $"{filename}.svs", $"{filename}_files/{level}/{row}_{col}"); } } } Console.WriteLine("Done"); Console.ReadLine(); }
public Image GetThumbnail(SizeL size) { return(GetThumbnail(size.ToSize())); }
public abstract Image GetThumbnail(SizeL maxSize);
/*Returns an Image containing the contents of the region. * location: (x, y) tuple giving the top left pixel in the level 0 reference frame. * level: the level number. * maxSize: (width, height) tuple giving the region maxSize.*/ public abstract Image ReadRegion(SizeL location, int level, SizeL size);
public Image GetTile(int level, SizeL address) { // Read tile CheckParameters(level, address); var col = address.Width; var row = address.Height; // Get preferred slide level var preferedSlideLevel = BestSlideLevelForDeepZoomLevel[level]; // Calculate top left and bottom right overlap var topLeftOverlap = new SizeL(col == 0 ? 0 : DeepZoomOverlap, row == 0 ? 0 : DeepZoomOverlap); var bottomRightOverlap = new SizeL(col == TileDimensions[level].Width - 1 ? 0 : DeepZoomOverlap, row == TileDimensions[level].Height - 1 ? 0 : DeepZoomOverlap); // Get final size of the tile var finalTileWidth = Math.Min(TileSize, DeepZoomLevelDimensions[level].Width - TileSize * col) + topLeftOverlap.Width + bottomRightOverlap.Width; var finalTileHeight = Math.Min(TileSize, DeepZoomLevelDimensions[level].Height - TileSize * row) + topLeftOverlap.Height + bottomRightOverlap.Height; var finalTileSize = new SizeL(finalTileWidth, finalTileHeight); if (finalTileSize.Width < 0 || finalTileSize.Height < 0) { throw new ArgumentException($"out of bounds level {level}, row {row}, col {col}"); } // Obtain the region coordinates var deepZoomLocation = new SizeL(TileSize * col, TileSize * row); var levelLocation = new SizeF( (float)DeepZoomLevelDownsamples[level] * (deepZoomLocation.Width - topLeftOverlap.Width), (float)DeepZoomLevelDownsamples[level] * (deepZoomLocation.Height - topLeftOverlap.Height)); // Round location down and size up, and add offset of active area var level0Location = new SizeL( (long)(Osr.LevelDownsamples[preferedSlideLevel] * levelLocation.Width + Level0Offset.Width), (long)(Osr.LevelDownsamples[preferedSlideLevel] * levelLocation.Height + Level0Offset.Height)); var regionWidth = (long)Math.Min(Math.Ceiling(DeepZoomLevelDownsamples[level] * finalTileSize.Width), LevelDimensions[preferedSlideLevel].Width - Math.Ceiling(levelLocation.Width)); var regionHeight = (long)Math.Min(Math.Ceiling(DeepZoomLevelDownsamples[level] * finalTileSize.Height), LevelDimensions[preferedSlideLevel].Height - Math.Ceiling(levelLocation.Height)); var regionSize = new SizeL(regionWidth, regionHeight); var tileBmp = Osr.ReadRegion(level0Location, preferedSlideLevel, regionSize); //Apply on background color (composite) tileBmp = ApplyOnBackgroundColor(tileBmp); // Scale to the correct size var deepZoomSize = finalTileSize; if (regionSize.Width == deepZoomSize.Width && regionSize.Height == deepZoomSize.Height) { return(tileBmp); } tileBmp = new Bitmap(tileBmp, deepZoomSize.ToSize()); return(tileBmp); }