diff --git a/OpenSlideSharp.Common.props b/OpenSlideSharp.Common.props
index 220240c..4284970 100644
--- a/OpenSlideSharp.Common.props
+++ b/OpenSlideSharp.Common.props
@@ -3,7 +3,6 @@
- 1.0.1.4
IOL0ol1
Copyright © 2021-2022
MIT
diff --git a/OpenSlideSharp.sln b/OpenSlideSharp.sln
index b3bd159..c226c8b 100644
--- a/OpenSlideSharp.sln
+++ b/OpenSlideSharp.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30406.217
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33110.190
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6EE7C68C-65D9-4290-81AE-09BA58C857CD}"
EndProject
@@ -25,7 +25,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenSlideSharp.BitmapExtens
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenSlideSharp.BruTile", "src\OpenSlideSharp.BruTile\OpenSlideSharp.BruTile.csproj", "{9DA7F592-F964-45CB-9E2E-F8028AE3C956}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SlideViewer", "example\SlideViewer\SlideViewer.csproj", "{11D9A92F-2314-407B-A392-18B2290E4972}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlideViewer", "example\SlideViewer\SlideViewer.csproj", "{11D9A92F-2314-407B-A392-18B2290E4972}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenSlideSharp.OpencvExtensions", "src\OpenSlideSharp.OpencvExtensions\OpenSlideSharp.OpencvExtensions.csproj", "{4322CA50-F9C6-4619-8A8F-9D99E5906CCB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -69,6 +71,10 @@ Global
{11D9A92F-2314-407B-A392-18B2290E4972}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11D9A92F-2314-407B-A392-18B2290E4972}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11D9A92F-2314-407B-A392-18B2290E4972}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4322CA50-F9C6-4619-8A8F-9D99E5906CCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4322CA50-F9C6-4619-8A8F-9D99E5906CCB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4322CA50-F9C6-4619-8A8F-9D99E5906CCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4322CA50-F9C6-4619-8A8F-9D99E5906CCB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -83,6 +89,7 @@ Global
{695DED59-4106-424A-9831-2227F0B35BAE} = {6EE7C68C-65D9-4290-81AE-09BA58C857CD}
{9DA7F592-F964-45CB-9E2E-F8028AE3C956} = {6EE7C68C-65D9-4290-81AE-09BA58C857CD}
{11D9A92F-2314-407B-A392-18B2290E4972} = {C3C9459E-1461-4480-B551-AAED7BDAD940}
+ {4322CA50-F9C6-4619-8A8F-9D99E5906CCB} = {6EE7C68C-65D9-4290-81AE-09BA58C857CD}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6D55D41F-7887-4787-BD15-17389C769282}
diff --git a/build/DownloadAndCopy.ps1 b/build/DownloadAndCopy.ps1
index 893431f..e6655ff 100644
--- a/build/DownloadAndCopy.ps1
+++ b/build/DownloadAndCopy.ps1
@@ -1,8 +1,8 @@
param(
-[string]$x86="https://github.com/openslide/openslide-winbuild/releases/download/v20171122/openslide-win32-20171122.zip",
-[string]$x64="https://github.com/openslide/openslide-winbuild/releases/download/v20171122/openslide-win64-20171122.zip",
+[string]$x86="https://github.com/openslide/openslide-winbuild/releases/download/v20221111/openslide-win32-20221111.zip",
+[string]$x64="https://github.com/openslide/openslide-winbuild/releases/download/v20221111/openslide-win64-20221111.zip",
[string]$x86Output="..\openslide\x86\",
[string]$x64Output="..\openslide\x64\")
diff --git a/example/MultiSlideServer/Cache/DeepZoomGeneratorCache.cs b/example/MultiSlideServer/Cache/DeepZoomGeneratorCache.cs
index 5ad26ac..e0797d6 100644
--- a/example/MultiSlideServer/Cache/DeepZoomGeneratorCache.cs
+++ b/example/MultiSlideServer/Cache/DeepZoomGeneratorCache.cs
@@ -1,7 +1,6 @@
-using System;
-
-using Microsoft.Extensions.Caching.Memory;
+using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
+using System;
namespace MultiSlideServer.Cache
{
diff --git a/example/MultiSlideServer/Controllers/HomeController.cs b/example/MultiSlideServer/Controllers/HomeController.cs
index 033b846..86f0a73 100644
--- a/example/MultiSlideServer/Controllers/HomeController.cs
+++ b/example/MultiSlideServer/Controllers/HomeController.cs
@@ -1,9 +1,7 @@
-using System.Linq;
-using System.Text;
-
-using Microsoft.AspNetCore.Mvc;
-
+using Microsoft.AspNetCore.Mvc;
using MultiSlideServer.Cache;
+using System.Linq;
+using System.Text;
namespace MultiSlideServer.Controllers
{
diff --git a/example/MultiSlideServer/ImageProvider.cs b/example/MultiSlideServer/ImageProvider.cs
index b7ca511..86ca4a3 100644
--- a/example/MultiSlideServer/ImageProvider.cs
+++ b/example/MultiSlideServer/ImageProvider.cs
@@ -1,7 +1,6 @@
using Microsoft.Extensions.Options;
using MultiSlideServer.Cache;
using OpenSlideSharp;
-using System;
using System.Collections.Generic;
namespace MultiSlideServer
@@ -53,6 +52,6 @@ public RetainableDeepZoomGenerator RetainDeepZoomGenerator(string name, string p
dz.Dispose();
return dz;
}
-
+
}
}
diff --git a/example/MultiSlideServer/Startup.cs b/example/MultiSlideServer/Startup.cs
index 94bfede..33153a2 100644
--- a/example/MultiSlideServer/Startup.cs
+++ b/example/MultiSlideServer/Startup.cs
@@ -1,17 +1,14 @@
-using System;
-using System.Threading.Tasks;
-
-using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Primitives;
-
using MultiSlideServer.Cache;
-
using OpenSlideSharp;
+using OpenSlideSharp.BitmapExtensions;
+using System;
namespace MultiSlideServer
{
public class Startup
diff --git a/example/SingleSlideServer/ImageOption.cs b/example/SingleSlideServer/ImageOption.cs
index 8f7a1d8..dde9115 100644
--- a/example/SingleSlideServer/ImageOption.cs
+++ b/example/SingleSlideServer/ImageOption.cs
@@ -2,6 +2,6 @@
{
public class ImageOption
{
- public string Path { get; set; }
+ public string Path { get; set; }
}
}
diff --git a/example/SingleSlideServer/ImageProvider.cs b/example/SingleSlideServer/ImageProvider.cs
index 820234d..17d65f6 100644
--- a/example/SingleSlideServer/ImageProvider.cs
+++ b/example/SingleSlideServer/ImageProvider.cs
@@ -1,6 +1,6 @@
-using System;
-using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Options;
using OpenSlideSharp;
+using System;
namespace SingleSlideServer
{
diff --git a/example/SingleSlideServer/Startup.cs b/example/SingleSlideServer/Startup.cs
index ab6106b..d5d93e1 100644
--- a/example/SingleSlideServer/Startup.cs
+++ b/example/SingleSlideServer/Startup.cs
@@ -1,13 +1,11 @@
-using System.Threading.Tasks;
-
-using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Primitives;
-using OpenSlideSharp;
+using OpenSlideSharp.BitmapExtensions;
namespace SingleSlideServer
{
diff --git a/example/SlideViewer/App.xaml b/example/SlideViewer/App.xaml
index f0e50b0..70b4a12 100644
--- a/example/SlideViewer/App.xaml
+++ b/example/SlideViewer/App.xaml
@@ -1,13 +1,17 @@
-
+
-
+
diff --git a/example/SlideViewer/Behaviors/PreviewBehavior.cs b/example/SlideViewer/Behaviors/PreviewBehavior.cs
index a65c27e..5672505 100644
--- a/example/SlideViewer/Behaviors/PreviewBehavior.cs
+++ b/example/SlideViewer/Behaviors/PreviewBehavior.cs
@@ -1,4 +1,11 @@
-using System;
+using Mapsui;
+using Mapsui.Geometries;
+using Mapsui.Layers;
+using Mapsui.Providers;
+using Mapsui.Styles;
+using Mapsui.UI.Wpf;
+using Microsoft.Xaml.Behaviors;
+using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
@@ -7,13 +14,6 @@
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Threading;
-using Mapsui;
-using Mapsui.Geometries;
-using Mapsui.Layers;
-using Mapsui.Providers;
-using Mapsui.Styles;
-using Mapsui.UI.Wpf;
-using Microsoft.Xaml.Behaviors;
using Bitmap = System.Drawing.Bitmap;
using Point = Mapsui.Geometries.Point;
diff --git a/example/SlideViewer/Behaviors/ViewportBehavior.cs b/example/SlideViewer/Behaviors/ViewportBehavior.cs
index 5530d01..7b4fd77 100644
--- a/example/SlideViewer/Behaviors/ViewportBehavior.cs
+++ b/example/SlideViewer/Behaviors/ViewportBehavior.cs
@@ -1,9 +1,15 @@
-using System;
-using System.Windows;
-
-using Mapsui.UI.Wpf;
+using Mapsui.UI.Wpf;
+/* 项目“SlideViewer (netcoreapp3.1)”的未合并的更改
+在此之前:
+using Microsoft.Xaml.Behaviors;
+在此之后:
using Microsoft.Xaml.Behaviors;
+using System;
+using System.Windows;
+*/
+using Microsoft.Xaml.Behaviors;
+using System.Windows;
namespace SlideLibrary.Demo
{
diff --git a/example/SlideViewer/Converters/PointConverter.cs b/example/SlideViewer/Converters/PointConverter.cs
index 646ef65..af86115 100644
--- a/example/SlideViewer/Converters/PointConverter.cs
+++ b/example/SlideViewer/Converters/PointConverter.cs
@@ -1,10 +1,16 @@
-using System;
-using System.Collections.Generic;
+
+/* 项目“SlideViewer (netcoreapp3.1)”的未合并的更改
+在此之前:
+using System;
+在此之后:
+using Mapsui.Geometries;
+using System;
+*/
+using Mapsui.Geometries;
+using System;
using System.Globalization;
using System.Windows.Data;
-using Mapsui.Geometries;
-
namespace SlideLibrary.Demo
{
public class PointConverter : IValueConverter
diff --git a/example/SlideViewer/MainWindow.xaml.cs b/example/SlideViewer/MainWindow.xaml.cs
index 8d7b472..0435e6c 100644
--- a/example/SlideViewer/MainWindow.xaml.cs
+++ b/example/SlideViewer/MainWindow.xaml.cs
@@ -1,4 +1,7 @@
-using System;
+using Mapsui.Fetcher;
+using Microsoft.Win32;
+using OpenSlideSharp.BruTile;
+using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
@@ -9,13 +12,6 @@
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Media;
-
-using Mapsui.Fetcher;
-
-using Microsoft.Win32;
-
-using OpenSlideSharp.BruTile;
-
using Point = Mapsui.Geometries.Point;
namespace SlideLibrary.Demo
diff --git a/example/SlideViewer/Mapsui/SlideSliceLayer.cs b/example/SlideViewer/Mapsui/SlideSliceLayer.cs
index 529e591..b384fce 100644
--- a/example/SlideViewer/Mapsui/SlideSliceLayer.cs
+++ b/example/SlideViewer/Mapsui/SlideSliceLayer.cs
@@ -1,17 +1,14 @@
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-using BruTile;
-
+using BruTile;
using Mapsui;
using Mapsui.Fetcher;
using Mapsui.Geometries;
using Mapsui.Layers;
using Mapsui.Providers;
using Mapsui.Styles;
-
using OpenSlideSharp.BruTile;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
namespace SlideLibrary.Demo
{
diff --git a/example/SlideViewer/Mapsui/SlideTileLayer.cs b/example/SlideViewer/Mapsui/SlideTileLayer.cs
index 10ed906..a6ac2cf 100644
--- a/example/SlideViewer/Mapsui/SlideTileLayer.cs
+++ b/example/SlideViewer/Mapsui/SlideTileLayer.cs
@@ -1,15 +1,12 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-using BruTile;
-
+using BruTile;
using Mapsui.Fetcher;
using Mapsui.Layers;
using Mapsui.Providers;
using Mapsui.Rendering;
-
using OpenSlideSharp.BruTile;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace SlideLibrary.Demo
{
diff --git a/example/SlideViewer/SlideViewer.csproj b/example/SlideViewer/SlideViewer.csproj
index 9a012b6..5365203 100644
--- a/example/SlideViewer/SlideViewer.csproj
+++ b/example/SlideViewer/SlideViewer.csproj
@@ -8,11 +8,12 @@
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/OpenSlideSharp.BitmapExtensions/AssociatedImageExtensions.cs b/src/OpenSlideSharp.BitmapExtensions/AssociatedImageExtensions.cs
index 17f5272..bc80cd2 100644
--- a/src/OpenSlideSharp.BitmapExtensions/AssociatedImageExtensions.cs
+++ b/src/OpenSlideSharp.BitmapExtensions/AssociatedImageExtensions.cs
@@ -2,9 +2,8 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
-using System.Runtime.InteropServices;
-namespace OpenSlideSharp
+namespace OpenSlideSharp.BitmapExtensions
{
///
///
diff --git a/src/OpenSlideSharp.BitmapExtensions/BitmapExtensions.cs b/src/OpenSlideSharp.BitmapExtensions/BitmapExtensions.cs
index cc42dd3..0093ee0 100644
--- a/src/OpenSlideSharp.BitmapExtensions/BitmapExtensions.cs
+++ b/src/OpenSlideSharp.BitmapExtensions/BitmapExtensions.cs
@@ -5,7 +5,7 @@
using System.IO;
using System.Linq;
-namespace OpenSlideSharp
+namespace OpenSlideSharp.BitmapExtensions
{
///
///
@@ -38,7 +38,7 @@ public static MemoryStream ToStream(this Image bitmap, ImageFormat format = null
if (bitmap == null) throw new NullReferenceException();
var ms = new MemoryStream();
EncoderParameters parameters = quality.HasValue ? new EncoderParameters() { Param = new[] { new EncoderParameter(Encoder.Quality, quality.Value) } } : null;
- bitmap.Save(ms, (format??ImageFormat.Jpeg).FindCodec(), parameters);
+ bitmap.Save(ms, (format ?? ImageFormat.Jpeg).FindCodec(), parameters);
ms.Seek(0, SeekOrigin.Begin);
return ms;
}
diff --git a/src/OpenSlideSharp.BitmapExtensions/DeepZoomGeneratorExtensions.cs b/src/OpenSlideSharp.BitmapExtensions/DeepZoomGeneratorExtensions.cs
index d3f936a..4d12cad 100644
--- a/src/OpenSlideSharp.BitmapExtensions/DeepZoomGeneratorExtensions.cs
+++ b/src/OpenSlideSharp.BitmapExtensions/DeepZoomGeneratorExtensions.cs
@@ -2,10 +2,9 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
-using System.Runtime.InteropServices;
using static OpenSlideSharp.DeepZoomGenerator;
-namespace OpenSlideSharp
+namespace OpenSlideSharp.BitmapExtensions
{
///
///
@@ -42,7 +41,7 @@ public static byte[] GetTileAsJpeg(this DeepZoomGenerator generator, int level,
///
public static MemoryStream GetTileAsJpegStream(this DeepZoomGenerator generator, int level, int col, int row, out TileInfo tileInfo, int? quality = null)
{
- return GetTileImage(generator, level, col, row, out tileInfo, quality).ToStream(ImageFormat.Jpeg, quality);
+ return GetTileImage(generator, level, col, row, out tileInfo).ToStream(ImageFormat.Jpeg, quality);
}
@@ -76,7 +75,7 @@ public static byte[] GetTileAsPng(this DeepZoomGenerator generator, int level, i
///
public static MemoryStream GetTileAsPngStream(this DeepZoomGenerator generator, int level, int col, int row, out TileInfo tileInfo, int? quality = null)
{
- return GetTileImage(generator, level, col, row, out tileInfo, quality).ToStream(ImageFormat.Png, quality);
+ return GetTileImage(generator, level, col, row, out tileInfo).ToStream(ImageFormat.Png, quality);
}
///
@@ -87,9 +86,8 @@ public static MemoryStream GetTileAsPngStream(this DeepZoomGenerator generator,
///
///
///
- ///
///
- public unsafe static Bitmap GetTileImage(this DeepZoomGenerator generator, int level, int col, int row, out TileInfo tileInfo, int? quality = null)
+ public unsafe static Bitmap GetTileImage(this DeepZoomGenerator generator, int level, int col, int row, out TileInfo tileInfo)
{
if (generator == null)
throw new NullReferenceException();
diff --git a/src/OpenSlideSharp.BitmapExtensions/JpegExtensions.cs b/src/OpenSlideSharp.BitmapExtensions/JpegExtensions.cs
new file mode 100644
index 0000000..54b2948
--- /dev/null
+++ b/src/OpenSlideSharp.BitmapExtensions/JpegExtensions.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Drawing;
+using System.Drawing.Imaging;
+
+namespace OpenSlideSharp.BitmapExtensions
+{
+ ///
+ ///
+ ///
+ public class JpegExtensions
+ {
+ ///
+ /// BGR/BGRA convert to jpeg
+ ///
+ /// BGR/BGRA
+ /// bytes per pixel
+ /// bytes per line
+ /// width
+ /// height
+ /// dst width
+ /// dst height
+ /// jpeg quality
+ ///
+ public static unsafe byte[] GetJpeg(byte[] bgraBytes, int bytesPerPixel, int bytesPerLine, int width, int height, int dstWidth = 0, int dstHeight = 0, int? quality = null)
+ {
+ if (bgraBytes == null) return null;
+ if (bytesPerPixel != 3 && bytesPerPixel != 4) throw new ArgumentException(nameof(bytesPerPixel));
+ var pixel = bytesPerPixel == 3 ? PixelFormat.Format24bppRgb : PixelFormat.Format32bppRgb;
+ fixed (byte* scan0 = bgraBytes)
+ {
+ using (var bmp = new Bitmap(width, height, bytesPerLine, pixel, (IntPtr)scan0))
+ {
+
+ if ((dstWidth <= 0 && dstHeight <= 0) || (dstWidth == width && dstHeight == height))
+ {
+ return bmp.ToStream(ImageFormat.Jpeg, quality).ToArray();
+ }
+ else // fill
+ {
+ using (var dstImage = new Bitmap(dstWidth, dstHeight))
+ using (var g = Graphics.FromImage(dstImage))
+ {
+ g.Clear(Color.White);
+ g.DrawImage(bmp, new Point(0, 0));
+ return dstImage.ToStream(ImageFormat.Jpeg, quality).ToArray();
+ }
+ }
+ }
+ }
+ }
+
+ }
+}
diff --git a/src/OpenSlideSharp.BitmapExtensions/OpenSlideImageExtensions.cs b/src/OpenSlideSharp.BitmapExtensions/OpenSlideImageExtensions.cs
index 208c66b..a1ece4b 100644
--- a/src/OpenSlideSharp.BitmapExtensions/OpenSlideImageExtensions.cs
+++ b/src/OpenSlideSharp.BitmapExtensions/OpenSlideImageExtensions.cs
@@ -2,9 +2,8 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
-using System.Runtime.InteropServices;
-namespace OpenSlideSharp
+namespace OpenSlideSharp.BitmapExtensions
{
///
///
diff --git a/src/OpenSlideSharp.BitmapExtensions/OpenSlideSharp.BitmapExtensions.csproj b/src/OpenSlideSharp.BitmapExtensions/OpenSlideSharp.BitmapExtensions.csproj
index 29fe3c4..c367b43 100644
--- a/src/OpenSlideSharp.BitmapExtensions/OpenSlideSharp.BitmapExtensions.csproj
+++ b/src/OpenSlideSharp.BitmapExtensions/OpenSlideSharp.BitmapExtensions.csproj
@@ -3,7 +3,7 @@
- net35;netstandard2.0;netstandard2.1;net5.0
+ net35;netstandard2.0;netstandard2.1
true
true
true
@@ -12,27 +12,20 @@
OpenSlideSharp bitmap extensions
OpenSlideSharp bitmap extensions
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
+ 1.1.0
-
-
- 5.0.2
+ [5.0.0,)
- 5.0.2
-
-
-
-
-
- 5.0.2
+ [5.0.0,)
-
+
diff --git a/src/OpenSlideSharp.BruTile/ISlideSource.cs b/src/OpenSlideSharp.BruTile/ISlideSource.cs
index 3f1928c..2795f75 100644
--- a/src/OpenSlideSharp.BruTile/ISlideSource.cs
+++ b/src/OpenSlideSharp.BruTile/ISlideSource.cs
@@ -1,13 +1,11 @@
-using System;
+using BruTile;
+using BruTile.Cache;
+using OpenCvSharp;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using BruTile;
-using BruTile.Cache;
-
-using OpenCvSharp;
-
namespace OpenSlideSharp.BruTile
{
diff --git a/src/OpenSlideSharp.BruTile/OpenSlideBase.cs b/src/OpenSlideSharp.BruTile/OpenSlideBase.cs
index 896beb3..6fbe228 100644
--- a/src/OpenSlideSharp.BruTile/OpenSlideBase.cs
+++ b/src/OpenSlideSharp.BruTile/OpenSlideBase.cs
@@ -1,11 +1,9 @@
-using System;
+using BruTile;
+using BruTile.Cache;
+using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
-using BruTile;
-using BruTile.Cache;
-
namespace OpenSlideSharp.BruTile
{
public class OpenSlideBase : SlideSourceBase
@@ -89,8 +87,8 @@ protected void InitResolutions(IDictionary resolutions, int til
{
for (int i = 0; i < SlideImage.LevelCount; i++)
{
- bool useInternalWidth = int.TryParse(ExternInfo[$"openslide.level[{i}].tile-width"].ToString(), out var w) && w >= tileWidth;
- bool useInternalHeight = int.TryParse(ExternInfo[$"openslide.level[{i}].tile-height"].ToString(), out var h) && h >= tileHeight;
+ bool useInternalWidth = int.TryParse(ExternInfo.TryGetValue($"openslide.level[{i}].tile-width", out var _w) ? (string)_w : null, out var w) && w >= tileWidth;
+ bool useInternalHeight = int.TryParse(ExternInfo.TryGetValue($"openslide.level[{i}].tile-height", out var _h) ? (string)_h : null, out var h) && h >= tileHeight;
bool useInternalSize = useInternalHeight && useInternalWidth;
var tw = useInternalSize ? w : tileWidth;
diff --git a/src/OpenSlideSharp.BruTile/OpenSlideSharp.BruTile.csproj b/src/OpenSlideSharp.BruTile/OpenSlideSharp.BruTile.csproj
index 7964ba0..8f5d123 100644
--- a/src/OpenSlideSharp.BruTile/OpenSlideSharp.BruTile.csproj
+++ b/src/OpenSlideSharp.BruTile/OpenSlideSharp.BruTile.csproj
@@ -3,9 +3,9 @@
- net461;netstandard2.0;netstandard2.1;net5.0
+ netstandard2.0;netstandard2.1
true
- 1701;1702;1591
+ 1701;1702;1591;NU1603
true
true
OpenSlideSharp.BruTile
@@ -13,19 +13,14 @@
OpenSlideSharp for BruTile
OpenSlideSharp for BruTile
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
+ 1.1.0
-
-
-
-
-
-
+
+
-
-
diff --git a/src/OpenSlideSharp.BruTile/Utilities.cs b/src/OpenSlideSharp.BruTile/Utilities.cs
index 24c0c07..d8e03c2 100644
--- a/src/OpenSlideSharp.BruTile/Utilities.cs
+++ b/src/OpenSlideSharp.BruTile/Utilities.cs
@@ -1,16 +1,9 @@
-using System;
+using BruTile;
+using OpenCvSharp;
+using System;
using System.Collections.Generic;
-using System.Drawing;
-using System.Drawing.Imaging;
-using System.IO;
using System.Linq;
-using System.Reflection;
-
-using BruTile;
-
-using OpenCvSharp;
-
-using Point = System.Drawing.Point;
+using Range = OpenCvSharp.Range;
namespace OpenSlideSharp.BruTile
{
@@ -20,7 +13,7 @@ public class ImageUtil
///
/// BGR/BGRA convert to jpeg
///
- /// BGR/BGRA
+ /// BGR/BGRA
/// bytes per pixel
/// bytes per line
/// width
@@ -28,35 +21,64 @@ public class ImageUtil
/// dst width
/// dst height
/// jpeg quality
+ /// background color for transparent if == 4
///
- public static unsafe byte[] GetJpeg(byte[] raw, int bytesPerPixel, int bytesPerLine, int width, int height, int dstWidth = 0, int dstHeight = 0, int? quality = null)
+ public static unsafe byte[] GetJpeg(byte[] bgraBytes, int bytesPerPixel, int bytesPerLine, int width, int height, int dstWidth = 0, int dstHeight = 0, int? quality = null, uint background = 0xFFFFFFFF)
{
- if (raw == null) return null;
+ if (bgraBytes == null) return null;
if (bytesPerPixel != 3 && bytesPerPixel != 4) throw new ArgumentException(nameof(bytesPerPixel));
- var pixel = bytesPerPixel == 3 ? PixelFormat.Format24bppRgb : PixelFormat.Format32bppRgb;
- fixed (byte* scan0 = raw)
+ var prms = quality != null ? new int[] { (int)ImwriteFlags.JpegQuality, quality.Value } : null;
+ var pixel = MatType.CV_8UC(bytesPerPixel);
+ fixed (byte* scan0 = bgraBytes)
{
- using (var bmp = new Bitmap(width, height, bytesPerLine, pixel, (IntPtr)scan0))
+ using (var src = new Mat(height, width, pixel, (IntPtr)scan0, bytesPerLine))
{
-
+ // black transparent to background
+ if (pixel.Channels == 4)
+ {
+ unchecked
+ {
+ src.ForEachAsInt32((_i, _p) =>
+ {
+ if (*_i == 0) *_i = (Int32)(background);
+ });
+ }
+ }
if ((dstWidth <= 0 && dstHeight <= 0) || (dstWidth == width && dstHeight == height))
{
- return bmp.ToArray(ImageFormat.Jpeg, quality);
+ return src.ToBytes(".jpg", prms);
}
- else // fill
+ else // fill
{
- using (var dstImage = new Bitmap(dstWidth, dstHeight))
- using (var g = Graphics.FromImage(dstImage))
+ var scalar = new Scalar((int)(background >> 24 & 0xFF), (int)(background >> 16 & 0xFF), (int)(background >> 8 & 0xFF), (int)(background & 0xFF));
+ using (var dst = new Mat(dstHeight, dstWidth, pixel, scalar))
{
- g.Clear(Color.White);
- g.DrawImage(bmp, new Point(0, 0));
- return dstImage.ToArray(ImageFormat.Jpeg, quality);
+ DrawImage(src, dst);
+ return dst.ToBytes(".jpg", prms);
}
}
}
}
}
+ ///
+ /// Fill the source image with adaptive scaling to the target image
+ ///
+ ///
+ ///
+ private static void DrawImage(Mat src, Mat dst)
+ {
+ var fx = (double)dst.Width / src.Width;
+ var fy = (double)dst.Height / src.Height;
+ var fmin = Math.Min(fx, fy);
+ using (var srcResized = src.Resize(new Size(src.Width * fmin, src.Height * fmin)))
+ {
+ using (var sub = new Mat(dst, new Rect(0, 0, srcResized.Width, srcResized.Height)))
+ {
+ srcResized.CopyTo(sub);
+ }
+ }
+ }
///
/// Join by and cut by then scale to (only height an width is useful).
@@ -125,6 +147,15 @@ public static byte[] Join(IEnumerable> srcPixelTiles, Extent
public class TileUtil
{
+ ///
+ /// To ensure image quality, try to use high-resolution level downsampling to low-resolution level
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public static int GetLevel(IDictionary resolutions, double unitsPerPixel, SampleMode sampleMode = SampleMode.Nearest)
{
if (resolutions.Count == 0)
@@ -179,40 +210,4 @@ public static int GetLevel(IDictionary resolutions, double unit
}
}
}
-
- public static class BitmapEx
- {
- private static IDictionary> encoders = new Dictionary>();
-
- static BitmapEx()
- {
- ImageCodecInfo[] array = ImageCodecInfo.GetImageEncoders();
- foreach (var coder in array)
- {
- if (encoders.ContainsKey(coder.FormatID))
- encoders[coder.FormatID].Add(coder);
- else
- encoders[coder.FormatID] = new List(new[] { coder });
- }
- }
-
- public static byte[] ToArray(this Image bitmap, ImageFormat format, int? quality = null)
- {
- using (var ms = new MemoryStream())
- {
- EncoderParameters parameters = quality.HasValue ? new EncoderParameters() { Param = new[] { new EncoderParameter(Encoder.Quality, quality.Value) } } : null;
- bitmap.Save(ms, format?.FindCodec(), parameters);
- return ms.GetBuffer();
- }
- }
-
- public static ImageCodecInfo FindCodec(this ImageFormat format)
- {
- if (encoders.ContainsKey(format.Guid))
- return encoders[format.Guid].FirstOrDefault();
-
- return null;
- }
- }
-
}
diff --git a/src/OpenSlideSharp.OpencvExtensions/AssociatedImageExtensions.cs b/src/OpenSlideSharp.OpencvExtensions/AssociatedImageExtensions.cs
new file mode 100644
index 0000000..09c537d
--- /dev/null
+++ b/src/OpenSlideSharp.OpencvExtensions/AssociatedImageExtensions.cs
@@ -0,0 +1,94 @@
+using OpenCvSharp;
+using System;
+using System.IO;
+
+namespace OpenSlideSharp.OpencvExtensions
+{
+ ///
+ ///
+ ///
+ public static class AssociatedImageExtensions
+ {
+ ///
+ /// To mat.
+ ///
+ ///
+ ///
+ public unsafe static Mat ToMat(this AssociatedImage image)
+ {
+ if (image == null) throw new NullReferenceException();
+ fixed (byte* scan0 = image.Data)
+ {
+ return new Mat((int)image.Dimensions.Height, (int)image.Dimensions.Width, MatType.CV_8UC4, (IntPtr)scan0, (int)image.Dimensions.Width * 4);
+ }
+ }
+
+ ///
+ /// To jpeg array
+ ///
+ ///
+ ///
+ /// For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default
+ /// value is 95.
+ ///
+ ///
+
+ public static byte[] ToJpeg(this AssociatedImage image, int? quality = null)
+ {
+ var prms = quality != null ? new int[] { (int)ImwriteFlags.JpegQuality, quality.Value } : null;
+ using (var mat = ToMat(image))
+ {
+ return mat.ToBytes(".jpg", prms);
+ }
+ }
+
+ ///
+ /// To jpeg stream
+ ///
+ ///
+ ///
+ /// For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default
+ /// value is 95.
+ ///
+ ///
+
+ public static MemoryStream ToJpegStream(this AssociatedImage image, int? quality = null)
+ {
+ return new MemoryStream(ToJpeg(image, quality));
+ }
+
+ ///
+ /// To png array.
+ ///
+ ///
+ ///
+ /// For PNG, it can be the compression level from 0 to 9. A higher value means a
+ /// smaller size and longer compression time. Default value is 3.
+ ///
+ ///
+ public static byte[] ToPng(this AssociatedImage image, int? quality = null)
+ {
+ var prms = quality != null ? new int[] { (int)ImwriteFlags.PngCompression, quality.Value } : null;
+ using (var mat = ToMat(image))
+ {
+ return mat.ToBytes(".png", prms);
+ }
+ }
+
+ ///
+ /// To png stream.
+ ///
+ ///
+ ///
+ /// For PNG, it can be the compression level from 0 to 9. A higher value means a
+ /// smaller size and longer compression time. Default value is 3.
+ ///
+ ///
+ public static MemoryStream ToPngStream(this AssociatedImage image, int? quality = null)
+ {
+ return new MemoryStream(ToPng(image, quality));
+ }
+ }
+
+
+}
diff --git a/src/OpenSlideSharp.OpencvExtensions/DeepZoomGeneratorExtensions.cs b/src/OpenSlideSharp.OpencvExtensions/DeepZoomGeneratorExtensions.cs
new file mode 100644
index 0000000..aa25d85
--- /dev/null
+++ b/src/OpenSlideSharp.OpencvExtensions/DeepZoomGeneratorExtensions.cs
@@ -0,0 +1,108 @@
+using OpenCvSharp;
+using System;
+using System.IO;
+using static OpenSlideSharp.DeepZoomGenerator;
+
+namespace OpenSlideSharp.OpencvExtensions
+{
+ ///
+ ///
+ ///
+ public static class DeepZoomGeneratorExtensions
+ {
+ ///
+ /// Get tile as jpeg.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default
+ /// value is 95.
+ ///
+ public static byte[] GetTileAsJpeg(this DeepZoomGenerator generator, int level, int col, int row, out TileInfo tileInfo, int? quality = null)
+ {
+ using (var mat = GetTileImage(generator, level, col, row, out tileInfo))
+ {
+ var prms = quality != null ? new int[] { (int)ImwriteFlags.JpegQuality, quality.Value } : null;
+ return mat.ToBytes(".jpg", prms);
+ }
+ }
+
+ ///
+ /// Get tile as jpeg stream.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default
+ /// value is 95.
+ ///
+ public static MemoryStream GetTileAsJpegStream(this DeepZoomGenerator generator, int level, int col, int row, out TileInfo tileInfo, int? quality = null)
+ {
+ return new MemoryStream(GetTileAsJpeg(generator, level, col, row, out tileInfo, quality));
+ }
+
+ ///
+ /// Get tile as png.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For PNG, it can be the compression level from 0 to 9. A higher value means a
+ /// smaller size and longer compression time. Default value is 3.
+ ///
+ ///
+ public static byte[] GetTileAsPng(this DeepZoomGenerator generator, int level, int col, int row, out TileInfo tileInfo, int? quality = null)
+ {
+ using (var mat = GetTileImage(generator, level, col, row, out tileInfo))
+ {
+ var prms = quality != null ? new int[] { (int)ImwriteFlags.PngCompression, quality.Value } : null;
+ return mat.ToBytes(".png", prms);
+ }
+ }
+
+ ///
+ /// Get tile as png stream.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For PNG, it can be the compression level from 0 to 9. A higher value means a
+ /// smaller size and longer compression time. Default value is 3.
+ ///
+ public static MemoryStream GetTileAsPngStream(this DeepZoomGenerator generator, int level, int col, int row, out TileInfo tileInfo, int? quality = null)
+ {
+ return new MemoryStream(GetTileAsPng(generator, level, col, row, out tileInfo, quality));
+ }
+
+ ///
+ /// Get tile mat.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public unsafe static Mat GetTileImage(this DeepZoomGenerator generator, int level, int col, int row, out TileInfo tileInfo)
+ {
+ if (generator == null)
+ throw new NullReferenceException();
+ var raw = generator.GetTile(level, col, row, out tileInfo);
+ fixed (byte* scan0 = raw)
+ {
+ return new Mat((int)tileInfo.Height, (int)tileInfo.Width, MatType.CV_8UC4, (IntPtr)scan0, (int)tileInfo.Width * 4);
+ }
+ }
+ }
+}
diff --git a/src/OpenSlideSharp.OpencvExtensions/JpegExtensions.cs b/src/OpenSlideSharp.OpencvExtensions/JpegExtensions.cs
new file mode 100644
index 0000000..2d29b21
--- /dev/null
+++ b/src/OpenSlideSharp.OpencvExtensions/JpegExtensions.cs
@@ -0,0 +1,81 @@
+using OpenCvSharp;
+using System;
+
+namespace OpenSlideSharp.OpencvExtensions
+{
+ ///
+ ///
+ ///
+ public class JpegExtensions
+ {
+ ///
+ /// BGR/BGRA convert to jpeg
+ ///
+ /// BGR/BGRA
+ /// bytes per pixel
+ /// bytes per line
+ /// width
+ /// height
+ /// dst width
+ /// dst height
+ /// jpeg quality
+ /// background color for transparent if == 4
+ ///
+ public static unsafe byte[] GetJpeg(byte[] bgraBytes, int bytesPerPixel, int bytesPerLine, int width, int height, int dstWidth = 0, int dstHeight = 0, int? quality = null, uint background = 0xFFFFFFFF)
+ {
+ if (bgraBytes == null) return null;
+ if (bytesPerPixel != 3 && bytesPerPixel != 4) throw new ArgumentException(nameof(bytesPerPixel));
+ var prms = quality != null ? new int[] { (int)ImwriteFlags.JpegQuality, quality.Value } : null;
+ var pixel = MatType.CV_8UC(bytesPerPixel);
+ fixed (byte* scan0 = bgraBytes)
+ {
+ using (var src = new Mat(height, width, pixel, (IntPtr)scan0, bytesPerLine))
+ {
+ // black transparent to background
+ if (pixel.Channels == 4)
+ {
+ unchecked
+ {
+ src.ForEachAsInt32((_i, _p) =>
+ {
+ if (*_i == 0) *_i = (Int32)(background);
+ });
+ }
+ }
+ if ((dstWidth <= 0 && dstHeight <= 0) || (dstWidth == width && dstHeight == height))
+ {
+ return src.ToBytes(".jpg", prms);
+ }
+ else // fill
+ {
+ var scalar = new Scalar((int)(background >> 24 & 0xFF), (int)(background >> 16 & 0xFF), (int)(background >> 8 & 0xFF), (int)(background & 0xFF));
+ using (var dst = new Mat(dstHeight, dstWidth, pixel, scalar))
+ {
+ DrawImage(src, dst);
+ return dst.ToBytes(".jpg", prms);
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Fill the source image with adaptive scaling to the target image
+ ///
+ ///
+ ///
+ private static void DrawImage(Mat src, Mat dst)
+ {
+ var fx = (double)dst.Width / src.Width;
+ var fy = (double)dst.Height / src.Height;
+ var fmin = Math.Min(fx, fy);
+ using (var srcResized = src.Resize(new Size(src.Width * fmin, src.Height * fmin)))
+ {
+ using (var sub = new Mat(dst, new Rect(0, 0, srcResized.Width, srcResized.Height)))
+ {
+ srcResized.CopyTo(sub);
+ }
+ }
+ }
+ }
+}
diff --git a/src/OpenSlideSharp.OpencvExtensions/OpenSlideImageExtensions.cs b/src/OpenSlideSharp.OpencvExtensions/OpenSlideImageExtensions.cs
new file mode 100644
index 0000000..6c59460
--- /dev/null
+++ b/src/OpenSlideSharp.OpencvExtensions/OpenSlideImageExtensions.cs
@@ -0,0 +1,228 @@
+using OpenCvSharp;
+using System;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+
+namespace OpenSlideSharp.OpencvExtensions
+{
+ ///
+ ///
+ ///
+ public static class OpenSlideImageExtensions
+ {
+ ///
+ /// Read region mat.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public unsafe static Mat ReadRegionImage(this OpenSlideImage image, int level, long x, long y, long width, long height)
+ {
+ if (image == null) throw new NullReferenceException();
+ var data = image.ReadRegion(level, x, y, width, height);
+ fixed (byte* scan0 = data)
+ {
+ return new Mat((int)height, (int)width, MatType.CV_8UC4, (IntPtr)scan0, (int)width * 4);
+ }
+ }
+
+ ///
+ /// Read region jpeg stream.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default
+ /// value is 95.
+ ///
+ public unsafe static MemoryStream ReadRegionJpegStream(this OpenSlideImage image, int level, long x, long y, long width, long height, int? quality = null)
+ {
+ return new MemoryStream(ReadRegionJpeg(image, level, x, y, width, height, quality));
+ }
+
+ ///
+ /// Read region jpeg
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default
+ /// value is 95.
+ ///
+
+ public unsafe static byte[] ReadRegionJpeg(this OpenSlideImage image, int level, long x, long y, long width, long height, int? quality = null)
+ {
+ var prms = quality != null ? new int[] { (int)ImwriteFlags.JpegQuality, quality.Value } : null;
+ return ReadRegionImage(image, level, x, y, width, height).ToBytes(".jpg", prms);
+ }
+
+ ///
+ /// Read region png stream.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For PNG, it can be the compression level from 0 to 9. A higher value means a
+ /// smaller size and longer compression time. Default value is 3.
+ ///
+ ///
+ public unsafe static MemoryStream ReadRegionPngStream(this OpenSlideImage image, int level, long x, long y, long width, long height, int? quality = null)
+ {
+ return new MemoryStream(ReadRegionPng(image, level, x, y, width, height, quality));
+ }
+
+ ///
+ /// Read region png.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For PNG, it can be the compression level from 0 to 9. A higher value means a
+ /// smaller size and longer compression time. Default value is 3.
+ ///
+ public unsafe static byte[] ReadRegionPng(this OpenSlideImage image, int level, long x, long y, long width, long height, int? quality = null)
+ {
+ var prms = quality != null ? new int[] { (int)ImwriteFlags.PngCompression, quality.Value } : null;
+ return ReadRegionImage(image, level, x, y, width, height).ToBytes(".png", prms);
+ }
+
+ ///
+ /// Generate thumbnail image.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Mat GenerateThumbnailImage(this OpenSlideImage image, int maxWidth, int maxHeight)
+ {
+ if (image == null) throw new NullReferenceException();
+
+ (long width, long height) = image.Dimensions;
+
+ // Find the appropriate level
+ double downsampleWidth = width / (double)maxWidth;
+ double downsampleHeight = height / (double)maxHeight;
+ double downsample = Math.Max(downsampleWidth, downsampleHeight);
+ int level = image.GetBestLevelForDownsample(downsample);
+ (long levelWidth, long levelHeight) = image.GetLevelDimension(level);
+
+ // Calculate target size
+ int targetWidth, targetHeight;
+ if (downsampleWidth > downsampleHeight)
+ {
+ targetWidth = maxWidth;
+ targetHeight = (int)(height / downsampleWidth);
+ }
+ else
+ {
+ targetWidth = (int)(width / downsampleHeight);
+ targetHeight = maxHeight;
+ }
+
+ var bitmap = ReadRegionImage(image, level, 0, 0, levelWidth, levelHeight);
+ bitmap.Resize(targetWidth, targetHeight);
+ return bitmap;
+ }
+
+ ///
+ /// Generate thumbnail jpeg stream.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default
+ /// value is 95.
+ ///
+ public static MemoryStream GenerateThumbnailJpegStream(this OpenSlideImage image, int maxWidth, int maxHeight, out int targetWidth, out int targetHeight, int? quality = null)
+ {
+ return new MemoryStream(GenerateThumbnailJpeg(image, maxWidth, maxHeight, out targetWidth, out targetHeight, quality));
+ }
+
+ ///
+ /// Generate thumbnail jpeg.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default
+ /// value is 95.
+ ///
+ public static byte[] GenerateThumbnailJpeg(this OpenSlideImage image, int maxWidth, int maxHeight, out int targetWidth, out int targetHeight, int? quality = null)
+ {
+ using (var bitmap = GenerateThumbnailImage(image, maxWidth, maxHeight))
+ {
+ targetWidth = bitmap.Width;
+ targetHeight = bitmap.Height;
+ var prms = quality != null ? new int[] { (int)ImwriteFlags.JpegQuality, quality.Value } : null;
+ return bitmap.ToBytes(".jpg", prms);
+ }
+ }
+
+ ///
+ /// Generate thumbail png stream.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For PNG, it can be the compression level from 0 to 9. A higher value means a
+ /// smaller size and longer compression time. Default value is 3.
+ ///
+ ///
+ public static MemoryStream GenerateThumbnailPngStream(this OpenSlideImage image, int maxWidth, int maxHeight, out int targetWidth, out int targetHeight, int? quality = null)
+ {
+ return new MemoryStream(GenerateThumbnailPng(image, maxWidth, maxHeight, out targetWidth, out targetHeight, quality));
+ }
+
+ ///
+ /// Generate thumbnail png.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For PNG, it can be the compression level from 0 to 9. A higher value means a
+ /// smaller size and longer compression time. Default value is 3.
+ ///
+ ///
+ public static byte[] GenerateThumbnailPng(this OpenSlideImage image, int maxWidth, int maxHeight, out int targetWidth, out int targetHeight, int? quality = null)
+ {
+ using (var bitmap = GenerateThumbnailImage(image, maxWidth, maxHeight))
+ {
+ targetWidth = bitmap.Width;
+ targetHeight = bitmap.Height;
+ var prms = quality != null ? new int[] { (int)ImwriteFlags.PngCompression, quality.Value } : null;
+ return bitmap.ToBytes(".png", prms);
+ }
+ }
+ }
+
+
+}
diff --git a/src/OpenSlideSharp.OpencvExtensions/OpenSlideSharp.OpencvExtensions.csproj b/src/OpenSlideSharp.OpencvExtensions/OpenSlideSharp.OpencvExtensions.csproj
new file mode 100644
index 0000000..66a6a59
--- /dev/null
+++ b/src/OpenSlideSharp.OpencvExtensions/OpenSlideSharp.OpencvExtensions.csproj
@@ -0,0 +1,28 @@
+
+
+
+
+
+ netstandard2.0;netstandard2.1
+ true
+ true
+ true
+ OpenSlideSharp.OpenCVExtensions
+ openslide image
+ OpenSlideSharp opencv extensions
+ OpenSlideSharp opencv mat extensions
+ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
+ 1.1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/OpenSlideSharp.Windows/OpenSlideSharp.Windows.csproj b/src/OpenSlideSharp.Windows/OpenSlideSharp.Windows.csproj
index 4abb2bd..0dbe2e2 100644
--- a/src/OpenSlideSharp.Windows/OpenSlideSharp.Windows.csproj
+++ b/src/OpenSlideSharp.Windows/OpenSlideSharp.Windows.csproj
@@ -3,7 +3,7 @@
- net35;netstandard2.0;netstandard2.1;net5.0-windows
+ net35;netstandard2.0;netstandard2.1
true
false
OpenSlideSharp.Windows
@@ -11,11 +11,12 @@
OpenSlideSharp all in one package for Windows
OpenSlideSharp all in one package for Windows
1701;1702;NU5128;
+ 1.1.0
-
+
diff --git a/src/OpenSlideSharp.runtime.win/OpenSlideSharp.runtime.win.csproj b/src/OpenSlideSharp.runtime.win/OpenSlideSharp.runtime.win.csproj
index 32ffb41..ffa96f5 100644
--- a/src/OpenSlideSharp.runtime.win/OpenSlideSharp.runtime.win.csproj
+++ b/src/OpenSlideSharp.runtime.win/OpenSlideSharp.runtime.win.csproj
@@ -3,7 +3,7 @@
- net35;netstandard2.0;netstandard2.1;net5.0-windows
+ net35;netstandard2.0;netstandard2.1
true
false
OpenSlideSharp.runtime.win
@@ -11,6 +11,7 @@
OpenSlideSharp runtime in Windows
OpenSlideSharp runtime in Windows
1701;1702;NU5128;
+ 1.1.0
diff --git a/src/OpenSlideSharp.runtime.win/OpenSlideSharp.runtime.win.targets b/src/OpenSlideSharp.runtime.win/OpenSlideSharp.runtime.win.targets
index f1c1037..5012b13 100644
--- a/src/OpenSlideSharp.runtime.win/OpenSlideSharp.runtime.win.targets
+++ b/src/OpenSlideSharp.runtime.win/OpenSlideSharp.runtime.win.targets
@@ -13,8 +13,8 @@
openslide\x64\libcairo-2.dll
Always
-
- openslide\x64\libffi-6.dll
+
+ openslide\x64\libffi-8.dll
Always
@@ -57,6 +57,10 @@
openslide\x64\libopenslide-0.dll
Always
+
+ openslide\x64\libpcre2-8-0.dll
+ Always
+
openslide\x64\libpixman-1-0.dll
Always
@@ -69,10 +73,18 @@
openslide\x64\libsqlite3-0.dll
Always
+
+ openslide\x64\libssp-0.dll
+ Always
+
openslide\x64\libtiff-5.dll
Always
+
+ openslide\x64\libwinpthread-1.dll
+ Always
+
openslide\x64\libxml2-2.dll
Always
@@ -96,8 +108,8 @@
openslide\x86\libcairo-2.dll
Always
-
- openslide\x86\libffi-6.dll
+
+ openslide\x86\libffi-8.dll
Always
@@ -140,6 +152,10 @@
openslide\x86\libopenslide-0.dll
Always
+
+ openslide\x86\libpcre2-8-0.dll
+ Always
+
openslide\x86\libpixman-1-0.dll
Always
@@ -152,10 +168,18 @@
openslide\x86\libsqlite3-0.dll
Always
+
+ openslide\x86\libssp-0.dll
+ Always
+
openslide\x86\libtiff-5.dll
Always
+
+ openslide\x86\libwinpthread-1.dll
+ Always
+
openslide\x86\libxml2-2.dll
Always
diff --git a/src/OpenSlideSharp/DeepZoomGenerator.cs b/src/OpenSlideSharp/DeepZoomGenerator.cs
index 94e4699..1e12179 100644
--- a/src/OpenSlideSharp/DeepZoomGenerator.cs
+++ b/src/OpenSlideSharp/DeepZoomGenerator.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
namespace OpenSlideSharp
diff --git a/src/OpenSlideSharp/OpenSlideImage.cs b/src/OpenSlideSharp/OpenSlideImage.cs
index 37373f8..e699b5f 100644
--- a/src/OpenSlideSharp/OpenSlideImage.cs
+++ b/src/OpenSlideSharp/OpenSlideImage.cs
@@ -1,11 +1,10 @@
-using System;
+using OpenSlideSharp.Interop;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
-using OpenSlideSharp.Interop;
-
namespace OpenSlideSharp
{
///
@@ -57,12 +56,15 @@ public OpenSlideImage(IntPtr handle, bool isOwner = true)
///
public static void Initialize(string path = null)
{
- path = string.IsNullOrEmpty(path) ? Path.Combine("openslide", $"{(IntPtr.Size == 8 ? "x64" : "x86")}") : path;
- path = Path.Combine(Directory.GetParent(Assembly.GetCallingAssembly().Location)?.FullName, path);
+ var openslide = Path.Combine(Directory.GetParent(Assembly.GetCallingAssembly().Location)?.FullName, Path.Combine("openslide", $"{(IntPtr.Size == 8 ? "x64" : "x86")}"));
+ path = string.IsNullOrEmpty(path) ? openslide : path;
if (Directory.Exists(path))
{
var PATH = Environment.GetEnvironmentVariable("PATH");
- Environment.SetEnvironmentVariable("PATH", $"{PATH};{path}");
+ if (!PATH.ToUpper().Contains(path.ToUpper()))
+ {
+ Environment.SetEnvironmentVariable("PATH", $"{PATH};{path}");
+ }
}
}
static OpenSlideImage()
diff --git a/src/OpenSlideSharp/OpenSlideSharp.csproj b/src/OpenSlideSharp/OpenSlideSharp.csproj
index faa7ad2..7f04481 100644
--- a/src/OpenSlideSharp/OpenSlideSharp.csproj
+++ b/src/OpenSlideSharp/OpenSlideSharp.csproj
@@ -3,7 +3,7 @@
- net35;netstandard2.0;netstandard2.1;net5.0
+ net35;netstandard2.0;netstandard2.1
true
true
true
@@ -12,6 +12,7 @@
.NET bindings for OpenSlide(https://openslide.org/), include DeepZoomGenerator
.NET bindings for OpenSlide(https://openslide.org/), include DeepZoomGenerator
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
+ 1.1.0
diff --git a/test/OpenSlideSharp.Tests/OpenSlideSharp.Tests.csproj b/test/OpenSlideSharp.Tests/OpenSlideSharp.Tests.csproj
index 076aded..b0a5c98 100644
--- a/test/OpenSlideSharp.Tests/OpenSlideSharp.Tests.csproj
+++ b/test/OpenSlideSharp.Tests/OpenSlideSharp.Tests.csproj
@@ -13,13 +13,13 @@
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all