7
7
// pull request raised to extend library used.
8
8
namespace QRCoder
9
9
{
10
- public class LogoQRCode : AbstractQRCode , IDisposable
10
+ public class ArtQRCode : AbstractQRCode , IDisposable
11
11
{
12
12
/// <summary>
13
13
/// Constructor without params to be used in COM Objects connections
14
14
/// </summary>
15
- public LogoQRCode ( ) { }
15
+ public ArtQRCode ( ) { }
16
16
17
- public LogoQRCode ( QRCodeData data ) : base ( data ) { }
17
+ public ArtQRCode ( QRCodeData data ) : base ( data ) { }
18
18
19
- public Bitmap GetGraphic ( Bitmap backgroundImage = null )
19
+ public Bitmap GetGraphic ( int pixelsPerModule )
20
20
{
21
- return this . GetGraphic ( 10 , 7 , Color . Black , Color . White , backgroundImage : backgroundImage ) ;
21
+ return this . GetGraphic ( pixelsPerModule , ( pixelsPerModule * 8 ) / 10 , Color . Black , Color . White ) ;
22
22
}
23
23
24
- public Bitmap GetGraphic ( int pixelsPerModule , Bitmap backgroundImage = null )
24
+ public Bitmap GetGraphic ( Bitmap backgroundImage = null )
25
25
{
26
- return this . GetGraphic ( pixelsPerModule , ( pixelsPerModule * 8 ) / 10 , Color . Black , Color . White , backgroundImage : backgroundImage ) ;
26
+ return this . GetGraphic ( 10 , 7 , Color . Black , Color . White , backgroundImage : backgroundImage ) ;
27
27
}
28
28
29
- public Bitmap GetGraphic ( int pixelsPerModule ,
29
+ public Bitmap GetGraphic (
30
+ int pixelsPerModule ,
30
31
int pixelSize ,
31
32
Color darkColor ,
32
33
Color lightColor ,
33
- Bitmap backgroundImage = null ,
34
34
bool drawQuietZones = false ,
35
- Bitmap reticleImage = null )
35
+ Bitmap reticleImage = null ,
36
+ Bitmap backgroundImage = null )
36
37
{
37
38
int numModules = this . QrCodeData . ModuleMatrix . Count - ( drawQuietZones ? 0 : 8 ) ;
38
39
var offset = ( drawQuietZones ? 0 : 4 ) ;
@@ -42,6 +43,7 @@ public Bitmap GetGraphic(int pixelsPerModule,
42
43
Bitmap bitmap = backgroundImage ?? new Bitmap ( size , size ) ;
43
44
bitmap = Resize ( bitmap , size ) ;
44
45
46
+
45
47
using ( Graphics graphics = Graphics . FromImage ( bitmap ) )
46
48
{
47
49
using ( SolidBrush lightBrush = new SolidBrush ( lightColor ) )
@@ -57,21 +59,23 @@ public Bitmap GetGraphic(int pixelsPerModule,
57
59
}
58
60
}
59
61
62
+ var darkModulePixel = MakeDotPixel ( pixelsPerModule , pixelSize , darkBrush ) ;
63
+ var lightModulePixel = MakeDotPixel ( pixelsPerModule , pixelSize , lightBrush ) ;
64
+
60
65
for ( int x = 0 ; x < numModules ; x += 1 )
61
66
{
62
67
for ( int y = 0 ; y < numModules ; y += 1 )
63
68
{
64
- var solidBrush = ( Brush ) ( this . QrCodeData . ModuleMatrix [ offset + y ] [ offset + x ] ? darkBrush : lightBrush ) ;
65
-
66
- if ( IsPartOfReticle ( x , y , numModules , offset ) )
67
- {
68
- if ( reticleImage == null )
69
- {
70
- graphics . FillRectangle ( solidBrush , new Rectangle ( x * pixelsPerModule , y * pixelsPerModule , pixelsPerModule , pixelsPerModule ) ) ;
71
- }
72
- }
73
- else
74
- graphics . FillEllipse ( solidBrush , new Rectangle ( x * pixelsPerModule + moduleMargin , y * pixelsPerModule + moduleMargin , pixelSize , pixelSize ) ) ;
69
+ var rectangleF = new Rectangle ( x * pixelsPerModule , y * pixelsPerModule , pixelsPerModule , pixelsPerModule ) ;
70
+
71
+ var pixelIsDark = this . QrCodeData . ModuleMatrix [ offset + y ] [ offset + x ] ;
72
+ var solidBrush = pixelIsDark ? darkBrush : lightBrush ;
73
+ var pixelImage = pixelIsDark ? darkModulePixel : lightModulePixel ;
74
+
75
+ if ( ! IsPartOfReticle ( x , y , numModules , offset ) )
76
+ graphics . DrawImage ( pixelImage , rectangleF ) ;
77
+ else if ( reticleImage == null )
78
+ graphics . FillRectangle ( solidBrush , rectangleF ) ;
75
79
}
76
80
}
77
81
@@ -90,6 +94,39 @@ public Bitmap GetGraphic(int pixelsPerModule,
90
94
return bitmap ;
91
95
}
92
96
97
+ /// <summary>
98
+ /// If the pixelSize is bigger than the pixelsPerModule or may end up filling the Module making a traditional QR code.
99
+ /// </summary>
100
+ /// <param name="pixelsPerModule"></param>
101
+ /// <param name="pixelSize"></param>
102
+ /// <param name="brush"></param>
103
+ /// <returns></returns>
104
+ private Bitmap MakeDotPixel ( int pixelsPerModule , int pixelSize , SolidBrush brush )
105
+ {
106
+ // draw a dot
107
+ var bitmap = new Bitmap ( pixelSize , pixelSize ) ;
108
+ using ( var graphics = Graphics . FromImage ( bitmap ) )
109
+ {
110
+ graphics . FillEllipse ( brush , new Rectangle ( 0 , 0 , pixelSize , pixelSize ) ) ;
111
+ graphics . Save ( ) ;
112
+ }
113
+
114
+ var pixelWidth = Math . Min ( pixelsPerModule , pixelSize ) ;
115
+ var margin = Math . Max ( ( pixelsPerModule - pixelWidth ) / 2 , 0 ) ;
116
+
117
+ // center the dot in the module and crop to stay the right size.
118
+ var cropped = new Bitmap ( pixelsPerModule , pixelsPerModule ) ;
119
+ using ( var graphics = Graphics . FromImage ( cropped ) )
120
+ {
121
+ graphics . DrawImage ( bitmap , new Rectangle ( margin , margin , pixelWidth , pixelWidth ) ,
122
+ new RectangleF ( ( ( float ) pixelSize - pixelWidth ) / 2 , ( ( float ) pixelSize - pixelWidth ) / 2 , pixelWidth , pixelWidth ) ,
123
+ GraphicsUnit . Pixel ) ;
124
+ graphics . Save ( ) ;
125
+ }
126
+
127
+ return cropped ;
128
+ }
129
+
93
130
private bool IsPartOfReticle ( int x , int y , int numModules , int offset )
94
131
{
95
132
var cornerSize = 11 - offset ;
@@ -99,25 +136,36 @@ private bool IsPartOfReticle(int x, int y, int numModules, int offset)
99
136
( x < cornerSize && y > ( numModules - cornerSize - 1 ) ) ;
100
137
}
101
138
102
- private Bitmap Resize ( Bitmap image , int size )
139
+ /// <summary>
140
+ /// Resize to a square bitmap, but maintain the aspect ratio by padding transparently.
141
+ /// </summary>
142
+ ///
143
+ /// <param name="image"></param>
144
+ /// <param name="newSize"></param>
145
+ /// <returns></returns>
146
+ private Bitmap Resize ( Bitmap image , int newSize )
103
147
{
104
- float scale = Math . Min ( ( float ) size / image . Width , ( float ) size / image . Height ) ;
105
- var scaleWidth = ( int ) ( image . Width * scale ) ;
106
- var scaleHeight = ( int ) ( image . Height * scale ) ;
107
- var scaledImage = new Bitmap ( image , new Size ( scaleWidth , scaleHeight ) ) ;
148
+ float scale = Math . Min ( ( float ) newSize / image . Width , ( float ) newSize / image . Height ) ;
149
+ var scaledWidth = ( int ) ( image . Width * scale ) ;
150
+ var scaledHeight = ( int ) ( image . Height * scale ) ;
151
+ var offsetX = ( newSize - scaledWidth ) / 2 ;
152
+ var offsetY = ( newSize - scaledHeight ) / 2 ;
153
+
154
+ var scaledImage = new Bitmap ( image , new Size ( scaledWidth , scaledHeight ) ) ;
108
155
109
- var bm = new Bitmap ( size , size ) ;
156
+ var bm = new Bitmap ( newSize , newSize ) ;
110
157
111
158
using ( Graphics graphics = Graphics . FromImage ( bm ) )
112
159
{
113
160
using ( var brush = new SolidBrush ( Color . Transparent ) )
114
161
{
115
- graphics . FillRectangle ( brush , new Rectangle ( 0 , 0 , size , size ) ) ;
162
+ graphics . FillRectangle ( brush , new Rectangle ( 0 , 0 , newSize , newSize ) ) ;
116
163
117
164
graphics . InterpolationMode = InterpolationMode . High ;
118
165
graphics . CompositingQuality = CompositingQuality . HighQuality ;
119
166
graphics . SmoothingMode = SmoothingMode . AntiAlias ;
120
- graphics . DrawImage ( scaledImage , new Rectangle ( ( size / 2 ) - ( scaledImage . Width / 2 ) , ( size / 2 ) - ( scaledImage . Height / 2 ) , scaledImage . Width , scaledImage . Height ) ) ;
167
+
168
+ graphics . DrawImage ( scaledImage , new Rectangle ( offsetX , offsetY , scaledWidth , scaledHeight ) ) ;
121
169
}
122
170
}
123
171
0 commit comments