Skip to content

Commit 5090570

Browse files
committed
#416 : Add Scale option to all image export extensions
- `Scale` will not increase DPI, but increase image resolution while keeping DPI constant. When the image is then resized to a smaller resolution, this should have the same effect as increasing DPI. - Add tests for Image export file creation
1 parent 11456b4 commit 5090570

File tree

6 files changed

+135
-91
lines changed

6 files changed

+135
-91
lines changed

Diff for: src/Plotly.NET.CSharp/Plotly.NET.CSharp.csproj

-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
<AssemblyOriginatorKeyFile>../../key.snk</AssemblyOriginatorKeyFile>
1919
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
2020
<SignAssembly>true</SignAssembly>
21-
<AssemblyOriginatorKeyFile>../../key.snk</AssemblyOriginatorKeyFile>
2221
</PropertyGroup>
2322

2423
<PropertyGroup>

Diff for: src/Plotly.NET.ImageExport/ChartExtensions.fs

+56-31
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ open System.Runtime.CompilerServices
1212
[<AutoOpen>]
1313
module ChartExtensions =
1414

15-
type internal RenderOptions(?EngineType: ExportEngine, ?Width: int, ?Height: int) =
15+
type internal RenderOptions(?EngineType: ExportEngine, ?Width: int, ?Height: int, ?Scale:float) =
1616
member _.Engine =
1717
(defaultArg EngineType ExportEngine.PuppeteerSharp) |> ExportEngine.getEngine
1818

1919
member _.Width = defaultArg Width 600
2020
member _.Height = defaultArg Height 600
21+
member _.Scale = defaultArg Scale 1.0
2122

2223
type Chart with
2324

@@ -27,35 +28,39 @@ module ChartExtensions =
2728
/// <param name="EngineType">The Render engine to use</param>
2829
/// <param name="Width">width of the resulting image</param>
2930
/// <param name="Height">height of the resulting image</param>
31+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
3032
[<CompiledName("ToBase64JPGStringAsync")>]
3133
static member toBase64JPGStringAsync
3234
(
3335
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
3436
[<Optional; DefaultParameterValue(null)>] ?Width: int,
35-
[<Optional; DefaultParameterValue(null)>] ?Height: int
37+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
38+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
3639
) =
3740

3841
let opts =
39-
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height)
42+
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
4043

41-
fun (gChart: GenericChart) -> opts.Engine.RenderJPGAsync(opts.Width, opts.Height, gChart)
44+
fun (gChart: GenericChart) -> opts.Engine.RenderJPGAsync(opts.Width, opts.Height, opts.Scale, gChart)
4245

4346
/// <summary>
4447
/// Returns a function that converts a GenericChart to a base64 encoded JPG string
4548
/// </summary>
4649
/// <param name="EngineType">The Render engine to use</param>
4750
/// <param name="Width">width of the resulting image</param>
4851
/// <param name="Height">height of the resulting image</param>
52+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
4953
[<CompiledName("ToBase64JPGString")>]
5054
static member toBase64JPGString
5155
(
5256
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
5357
[<Optional; DefaultParameterValue(null)>] ?Width: int,
54-
[<Optional; DefaultParameterValue(null)>] ?Height: int
58+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
59+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
5560
) =
5661
fun (gChart: GenericChart) ->
5762
gChart
58-
|> Chart.toBase64JPGStringAsync (?EngineType = EngineType, ?Width = Width, ?Height = Height)
63+
|> Chart.toBase64JPGStringAsync (?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
5964
|> AsyncHelper.taskSync
6065

6166
/// <summary>
@@ -65,19 +70,21 @@ module ChartExtensions =
6570
/// <param name="EngineType">The Render engine to use</param>
6671
/// <param name="Width">width of the resulting image</param>
6772
/// <param name="Height">height of the resulting image</param>
73+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
6874
[<CompiledName("SaveJPGAsync")>]
6975
static member saveJPGAsync
7076
(
7177
path: string,
7278
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
7379
[<Optional; DefaultParameterValue(null)>] ?Width: int,
74-
[<Optional; DefaultParameterValue(null)>] ?Height: int
80+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
81+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
7582
) =
7683

7784
let opts =
78-
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height)
85+
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
7986

80-
fun (gChart: GenericChart) -> opts.Engine.SaveJPGAsync(path, opts.Width, opts.Height, gChart)
87+
fun (gChart: GenericChart) -> opts.Engine.SaveJPGAsync(path, opts.Width, opts.Height, opts.Scale, gChart)
8188

