Codemaru
1.0.0.0
QR 코드, 모바일 랜딩 페이지, vCard 연락처 저장과 명함 디자인을 한 화면에서 제공하는 디지털 명함 서비스입니다.
Toggle main menu visibility
로딩중...
검색중...
일치하는것 없음
ImageBackgroundRemover.cs
이 파일의 문서화 페이지로 가기
1
using
System.IO;
2
using
System.Windows;
3
using
System.Windows.Media;
4
using
System.Windows.Media.Imaging;
5
6
namespace
Codemaru.Services
;
7
16
public
sealed
class
ImageBackgroundRemover
17
{
26
private
const
double
ClearDistance
= 42;
35
private
const
double
SoftDistance
= 86;
44
private
const
int
LogoCanvasWidth
= 640;
53
private
const
int
LogoCanvasHeight
= 400;
62
private
const
int
LogoPadding
= 42;
63
104
public
string
CreateDataUrl
(
byte
[] imageBytes,
string
contentType,
bool
removeBackground)
105
{
106
if
(contentType.Contains(
"svg"
, StringComparison.OrdinalIgnoreCase))
107
{
108
return
$
"data:{contentType};base64,{Convert.ToBase64String(imageBytes)}"
;
109
}
110
111
try
112
{
113
var png =
NormalizeLogo
(imageBytes, removeBackground);
114
return
$
"data:image/png;base64,{Convert.ToBase64String(png)}"
;
115
}
116
catch
117
{
118
return
$
"data:{contentType};base64,{Convert.ToBase64String(imageBytes)}"
;
119
}
120
}
121
154
private
static
byte
[]
NormalizeLogo
(
byte
[] imageBytes,
bool
removeBackground)
155
{
156
using
var source =
new
MemoryStream(imageBytes);
157
var decoder = BitmapDecoder.Create(source, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
158
var frame = decoder.Frames[0];
159
var bitmap =
new
FormatConvertedBitmap(frame, PixelFormats.Bgra32,
null
, 0);
160
var width = bitmap.PixelWidth;
161
var height = bitmap.PixelHeight;
162
var stride = width * 4;
163
var pixels =
new
byte
[stride * height];
164
165
bitmap.CopyPixels(pixels, stride, 0);
166
167
if
(removeBackground)
168
{
169
RemoveBackgroundPixels
(pixels, width, height, stride);
170
}
171
172
var prepared = BitmapSource.Create(width, height, 96, 96, PixelFormats.Bgra32,
null
, pixels, stride);
173
var bounds = removeBackground
174
?
FindVisibleBounds
(pixels, width, height, stride)
175
:
new
Int32Rect(0, 0, width, height);
176
var cropped =
new
CroppedBitmap(prepared, bounds);
177
var fitted =
FitIntoCanvas
(cropped);
178
179
var encoder =
new
PngBitmapEncoder();
180
encoder.Frames.Add(BitmapFrame.Create(fitted));
181
182
using
var target =
new
MemoryStream();
183
encoder.Save(target);
184
return
target.ToArray();
185
}
186
227
private
static
void
RemoveBackgroundPixels
(
byte
[] pixels,
int
width,
int
height,
int
stride)
228
{
229
var background =
SampleBackground
(pixels, width, height, stride);
230
for
(var y = 0; y < height; y++)
231
{
232
for
(var x = 0; x < width; x++)
233
{
234
var i = y * stride + x * 4;
235
var distance =
ColorDistance
(
236
pixels[i + 2],
237
pixels[i + 1],
238
pixels[i],
239
background.R,
240
background.G,
241
background.B);
242
243
if
(distance <=
ClearDistance
)
244
{
245
pixels[i + 3] = 0;
246
}
247
else
if
(distance <
SoftDistance
)
248
{
249
var keep = (distance -
ClearDistance
) / (
SoftDistance
-
ClearDistance
);
250
pixels[i + 3] = (byte)Math.Min(pixels[i + 3], Math.Round(255 * keep));
251
}
252
}
253
}
254
}
255
280
private
static
BitmapSource
FitIntoCanvas
(BitmapSource source)
281
{
282
var availableWidth =
LogoCanvasWidth
-
LogoPadding
* 2;
283
var availableHeight =
LogoCanvasHeight
-
LogoPadding
* 2;
284
var scale = Math.Min((
double
)availableWidth / source.PixelWidth, (
double
)availableHeight / source.PixelHeight);
285
var targetWidth = Math.Max(1, source.PixelWidth * scale);
286
var targetHeight = Math.Max(1, source.PixelHeight * scale);
287
var left = (
LogoCanvasWidth
- targetWidth) / 2;
288
var top = (
LogoCanvasHeight
- targetHeight) / 2;
289
290
var visual =
new
DrawingVisual();
291
using
(var context = visual.RenderOpen())
292
{
293
context.DrawRectangle(Brushes.Transparent,
null
,
new
Rect(0, 0,
LogoCanvasWidth
,
LogoCanvasHeight
));
294
context.DrawImage(source,
new
Rect(left, top, targetWidth, targetHeight));
295
}
296
297
var target =
new
RenderTargetBitmap(
LogoCanvasWidth
,
LogoCanvasHeight
, 96, 96, PixelFormats.Pbgra32);
298
target.Render(visual);
299
target.Freeze();
300
return
target;
301
}
302
351
private
static
Int32Rect
FindVisibleBounds
(
byte
[] pixels,
int
width,
int
height,
int
stride)
352
{
353
var left = width;
354
var top = height;
355
var right = -1;
356
var bottom = -1;
357
358
for
(var y = 0; y < height; y++)
359
{
360
for
(var x = 0; x < width; x++)
361
{
362
var alpha = pixels[y * stride + x * 4 + 3];
363
if
(alpha <= 12)
364
{
365
continue
;
366
}
367
368
left = Math.Min(left, x);
369
top = Math.Min(top, y);
370
right = Math.Max(right, x);
371
bottom = Math.Max(bottom, y);
372
}
373
}
374
375
if
(right < left || bottom < top)
376
{
377
return
new
Int32Rect(0, 0, width, height);
378
}
379
380
return
new
Int32Rect(left, top, right - left + 1, bottom - top + 1);
381
}
382
431
private
static
Color
SampleBackground
(
byte
[] pixels,
int
width,
int
height,
int
stride)
432
{
433
var points =
new
[]
434
{
435
(X: 0, Y: 0),
436
(X: width - 1, Y: 0),
437
(X: 0, Y: height - 1),
438
(X: width - 1, Y: height - 1)
439
};
440
441
var r = 0;
442
var g = 0;
443
var b = 0;
444
445
foreach
(var point
in
points)
446
{
447
var i = point.Y * stride + point.X * 4;
448
b += pixels[i];
449
g += pixels[i + 1];
450
r += pixels[i + 2];
451
}
452
453
return
Color.FromRgb((
byte
)(r / points.Length), (
byte
)(g / points.Length), (
byte
)(b / points.Length));
454
}
455
520
private
static
double
ColorDistance
(
byte
r1,
byte
g1,
byte
b1,
byte
r2,
byte
g2,
byte
b2)
521
{
522
var r = r1 - r2;
523
var g = g1 - g2;
524
var b = b1 - b2;
525
return
Math.Sqrt(r * r + g * g + b * b);
526
}
527
}
Codemaru.Services
Definition
CardHybridCircuitSession.cs:8
Codemaru.Services.ImageBackgroundRemover
Definition
ImageBackgroundRemover.cs:17
Codemaru.Services.ImageBackgroundRemover.RemoveBackgroundPixels
static void RemoveBackgroundPixels(byte[] pixels, int width, int height, int stride)
Definition
ImageBackgroundRemover.cs:227
Codemaru.Services.ImageBackgroundRemover.SoftDistance
const double SoftDistance
Definition
ImageBackgroundRemover.cs:35
Codemaru.Services.ImageBackgroundRemover.LogoCanvasWidth
const int LogoCanvasWidth
Definition
ImageBackgroundRemover.cs:44
Codemaru.Services.ImageBackgroundRemover.ColorDistance
static double ColorDistance(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2)
Definition
ImageBackgroundRemover.cs:520
Codemaru.Services.ImageBackgroundRemover.LogoPadding
const int LogoPadding
Definition
ImageBackgroundRemover.cs:62
Codemaru.Services.ImageBackgroundRemover.ClearDistance
const double ClearDistance
Definition
ImageBackgroundRemover.cs:26
Codemaru.Services.ImageBackgroundRemover.FitIntoCanvas
static BitmapSource FitIntoCanvas(BitmapSource source)
Definition
ImageBackgroundRemover.cs:280
Codemaru.Services.ImageBackgroundRemover.LogoCanvasHeight
const int LogoCanvasHeight
Definition
ImageBackgroundRemover.cs:53
Codemaru.Services.ImageBackgroundRemover.NormalizeLogo
static byte[] NormalizeLogo(byte[] imageBytes, bool removeBackground)
Definition
ImageBackgroundRemover.cs:154
Codemaru.Services.ImageBackgroundRemover.FindVisibleBounds
static Int32Rect FindVisibleBounds(byte[] pixels, int width, int height, int stride)
Definition
ImageBackgroundRemover.cs:351
Codemaru.Services.ImageBackgroundRemover.CreateDataUrl
string CreateDataUrl(byte[] imageBytes, string contentType, bool removeBackground)
Definition
ImageBackgroundRemover.cs:104
Codemaru.Services.ImageBackgroundRemover.SampleBackground
static Color SampleBackground(byte[] pixels, int width, int height, int stride)
Definition
ImageBackgroundRemover.cs:431
Services
ImageBackgroundRemover.cs
다음에 의해 생성됨 :
1.17.0