.net core 的图片处理及二维码的生成及解析
写代码这事,掐指算来已经十有余年。
从html到css到javascript到vbscript到c#,从兴趣到职业,生活总是失落与惊喜并存。
绝大部分时候,出发并不是因为知道该到哪里去,只是知道不能再逗留下去了,如此而已。受过风吹雨打之后会有很多独有的感受及思考,主见开始生发并在摇摆中坚定,想来这就是成长了,嗯……就算是成长吧,呵呵!
话说微软的 .net core 3.0 即将发布了,作为一个码农,还是要关心一下的。从 .net core 2.0 及MySql官方开始支持 .net core 起,我尝试将自己的类库转成 .net standard 类库,开始了解 .net core 的成熟度,写了几个 demo ,之后就放弃了,因为我做的项目还是以web(asp.net core)为主,但是 .net core 对图片的处理是空白的,System.Drawing只是一个摆设(估计以后也是一样),即便是有很多人推崇的 ImageSharp 也因为接口变化过大且缺少文档在稍作尝试之后放弃了,我想,在 .net core 下应该还没有一个成熟的图片处理类库,还不足以迁移项目。如果按微软官方的意思要搞一个独立的图片处理应用来进行图片处理,那 asp.net core 只是作为一个简单的数据接口来用,这就很值得权衡一下了,毕竟中小型项目要去搞一个专门的图片处理应用是得不偿失的,不知道微软的产品和工程师们是否有过这些思量?又或者只是所谓的企业级应用才是他们的目标?
我假设 System.Drawing 在 .net core 中的下场就像 IE 浏览器和 Edge 浏览器在Win10 后的下场一样,也许该放弃了。那就找个替代方案吧,所以最终决定采用 SkiaSharp 来做图片处理,顺便处理一下二维码,毕竟也是图片嘛,并且二维码在天朝是很有场景可用的,之前在 .net framework 中我一致习惯用 ThoughtWorks.QRCode 来处理二维码的生成和解析,不过目前 ThoughtWorks.QRCode 好像还不支持在 .net core 中工作,因此二维码的生成和解析最后采用 ZXing.Net 来处理。
用 ZXing.Net 生成的二维码默认是有一定比例的白边的,大概算是一种工业标准,但是在实际的应用场景中有时候可能不需要白边,所以我对白边做了一点逻辑处理,对白边可以指定要保留的宽度像素值也可以保留原始的默认白边。
通过引用 SkiaSharp(1.68.0) 和 ZXing.Net(0.16.4) ,之后写了一个静态类,用来对图片进行缩放和裁剪等基本操作以及生成和解析二维码,代码如下:
public static class ImageHelper
{
static readonly long maxLength = ;//10*1024*1024
public static SkiaSharp.SKEncodedImageFormat GetImageFormatBySuffix(string suffix)
{
var format = SkiaSharp.SKEncodedImageFormat.Jpeg;
if (string.IsNullOrEmpty(suffix))
{
return format;
}
if (suffix[] == '.')
{
suffix = suffix.Substring();
}
if (string.IsNullOrEmpty(suffix))
{
return format;
}
suffix = suffix.ToUpper();
switch (suffix)
{
case "PNG":
format = SkiaSharp.SKEncodedImageFormat.Png;
break;
case "GIF":
format = SkiaSharp.SKEncodedImageFormat.Gif;
break;
case "BMP":
format = SkiaSharp.SKEncodedImageFormat.Bmp;
break;
case "ICON":
format = SkiaSharp.SKEncodedImageFormat.Ico;
break;
case "ICO":
format = SkiaSharp.SKEncodedImageFormat.Ico;
break;
case "DNG":
format = SkiaSharp.SKEncodedImageFormat.Dng;
break;
case "WBMP":
format = SkiaSharp.SKEncodedImageFormat.Wbmp;
break;
case "WEBP":
format = SkiaSharp.SKEncodedImageFormat.Webp;
break;
case "PKM":
format = SkiaSharp.SKEncodedImageFormat.Pkm;
break;
case "KTX":
format = SkiaSharp.SKEncodedImageFormat.Ktx;
break;
case "ASTC":
format = SkiaSharp.SKEncodedImageFormat.Astc;
break;
}
return format;
}
public static SkiaSharp.SKEncodedImageFormat GetImageFormatByPath(string path)
{
var suffix = "";
if (System.IO.Path.HasExtension(path))
{
suffix = System.IO.Path.GetExtension(path);
}
return GetImageFormatBySuffix(suffix);
}
public static Tuple<int, int, long, SkiaSharp.SKEncodedImageFormat> GetImageInfo(string path)
{
if (string.IsNullOrEmpty(path))
{
throw new Exception("路径不能为空");
}
if (!System.IO.File.Exists(path))
{
throw new Exception("文件不存在");
}
var fileStream = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); //fileInfo.OpenRead();
var fileLength = fileStream.Length;
if (fileLength > maxLength)
{
fileStream.Dispose();
throw new Exception("文件过大");
}
var sKManagedStream = new SkiaSharp.SKManagedStream(fileStream, true);
var sKBitmap = SkiaSharp.SKBitmap.Decode(sKManagedStream);
sKManagedStream.Dispose(); if (sKBitmap.IsEmpty)
{
sKBitmap.Dispose();
throw new Exception("文件无效");
}
int w = sKBitmap.Width;
int h = sKBitmap.Height;
return new Tuple<int, int, long, SkiaSharp.SKEncodedImageFormat>(w, h, fileLength, GetImageFormatByPath(path));
}
public static void ImageMaxCutByCenter(string path, string savePath, int saveWidth, int saveHeight, int quality)
{
var bytes = ImageMaxCutByCenter(path, saveWidth, saveHeight, quality);
if (bytes == null || bytes.Length < )
{
return;
}
string saveDirPath = System.IO.Path.GetDirectoryName(savePath);
if (!System.IO.Directory.Exists(saveDirPath))
{
System.IO.Directory.CreateDirectory(saveDirPath);
}
System.IO.FileStream fs = new System.IO.FileStream(savePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None);
fs.Write(bytes, , bytes.Length);
fs.Close();
}
public static byte[] ImageMaxCutByCenter(string path, int saveWidth, int saveHeight, int quality)
{
byte[] bytes = null;
if (!System.IO.File.Exists(path))
{
return bytes;
}
var fileStream = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); //fileInfo.OpenRead();
if (fileStream.Length > maxLength)
{
fileStream.Dispose();
return bytes;
}
var sKManagedStream = new SkiaSharp.SKManagedStream(fileStream, true);
var sKBitmap = SkiaSharp.SKBitmap.Decode(sKManagedStream);
sKManagedStream.Dispose(); if (sKBitmap.IsEmpty)
{
return bytes;
} if (saveWidth < ) { saveWidth = ; }
if (saveHeight < ) { saveHeight = ; }
if (quality < ) { quality = ; }
if (quality > ) { quality = ; } int oW = sKBitmap.Width;
int oH = sKBitmap.Height;
int cutW = saveWidth;
int cutH = saveHeight;
double ratio = ;
if (cutW > oW)
{
ratio = (double)oW / (double)cutW;
cutH = Convert.ToInt32((double)cutH * ratio);
cutW = oW;
if (cutH > oH)
{
ratio = (double)oH / (double)cutH;
cutW = Convert.ToInt32((double)cutW * ratio);
cutH = oH;
}
}
else if (cutW < oW)
{
ratio = (double)oW / (double)cutW;
cutH = Convert.ToInt32(Convert.ToDouble(cutH) * ratio);
cutW = oW;
if (cutH > oH)
{
ratio = (double)oH / (double)cutH;
cutW = Convert.ToInt32((double)cutW * ratio);
cutH = oH;
}
}
else
{
if (cutH > oH)
{
ratio = (double)oH / (double)cutH;
cutW = Convert.ToInt32((double)cutW * ratio);
cutH = oH;
}
}
int startX = oW > cutW ? (oW / - cutW / ) : (cutW / - oW / );
int startY = oH > cutH ? (oH / - cutH / ) : (cutH / - oH / ); var sKBitmap2 = new SkiaSharp.SKBitmap(saveWidth, saveHeight);
var sKCanvas = new SkiaSharp.SKCanvas(sKBitmap2);
var sKPaint = new SkiaSharp.SKPaint
{
FilterQuality = SkiaSharp.SKFilterQuality.Medium,
IsAntialias = true
};
sKCanvas.DrawBitmap(
sKBitmap,
new SkiaSharp.SKRect
{
Location = new SkiaSharp.SKPoint { X = startX, Y = startY },
Size = new SkiaSharp.SKSize { Height = cutH, Width = cutW }
},
new SkiaSharp.SKRect
{
Location = new SkiaSharp.SKPoint { X = , Y = },
Size = new SkiaSharp.SKSize { Height = saveHeight, Width = saveWidth }
}, sKPaint);
sKCanvas.Dispose();
var sKImage2 = SkiaSharp.SKImage.FromBitmap(sKBitmap2);
sKBitmap2.Dispose();
var data = sKImage2.Encode(GetImageFormatByPath(path), quality);
sKImage2.Dispose();
bytes = data.ToArray();
data.Dispose(); return bytes;
}
public static void ImageScalingToRange(string path, string savePath, int maxWidth, int maxHeight, int quality)
{
var bytes = ImageScalingToRange(path, maxWidth, maxHeight, quality);
if (bytes == null || bytes.Length < )
{
return;
}
string saveDirPath = System.IO.Path.GetDirectoryName(savePath);
if (!System.IO.Directory.Exists(saveDirPath))
{
System.IO.Directory.CreateDirectory(saveDirPath);
}
System.IO.FileStream fs = new System.IO.FileStream(savePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None);
fs.Write(bytes, , bytes.Length);
fs.Close();
}
public static byte[] ImageScalingToRange(string path, int maxWidth, int maxHeight, int quality)
{
byte[] bytes = null;
if (!System.IO.File.Exists(path))
{
return bytes;
}
var fileStream = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); //fileInfo.OpenRead();
if (fileStream.Length > maxLength)
{
fileStream.Dispose();
return bytes;
}
var sKManagedStream = new SkiaSharp.SKManagedStream(fileStream, true);
var sKBitmap = SkiaSharp.SKBitmap.Decode(sKManagedStream);
sKManagedStream.Dispose(); if (sKBitmap.IsEmpty)
{
return bytes;
} if (maxWidth < ) { maxWidth = ; }
if (maxHeight < ) { maxHeight = ; }
if (quality < ) { quality = ; }
if (quality > ) { quality = ; } int oW = sKBitmap.Width;
int oH = sKBitmap.Height;
int nW = oW;
int nH = oH; if (nW < maxWidth && nH < maxHeight)//放大
{
if (nW < maxWidth)
{
var r = (double)maxWidth / (double)nW;
nW = maxWidth;
nH = (int)Math.Floor((double)nH * r);
}
if (nH < maxHeight)
{
var r = (double)maxHeight / (double)nH;
nH = maxHeight;
nW = (int)Math.Floor((double)nW * r);
}
}
//限制超出(缩小)
if (nW > maxWidth)
{
var r = (double)maxWidth / (double)nW;
nW = maxWidth;
nH = (int)Math.Floor((double)nH * r);
}
if (nH > maxHeight)
{
var r = (double)maxHeight / (double)nH;
nH = maxHeight;
nW = (int)Math.Floor((double)nW * r);
} var sKBitmap2 = new SkiaSharp.SKBitmap(nW, nH);
var sKCanvas = new SkiaSharp.SKCanvas(sKBitmap2);
var sKPaint = new SkiaSharp.SKPaint
{
FilterQuality = SkiaSharp.SKFilterQuality.Medium,
IsAntialias = true
};
sKCanvas.DrawBitmap(
sKBitmap,
new SkiaSharp.SKRect
{
Location = new SkiaSharp.SKPoint { X = , Y = },
Size = new SkiaSharp.SKSize { Height = oH, Width = oW }
},
new SkiaSharp.SKRect
{
Location = new SkiaSharp.SKPoint { X = , Y = },
Size = new SkiaSharp.SKSize { Height = nH, Width = nW }
}, sKPaint);
sKCanvas.Dispose();
var sKImage2 = SkiaSharp.SKImage.FromBitmap(sKBitmap2);
sKBitmap2.Dispose();
var data = sKImage2.Encode(GetImageFormatByPath(path), quality);
sKImage2.Dispose();
bytes = data.ToArray();
data.Dispose(); return bytes;
}
public static void ImageScalingByOversized(string path, string savePath, int maxWidth, int maxHeight, int quality)
{
var bytes = ImageScalingByOversized(path, maxWidth, maxHeight, quality);
if (bytes == null || bytes.Length < )
{
return;
}
string saveDirPath = System.IO.Path.GetDirectoryName(savePath);
if (!System.IO.Directory.Exists(saveDirPath))
{
System.IO.Directory.CreateDirectory(saveDirPath);
}
System.IO.FileStream fs = new System.IO.FileStream(savePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None);
fs.Write(bytes, , bytes.Length);
fs.Close();
}
public static byte[] ImageScalingByOversized(string path, int maxWidth, int maxHeight, int quality)
{
byte[] bytes = null;
if (!System.IO.File.Exists(path))
{
return bytes;
}
var fileStream = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
if (fileStream.Length > maxLength)
{
fileStream.Dispose();
return bytes;
}
var sKManagedStream = new SkiaSharp.SKManagedStream(fileStream, true);
var sKBitmap = SkiaSharp.SKBitmap.Decode(sKManagedStream);
sKManagedStream.Dispose(); if (sKBitmap.IsEmpty)
{
return bytes;
} if (maxWidth < ) { maxWidth = ; }
if (maxHeight < ) { maxHeight = ; }
if (quality < ) { quality = ; }
if (quality > ) { quality = ; } int oW = sKBitmap.Width;
int oH = sKBitmap.Height;
int nW = oW;
int nH = oH; if (oW > maxWidth || oH > maxHeight)
{
nW = maxWidth;
nH = maxHeight;
double ratio = ; if (nW > && nH > )
{
ratio = (double)nW / oW;
nH = Convert.ToInt32(oH * ratio);
if (maxHeight < nH)
{
ratio = (double)maxHeight / nH;
nW = Convert.ToInt32(nW * ratio);
nH = maxHeight;
}
}
if (nW < && nH < )
{
nW = oW;
nH = oH;
}
if (nW < )
{
ratio = (double)nH / oH;
nW = Convert.ToInt32(oW * ratio);
}
if (nH < )
{
ratio = (double)nW / oW;
nH = Convert.ToInt32(oH * ratio);
}
var sKBitmap2 = new SkiaSharp.SKBitmap(nW, nH);
var sKCanvas = new SkiaSharp.SKCanvas(sKBitmap2);
var sKPaint = new SkiaSharp.SKPaint
{
FilterQuality = SkiaSharp.SKFilterQuality.Medium,
IsAntialias = true
};
sKCanvas.DrawBitmap(
sKBitmap,
new SkiaSharp.SKRect
{
Location = new SkiaSharp.SKPoint { X = , Y = },
Size = new SkiaSharp.SKSize { Height = oH, Width = oW }
},
new SkiaSharp.SKRect
{
Location = new SkiaSharp.SKPoint { X = , Y = },
Size = new SkiaSharp.SKSize { Height = nH, Width = nW }
}, sKPaint);
sKCanvas.Dispose();
sKBitmap.Dispose();
sKBitmap = sKBitmap2;
} var sKImage = SkiaSharp.SKImage.FromBitmap(sKBitmap);
sKBitmap.Dispose();
var data = sKImage.Encode(GetImageFormatByPath(path), quality);
sKImage.Dispose();
bytes = data.ToArray();
data.Dispose(); return bytes;
} /// <summary>
/// 生成二维码(320*320)
/// </summary>
/// <param name="text">文本内容</param>
/// <param name="savePath">保存路径</param>
/// <param name="logoPath">Logo图片路径(缩放到真实二维码区域尺寸的1/6)</param>
/// <param name="keepWhiteBorderPixelVal">白边处理(负值表示不做处理,最大值不超过真实二维码区域的1/10)</param>
public static void QRCoder(string text, string savePath, string logoPath = "", int keepWhiteBorderPixelVal = -)
{
var format = GetImageFormatByPath(savePath);
byte[] bytesLogo = null;
if (!string.IsNullOrEmpty(logoPath) && System.IO.File.Exists(logoPath))
{
var fsLogo = new System.IO.FileStream(logoPath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
fsLogo.CopyTo(ms);
fsLogo.Dispose();
bytesLogo = ms.ToArray();
ms.Dispose();
} var bytes = QRCoder(text, format, bytesLogo, keepWhiteBorderPixelVal); if (bytes == null || bytes.Length < )
{
return;
} var saveDirPath = System.IO.Path.GetDirectoryName(savePath);
if (!System.IO.Directory.Exists(saveDirPath))
{
System.IO.Directory.CreateDirectory(saveDirPath);
}
var fs = new System.IO.FileStream(savePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None);
fs.Write(bytes, , bytes.Length);
fs.Close();
}
/// <summary>
/// 生成二维码(320*320)
/// </summary>
/// <param name="text">文本内容</param>
/// <param name="format">保存格式</param>
/// <param name="logoImgae">Logo图片(缩放到真实二维码区域尺寸的1/6)</param>
/// <param name="keepWhiteBorderPixelVal">白边处理(负值表示不做处理,最大值不超过真实二维码区域的1/10)</param>
/// <returns></returns>
public static byte[] QRCoder(string text, SkiaSharp.SKEncodedImageFormat format, byte[] logoImgae = null, int keepWhiteBorderPixelVal = -)
{
byte[] reval = null;
int width = ;
int height = ;
var qRCodeWriter = new ZXing.QrCode.QRCodeWriter();
var hints = new Dictionary<ZXing.EncodeHintType, object>();
hints.Add(ZXing.EncodeHintType.CHARACTER_SET, "utf-8");
hints.Add(ZXing.EncodeHintType.QR_VERSION, );
hints.Add(ZXing.EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.Q);
var bitMatrix = qRCodeWriter.encode(text, ZXing.BarcodeFormat.QR_CODE, width, height, hints);
var w = bitMatrix.Width;
var h = bitMatrix.Height;
var sKBitmap = new SkiaSharp.SKBitmap(w, h); int blackStartPointX = ;
int blackStartPointY = ;
int blackEndPointX = w;
int blackEndPointY = h; #region --绘制二维码(同时获取真实的二维码区域起绘点和结束点的坐标)--
var sKCanvas = new SkiaSharp.SKCanvas(sKBitmap);
var sKColorBlack = SkiaSharp.SKColor.Parse("");
var sKColorWihte = SkiaSharp.SKColor.Parse("ffffff");
sKCanvas.Clear(sKColorWihte);
bool blackStartPointIsNotWriteDown = true;
for (var y = ; y < h; y++)
{
for (var x = ; x < w; x++)
{
var flag = bitMatrix[x, y];
if (flag)
{
if (blackStartPointIsNotWriteDown)
{
blackStartPointX = x;
blackStartPointY = y;
blackStartPointIsNotWriteDown = false;
}
blackEndPointX = x;
blackEndPointY = y;
sKCanvas.DrawPoint(x, y, sKColorBlack);
}
else
{
//sKCanvas.DrawPoint(x, y, sKColorWihte);//不用绘制(背景是白色的)
}
}
}
sKCanvas.Dispose();
#endregion int qrcodeRealWidth = blackEndPointX - blackStartPointX;
int qrcodeRealHeight = blackEndPointY - blackStartPointY; #region -- 处理白边 --
if (keepWhiteBorderPixelVal > -)//指定了边框宽度
{
var borderMaxWidth = (int)Math.Floor((double)qrcodeRealWidth / );
if (keepWhiteBorderPixelVal > borderMaxWidth)
{
keepWhiteBorderPixelVal = borderMaxWidth;
}
var nQrcodeRealWidth = width - keepWhiteBorderPixelVal - keepWhiteBorderPixelVal;
var nQrcodeRealHeight = height - keepWhiteBorderPixelVal - keepWhiteBorderPixelVal; var sKBitmap2 = new SkiaSharp.SKBitmap(width, height);
var sKCanvas2 = new SkiaSharp.SKCanvas(sKBitmap2);
sKCanvas2.Clear(sKColorWihte);
//二维码绘制到临时画布上时无需抗锯齿等处理(避免文件增大)
sKCanvas2.DrawBitmap(
sKBitmap,
new SkiaSharp.SKRect
{
Location = new SkiaSharp.SKPoint { X = blackStartPointX, Y = blackStartPointY },
Size = new SkiaSharp.SKSize { Height = qrcodeRealHeight, Width = qrcodeRealWidth }
},
new SkiaSharp.SKRect
{
Location = new SkiaSharp.SKPoint { X = keepWhiteBorderPixelVal, Y = keepWhiteBorderPixelVal },
Size = new SkiaSharp.SKSize { Width = nQrcodeRealWidth, Height = nQrcodeRealHeight }
}); blackStartPointX = keepWhiteBorderPixelVal;
blackStartPointY = keepWhiteBorderPixelVal;
qrcodeRealWidth = nQrcodeRealWidth;
qrcodeRealHeight = nQrcodeRealHeight; sKCanvas2.Dispose();
sKBitmap.Dispose();
sKBitmap = sKBitmap2;
}
#endregion #region -- 绘制LOGO --
if (logoImgae != null && logoImgae.Length > )
{
SkiaSharp.SKBitmap sKBitmapLogo = SkiaSharp.SKBitmap.Decode(logoImgae);
if (!sKBitmapLogo.IsEmpty)
{
var sKPaint2 = new SkiaSharp.SKPaint
{
FilterQuality = SkiaSharp.SKFilterQuality.None,
IsAntialias = true
};
var logoTargetMaxWidth = (int)Math.Floor((double)qrcodeRealWidth / );
var logoTargetMaxHeight = (int)Math.Floor((double)qrcodeRealHeight / );
var qrcodeCenterX = (int)Math.Floor((double)qrcodeRealWidth / );
var qrcodeCenterY = (int)Math.Floor((double)qrcodeRealHeight / );
var logoResultWidth = sKBitmapLogo.Width;
var logoResultHeight = sKBitmapLogo.Height;
if (logoResultWidth > logoTargetMaxWidth)
{
var r = (double)logoTargetMaxWidth / logoResultWidth;
logoResultWidth = logoTargetMaxWidth;
logoResultHeight = (int)Math.Floor(logoResultHeight * r);
}
if (logoResultHeight > logoTargetMaxHeight)
{
var r = (double)logoTargetMaxHeight / logoResultHeight;
logoResultHeight = logoTargetMaxHeight;
logoResultWidth = (int)Math.Floor(logoResultWidth * r);
}
var pointX = qrcodeCenterX - (int)Math.Floor((double)logoResultWidth / ) + blackStartPointX;
var pointY = qrcodeCenterY - (int)Math.Floor((double)logoResultHeight / ) + blackStartPointY; var sKCanvas3 = new SkiaSharp.SKCanvas(sKBitmap);
var sKPaint = new SkiaSharp.SKPaint
{
FilterQuality = SkiaSharp.SKFilterQuality.Medium,
IsAntialias = true
};
sKCanvas3.DrawBitmap(
sKBitmapLogo,
new SkiaSharp.SKRect
{
Location = new SkiaSharp.SKPoint { X = , Y = },
Size = new SkiaSharp.SKSize { Height = sKBitmapLogo.Height, Width = sKBitmapLogo.Width }
},
new SkiaSharp.SKRect
{
Location = new SkiaSharp.SKPoint { X = pointX, Y = pointY },
Size = new SkiaSharp.SKSize { Height = logoResultHeight, Width = logoResultWidth }
}, sKPaint);
sKCanvas3.Dispose();
sKPaint.Dispose();
sKBitmapLogo.Dispose();
}
else
{
sKBitmapLogo.Dispose();
}
}
#endregion SkiaSharp.SKImage sKImage = SkiaSharp.SKImage.FromBitmap(sKBitmap);
sKBitmap.Dispose();
var data = sKImage.Encode(format, );
sKImage.Dispose();
reval = data.ToArray();
data.Dispose(); return reval;
}
public static string QRDecoder(string qrCodeFilePath)
{
if (!System.IO.File.Exists(qrCodeFilePath))
{
throw new Exception("文件不存在");
} System.IO.FileStream fileStream = new System.IO.FileStream(qrCodeFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
if (fileStream.Length > maxLength)
{
fileStream.Dispose();
throw new Exception("图片文件太大");
}
return QRDecoder(fileStream);
}
public static string QRDecoder(byte[] qrCodeBytes)
{
if(qrCodeBytes==null|| qrCodeBytes.Length<)
{
throw new Exception("参数qrCodeBytes不存在");
}
if (qrCodeBytes.Length > maxLength)
{
throw new Exception("图片文件太大");
}
System.IO.MemoryStream ms = new System.IO.MemoryStream(qrCodeBytes);
return QRDecoder(ms);
}
public static string QRDecoder(System.IO.Stream qrCodeFileStream)
{
var sKManagedStream = new SkiaSharp.SKManagedStream(qrCodeFileStream, true);
var sKBitmap = SkiaSharp.SKBitmap.Decode(sKManagedStream);
sKManagedStream.Dispose();
if (sKBitmap.IsEmpty)
{
sKBitmap.Dispose();
throw new Exception("未识别的图片文件");
} var w = sKBitmap.Width;
var h = sKBitmap.Height;
int ps = w * h;
byte[] bytes = new byte[ps * ];
int byteIndex = ;
for (var x = ; x < w; x++)
{
for (var y = ; y < h; y++)
{
var color = sKBitmap.GetPixel(x, y);
bytes[byteIndex + ] = color.Red;
bytes[byteIndex + ] = color.Green;
bytes[byteIndex + ] = color.Blue;
byteIndex += ;
}
}
sKBitmap.Dispose(); var qRCodeReader = new ZXing.QrCode.QRCodeReader();
var rGBLuminanceSource = new ZXing.RGBLuminanceSource(bytes, w, h);
var hybridBinarizer = new ZXing.Common.HybridBinarizer(rGBLuminanceSource);
var binaryBitmap = new ZXing.BinaryBitmap(hybridBinarizer);
var hints = new Dictionary<ZXing.DecodeHintType, object>();
hints.Add(ZXing.DecodeHintType.CHARACTER_SET, "utf-8");
var result = qRCodeReader.decode(binaryBitmap, hints); return result != null ? result.Text : "";
}
}
开个控制台程序测试一下,测试代码:
static void Main(string[] args)
{
var path = @"d:\a\文字设计.png";//size=595*842
ImageHelper.ImageMaxCutByCenter(path, @"d:\a\文字设计002.png", , , );//size=1024*768
ImageHelper.ImageMaxCutByCenter(path, @"d:\a\文字设计003.png", , , );//size=768*1024
ImageHelper.ImageScalingToRange(path, @"d:\a\文字设计004.png", , , );//size=542*768
ImageHelper.ImageScalingToRange(path, @"d:\a\文字设计005.png", , , );//size=724*1024
ImageHelper.ImageScalingByOversized(path, @"d:\a\文字设计006.png", , , );//size=226*320
ImageHelper.ImageScalingByOversized(path, @"d:\a\文字设计007.png", , , );//size=320*453 var qrcodeSavePath = @"d:\a\hello.png";
var qrcodeLogoPath = @"d:\a\logo.png";
var qrcodeWhiteBorderPixelVal = ;
var qrcodeText = "高堂明镜悲白发,朝如青丝暮成雪!";
ImageHelper.QRCoder(qrcodeText, qrcodeSavePath, qrcodeLogoPath, qrcodeWhiteBorderPixelVal);
var result = ImageHelper.QRDecoder(qrcodeSavePath);
Console.WriteLine(result); var imageInfo = ImageHelper.GetImageInfo(qrcodeLogoPath);
Console.WriteLine($"WIDTH={imageInfo.Item1}&HEIGHT={imageInfo.Item2}&LENGTH={imageInfo.Item3}&FORMAT={imageInfo.Item4}");
}
程序运行结果:
图片处理结果:
最后的图片质量还是挺好的,如果你也有在 .net core 下的图片处理需求,可以试试这个处理方式!
以后会陆续将自己写的一些小东西发出来和大家一起分享,多半都是一些零零碎碎的东西,目的在于解决实实在在的具体的问题,希望对各位来过的朋友有所帮助!
.net core 的图片处理及二维码的生成及解析的更多相关文章
- ZXing二维码的生成和解析
Zxing是Google提供的关于条码(一维码.二维码)的解析工具,提供了二维码的生成与解析的方法, 现在我简单介绍一下使用Java利用Zxing生成与解析二维码 注意: 二维码的生成需要借助辅助类( ...
- 关于java的二维码的生成与解析
本文说的是通过zxing实现二维码的生成与解析,看着很简单,直接上代码 import java.io.File; import java.io.IOException; import java.nio ...
- Java 条形码 二维码 的生成与解析
Barcode简介 Barcode是由一组按一定编码规则排列的条,空符号,用以表示一定的字符,数字及符号组成的,一种机器可读的数据表示方式. Barcode的形式多种多样,按照它们的外观分类: Lin ...
- JavaUtil_02_二维码的生成与解析
1.引入jar包 zxing-core-1.7.jar : http://viralpatel.net/blogs/download/jar/zxing-core-1.7.jar zxing-j ...
- java实现二维码的生成与解析
简单介绍下二维码:二维码其实就是一种编码技术,只是这种编码技术是用在图片上了,将给定的一些文字,数字转换为一张经过特定编码的图片,而解析二维码则相反,就是将一张经过编码的图片解析为数字或者文字. 当然 ...
- 【Java】Java实现二维码的生成与解析
pom依赖 <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</ ...
- java实现二维码的生成和解析:QRCode、zxing 两种方式
第一种:QRCode.jar,使用QRCode生成和解析二维码 1.导入jar包 2.代码 (1)QRCodeUtil .java import com.swetake.util.Qrcode; i ...
- java二维码的生成与解析代码
二维码,是一种采用黑白相间的平面几何图形通过相应的编码算法来记录文字.图片.网址等信息的条码图片.如下图 二维码的特点: 1. 高密度编码,信息容量大 可容纳多达1850个大写字母或2710个数字或 ...
- Android二维码的生成,解析以及扫描功能
<1> 布局只有2个按钮,实现生成二维码和解析二维码 <Button android:layout_width="wrap_content" android:la ...
随机推荐
- vm12 安装ubuntu15.10详细图文教程 虚拟机安装ubuntu安装 ubuntu更新软件 ubuntu一直卡在下载语言怎么办?
1,准备工作-ubuntu下载 ubuntu官网下载 如何官网下载ubuntu http://www.ubuntu.com/download/ 2,打开虚拟机 虚拟机安装ubuntu15.10 虚拟机 ...
- js内存深入学习(二)
继上一篇文章 js内存深入学习(一) 3. 内存泄漏 对于持续运行的服务进程(daemon),必须及时释放不再用到的内存.否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃. 对于不再用到的内 ...
- Redis的复制是如何实现的?
前言 关系数据库通常会使用一个主服务器向多个从服务器发送更新,并使用从服务器来处理所有的读请求,Redis采用了同样方法来实现自己的复制特性. 简单总结起来就是:在接收到主服务器发送的数据初始副本之后 ...
- 表达式目录树(Expression)
一:什么是表达式树 Expression我们称为是表达式树,是一种数据结构体,用于存储需要计算,运算的一种结构,这种结构可以只是存储,而不进行运算.通常表达式目录树是配合Lambda一起来使用的,la ...
- ioc初步理解(一) 简单实用autofac搭建mvc三层+ioc(codeFirst)
1]首先搭好框架 1.1]搭建ui层 1.2]创建其他内库文件 整个项目基本部分搭建完毕之后如下 2]使用nuget引用文件 先在每一个项目中引入ef 然后再UI层引入以下两个文件autofac和Au ...
- WebService简单介绍(一)
分布式系统或软件如何通信?使用WebService服务.说它是服务可以,web通信中间件也ok,web通信组件....... 特点 自包含 自描述 跨平台.跨语言 基于开放和标准 (用了xml,嗯,开 ...
- 安装VS时,双击setup.exe后界面一闪而过的问题
问题:安装VS时,双击setup.exe界面一闪而过的问题 解决: 百度后说需要到"控制面板/添加和管理程序"关闭系统自带的netframework3.x及以上版本. 1.查看所有 ...
- 互联网安全中心(CIS)发布新版20大安全控制
这些最佳实践最初由SANS研究所提出,名为“SANS关键控制”,是各类公司企业不可或缺的安全控制措施.通过采纳这些控制方法,公司企业可防止绝大部分的网络攻击. 有效网络防御的20条关键安全控制 对上一 ...
- No module named "Crypto",如何安装Python三方模块Crypto
前两天公司公司老总让我研究怎么用企业微信第三方应用进行官网对接,完成URL回调验证问题. 具体如何进行Python 的Django网站与企业微信第三方应用进行回调验证的博客地址为:https://ww ...
- 01-vue学习之前的准备
一.具备的基础知识 1.扎实的HTML/CSS/Javascript基本功,这是前置条件. 2.不要用任何的构建项目工具,只用最简单的<script>,把教程里的例子模仿一遍,理解用法.不 ...