8289
/// <summary>
8390
/// Returns a function that saves a GenericChart as JPG image
@@ -86,17 +93,19 @@ module ChartExtensions =
8693
/// <param name="EngineType">The Render engine to use</param>
8794
/// <param name="Width">width of the resulting image</param>
8895
/// <param name="Height">height of the resulting image</param>
96+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
8997
[<CompiledName("SaveJPG")>]
9098
static member saveJPG
9199
(
92100
path: string,
93101
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
94102
[<Optional; DefaultParameterValue(null)>] ?Width: int,
95-
[<Optional; DefaultParameterValue(null)>] ?Height: int
103+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
104+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
96105
) =
97106
fun (gChart: GenericChart) ->
98107
gChart
99-
|> Chart.saveJPGAsync (path, ?EngineType = EngineType, ?Width = Width, ?Height = Height)
108+
|> Chart.saveJPGAsync (path, ?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
100109
|> AsyncHelper.taskSync
101110

102111
/// <summary>
@@ -105,35 +114,39 @@ module ChartExtensions =
105114
/// <param name="EngineType">The Render engine to use</param>
106115
/// <param name="Width">width of the resulting image</param>
107116
/// <param name="Height">height of the resulting image</param>
117+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
108118
[<CompiledName("ToBase64PNGStringAsync")>]
109119
static member toBase64PNGStringAsync
110120
(
111121
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
112122
[<Optional; DefaultParameterValue(null)>] ?Width: int,
113-
[<Optional; DefaultParameterValue(null)>] ?Height: int
123+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
124+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
114125
) =
115126

116127
let opts =
117-
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height)
128+
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
118129

119-
fun (gChart: GenericChart) -> opts.Engine.RenderPNGAsync(opts.Width, opts.Height, gChart)
130+
fun (gChart: GenericChart) -> opts.Engine.RenderPNGAsync(opts.Width, opts.Height, opts.Scale, gChart)
120131

121132
/// <summary>
122133
/// Returns a function that converts a GenericChart to a base64 encoded PNG string
123134
/// </summary>
124135
/// <param name="EngineType">The Render engine to use</param>
125136
/// <param name="Width">width of the resulting image</param>
126137
/// <param name="Height">height of the resulting image</param>
138+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
127139
[<CompiledName("ToBase64PNGString")>]
128140
static member toBase64PNGString
129141
(
130142
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
131143
[<Optional; DefaultParameterValue(null)>] ?Width: int,
132-
[<Optional; DefaultParameterValue(null)>] ?Height: int
144+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
145+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
133146
) =
134147
fun (gChart: GenericChart) ->
135148
gChart
136-
|> Chart.toBase64PNGStringAsync (?EngineType = EngineType, ?Width = Width, ?Height = Height)
149+
|> Chart.toBase64PNGStringAsync (?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
137150
|> AsyncHelper.taskSync
138151

139152
/// <summary>
@@ -143,18 +156,20 @@ module ChartExtensions =
143156
/// <param name="EngineType">The Render engine to use</param>
144157
/// <param name="Width">width of the resulting image</param>
145158
/// <param name="Height">height of the resulting image</param>
159+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
146160
[<CompiledName("SavePNGAsync")>]
147161
static member savePNGAsync
148162
(
149163
path: string,
150164
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
151165
[<Optional; DefaultParameterValue(null)>] ?Width: int,
152-
[<Optional; DefaultParameterValue(null)>] ?Height: int
166+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
167+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
153168
) =
154169
let opts =
155-
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height)
170+
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
156171

157-
fun (gChart: GenericChart) -> opts.Engine.SavePNGAsync(path, opts.Width, opts.Height, gChart)
172+
fun (gChart: GenericChart) -> opts.Engine.SavePNGAsync(path, opts.Width, opts.Height, opts.Scale, gChart)
158173

159174

160175
/// <summary>
@@ -164,17 +179,19 @@ module ChartExtensions =
164179
/// <param name="EngineType">The Render engine to use</param>
165180
/// <param name="Width">width of the resulting image</param>
166181
/// <param name="Height">height of the resulting image</param>
182+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
167183
[<CompiledName("SavePNG")>]
168184
static member savePNG
169185
(
170186
path: string,
171187
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
172188
[<Optional; DefaultParameterValue(null)>] ?Width: int,
173-
[<Optional; DefaultParameterValue(null)>] ?Height: int
189+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
190+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
174191
) =
175192
fun (gChart: GenericChart) ->
176193
gChart
177-
|> Chart.savePNGAsync (path, ?EngineType = EngineType, ?Width = Width, ?Height = Height)
194+
|> Chart.savePNGAsync (path, ?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
178195
|> AsyncHelper.taskSync
179196

180197
/// <summary>
@@ -183,34 +200,38 @@ module ChartExtensions =
183200
/// <param name="EngineType">The Render engine to use</param>
184201
/// <param name="Width">width of the resulting image</param>
185202
/// <param name="Height">height of the resulting image</param>
203+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
186204
[<CompiledName("ToSVGStringAsync")>]
187205
static member toSVGStringAsync
188206
(
189207
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
190208
[<Optional; DefaultParameterValue(null)>] ?Width: int,
191-
[<Optional; DefaultParameterValue(null)>] ?Height: int
209+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
210+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
192211
) =
193212
let opts =
194-
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height)
213+
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
195214

196-
fun (gChart: GenericChart) -> opts.Engine.RenderSVGAsync(opts.Width, opts.Height, gChart)
215+
fun (gChart: GenericChart) -> opts.Engine.RenderSVGAsync(opts.Width, opts.Height, opts.Scale, gChart)
197216

198217
/// <summary>
199218
/// Returns a function that converts a GenericChart to a SVG string
200219
/// </summary>
201220
/// <param name="EngineType">The Render engine to use</param>
202221
/// <param name="Width">width of the resulting image</param>
203222
/// <param name="Height">height of the resulting image</param>
223+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
204224
[<CompiledName("ToSVGString")>]
205225
static member toSVGString
206226
(
207227
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
208228
[<Optional; DefaultParameterValue(null)>] ?Width: int,
209-
[<Optional; DefaultParameterValue(null)>] ?Height: int
229+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
230+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
210231
) =
211232
fun (gChart: GenericChart) ->
212233
gChart
213-
|> Chart.toSVGStringAsync (?EngineType = EngineType, ?Width = Width, ?Height = Height)
234+
|> Chart.toSVGStringAsync (?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
214235
|> AsyncHelper.taskSync
215236

216237
/// <summary>
@@ -220,18 +241,20 @@ module ChartExtensions =
220241
/// <param name="EngineType">The Render engine to use</param>
221242
/// <param name="Width">width of the resulting image</param>
222243
/// <param name="Height">height of the resulting image</param>
244+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
223245
[<CompiledName("SaveSVGAsync")>]
224246
static member saveSVGAsync
225247
(
226248
path: string,
227249
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
228250
[<Optional; DefaultParameterValue(null)>] ?Width: int,
229-
[<Optional; DefaultParameterValue(null)>] ?Height: int
251+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
252+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
230253
) =
231254
let opts =
232-
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height)
255+
RenderOptions(?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
233256

234-
fun (gChart: GenericChart) -> opts.Engine.SaveSVGAsync(path, opts.Width, opts.Height, gChart)
257+
fun (gChart: GenericChart) -> opts.Engine.SaveSVGAsync(path, opts.Width, opts.Height, opts.Scale, gChart)
235258

236259
/// <summary>
237260
/// Returns a function that saves a GenericChart as SVG image
@@ -240,15 +263,17 @@ module ChartExtensions =
240263
/// <param name="EngineType">The Render engine to use</param>
241264
/// <param name="Width">width of the resulting image</param>
242265
/// <param name="Height">height of the resulting image</param>
266+
/// <param name="Scale">scale the resulting image by this factor. The DPI will stay the same, but the resolution will be scaled.</param>
243267
[<CompiledName("SaveSVG")>]
244268
static member saveSVG
245269
(
246270
path: string,
247271
[<Optional; DefaultParameterValue(null)>] ?EngineType: ExportEngine,
248272
[<Optional; DefaultParameterValue(null)>] ?Width: int,
249-
[<Optional; DefaultParameterValue(null)>] ?Height: int
273+
[<Optional; DefaultParameterValue(null)>] ?Height: int,
274+
[<Optional; DefaultParameterValue(null)>] ?Scale: float
250275
) =
251276
fun (gChart: GenericChart) ->
252277
gChart
253-
|> Chart.saveSVGAsync (path, ?EngineType = EngineType, ?Width = Width, ?Height = Height)
278+
|> Chart.saveSVGAsync (path, ?EngineType = EngineType, ?Width = Width, ?Height = Height, ?Scale = Scale)
254279
|> AsyncHelper.taskSync

0 commit comments

Comments
 (0)