【SkiaSharp绘图09】SKBitmap属性详解

文章目录

  • SKBitmap
    • 与Bitmap性能对比
    • 对比结果
  • 构造函数
    • SKBitmap()
    • SKBitmap(SKImageInfo)
    • SKBitmap(Int32, Int32, SKColorType, SKAlphaType, SKColorSpace)
  • SKBitmap属性
    • AlphaType
    • ByteCount
    • Bytes
    • BytesPerPixel
    • ColorSpace
    • ColorType
    • DrawsNothing
    • Info
    • IsEmpty
    • IsImmutable
    • IsNull
    • Pixels
    • ReadyToDraw
    • RowBytes
    • Width、Height
    • 示例

SKBitmap

  • 光栅位图,整数的宽度、高度,格式(颜色类型)以及指向实际像素的指针。
  • SkBitmap 构建于 SkImageInfo 之上,包含整数宽度和高度、描述像素格式的 SkColorType 和 SkAlphaType 以及描述颜色范围的 SkColorSpace。 SkBitmap指向SkPixelRef,它描述了像素的物理数组。 SkImageInfo 边界可以位于完全位于 SkPixelRef 边界内的任何位置。
  • SkBitmap可以使用SkCanvas来绘制。 SkBitmap 可以是 SkCanvas 绘制成员函数的绘制目标。 SkBitmap 作为像素容器的灵活性限制了目标平台可用的一些优化。
  • 如果像素数组主要是只读的,请使用 SkImage 以获得更好的性能。如果主要写入像素数组,请使用 SkSurface 以获得更好的性能。
  • SkBitmap 不是线程安全的。尽管线程可以共享底层像素数组,但每个线程都必须拥有自己的 SkBitmap 字段副本。
  • 使用GetPixels()获取位图的像素地址。(注意,1.60.0版本之后不再需要调用LockPixels和UnlockPixels方法)。

与Bitmap性能对比

分别测试,单像素GetPixel与指针访问的性能。

  1. 分别加载SKBitmap和Bitmap图像
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);

if (skBmp == null)
{
    skBmp = SKBitmap.Decode(@"Images\AIWoman.png");
}
if (bitmap == null)
{
    bitmap = new System.Drawing.Bitmap(@"Images\AIWoman.png");
}
  1. 逐像素分别访问SKBitmap与Bitmap对象
#region GetPixel对比
long sumR = 0;
long sumG = 0;
long sumB = 0;

var sw = Stopwatch.StartNew();
for (var row = 0; row < skBmp.Height; row++)
{
    for (var col = 0; col < skBmp.Width; col++)
    {
        var color = skBmp.GetPixel(col, row);
        sumR += color.Red;
        sumG += color.Green;
        sumB += color.Blue;
    }
}
sw.Stop();

long totalR = 0;
long totalG = 0;
long totalB = 0;

var sw1 = Stopwatch.StartNew();

for (var row = 0; row < bitmap.Height; row++) 
{
    for (var col = 0; col < bitmap.Width; col++)
    {
        var color = bitmap.GetPixel(col, row);
        totalR += color.R;
        totalG += color.G;
        totalB += color.B;
    }
}
sw1.Stop();
#endregion
  1. 分别显示耗时
var xOffset = 20F;
var yOffset = 50F;
var paint = new SKPaint();
paint.IsAntialias = true;
paint.TextSize = 24;
paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");
canvas.DrawText($"图像大小:{skBmp.Width}x{skBmp.Height}", xOffset, yOffset, paint);
yOffset += paint.FontSpacing;
canvas.DrawText("GetPixel效率对比:", xOffset, yOffset, paint);
yOffset += paint.FontSpacing;
canvas.DrawText($"SKBitmap GetPixel耗时:{sw.ElapsedMilliseconds}ms,R:{sumR},G:{sumG},B:{sumB}", xOffset, yOffset, paint);
yOffset += paint.FontSpacing;
canvas.DrawText($"Bitmap GetPixel耗时:{sw1.ElapsedMilliseconds}ms,R:{totalR},G:{totalG},B:{totalB}", xOffset, yOffset, paint);
yOffset += paint.FontSpacing;
  1. 使用指针方式逐像素访问
#region  指针访问

sumR = 0;
sumG = 0;
sumB = 0;

sw = Stopwatch.StartNew();
// 获取指向像素数据的指针
IntPtr pixelsPtr = skBmp.GetPixels();
int width = bitmap.Width;
int height = bitmap.Height;
int bytesPerPixel = skBmp.Info.BytesPerPixel;
// 使用不安全代码块访问指针数据
unsafe
{
    byte* ptrP = (byte*)pixelsPtr.ToPointer();
    for (int y = 0; y < height; y++)
    {
        var offset = y * width;
        for (int x = 0; x < width; x++)
        {
            // 计算当前像素的指针位置
            byte* pixel = ptrP + (offset + x) * bytesPerPixel;

            // 累加各通道的值
            sumB += pixel[0];   // 蓝色通道
            sumG += pixel[1];  // 绿色通道
            sumR += pixel[2];    // 红色通道
        }
    }
}
sw.Stop();

sw1 = Stopwatch.StartNew();
// 定义锁定区域
Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
// 锁定位图的指定区域
BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);

// 获取指向第一个像素数据的指针
IntPtr ptr = bmpData.Scan0;

// 判断像素格式,以确保正确处理像素数据
int pixelSize = Image.GetPixelFormatSize(bitmap.PixelFormat) / 8;

totalB = 0;
totalG = 0;
totalR = 0;

// 使用不安全代码块访问指针数据
unsafe
{
    byte* ptrP = (byte*)ptr.ToPointer();
    for (int y = 0; y < height; y++)
    {
        var offset = y * width;
        for (int x = 0; x < width; x++)
        {
            // 计算当前像素的指针位置
            byte* pixel = ptrP + (offset + x) * bytesPerPixel;

            // 累加各通道的值
            totalB+= pixel[0];   // 蓝色通道
            totalG+= pixel[1];  // 绿色通道
            totalR += pixel[2];    // 红色通道
        }
    }
}            
// 解锁位图
bitmap.UnlockBits(bmpData);
sw.Stop();
#endregion
  1. 分别显示耗时
canvas.DrawText("指针访问 对比:", xOffset, yOffset, paint);
yOffset += paint.FontSpacing;
canvas.DrawText($"SKBitmap 指针访问耗时:{sw.ElapsedMilliseconds}ms,R:{sumR},G:{sumG},B:{sumB}", xOffset, yOffset, paint);
yOffset += paint.FontSpacing;
canvas.DrawText($"Bitmap 指针访问耗时:{sw1.ElapsedMilliseconds}ms,R:{totalR},G:{totalG},B:{totalB}", xOffset, yOffset, paint);
yOffset += paint.FontSpacing;

canvas.DrawBitmap(skBmp,new SKRect(xOffset,yOffset,xOffset+400,yOffset+400), paint);
paint.Dispose();

效率对比

对比结果

SKBitmap的GetPixel对Bitmap的GetPixel快3倍左右,两个对象的指针访问方式性能一样,比GetPixel方法快几十、上百倍。

构造函数

SKBitmap()

public SKBitmap ();

构造一个0x0的图像,ColorType为Unknown,未分配内存。

SKBitmap(SKImageInfo)

public SKBitmap (SkiaSharp.SKImageInfo info);

根据指定的SKImageInfo构造位图对象。

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);

using (var paint = new SKPaint())
{
    paint.IsAntialias = true;
    paint.TextSize = 18F;
    paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");                

    var colorTypes = new SKColorType[] { SKColorType.Rgba8888, SKColorType.Gray8 };

    foreach(var colorType in colorTypes)
    {
        paint.IsStroke = true;
        var skImgInfo = new SKImageInfo(200, 100, colorType);

        var pt = new SKPoint(20F, 20F);
        using (var sBmp = new SKBitmap(skImgInfo))
        {
            canvas.DrawBitmap(sBmp, pt, paint);
            canvas.DrawRect(new SKRect(pt.X, pt.Y, pt.X + sBmp.Width, pt.Y + sBmp.Height), paint);

            paint.IsStroke = false;
            var yOffset = 20 + sBmp.Height + paint.FontSpacing;

            canvas.DrawText($"SKImageInfo的属性与值", 20, yOffset, paint);
            // 获取对象的类型信息
            Type type = skImgInfo.GetType();

            // 获取所有公共属性
            PropertyInfo[] properties = type.GetProperties();

            // 遍历并打印每个属性的名称和值
            foreach (PropertyInfo property in properties)
            {
                yOffset += paint.FontSpacing;
                string name = property.Name;
                object value = property.GetValue(skImgInfo);
                if (value == null) value = "null";
                canvas.DrawText($"{name}:{value}", 20, yOffset, paint);
            }
        }

        canvas.Translate(400, 0);
    }                
}

分别以SKColorType.Rgba8888和 SKColorType.Gray8创建两幅图像,查看其SKImageInfo各属性的值。
SKImageInfo值

SKBitmap(Int32, Int32, SKColorType, SKAlphaType, SKColorSpace)

public SKBitmap (int width, int height, SkiaSharp.SKColorType colorType, SkiaSharp.SKAlphaType alphaType, SkiaSharp.SKColorSpace colorspace);

创建一个SKBitmap,在SKBitmap上绘制一个圆,再将这个SKBitmap绘制到界面上。

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);

using (var paint = new SKPaint())
{
    paint.IsAntialias = true;
    paint.TextSize = 18F;
    paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");

    // 定义位图的宽度和高度
    int width = 600;
    int height = 600;

    // 定义颜色类型、透明度类型和颜色空间
    SKColorType colorType = SKColorType.Rgba8888;
    SKAlphaType alphaType = SKAlphaType.Premul;
    SKColorSpace colorSpace = SKColorSpace.CreateSrgb();
    using (var skBmp = new SKBitmap(width, height, colorType, alphaType, colorSpace))
    {
        using (var sCanvas = new SKCanvas(skBmp))
        {
            paint.Color = SKColors.LightGreen;
            sCanvas.DrawCircle(skBmp.Width / 2, skBmp.Height / 2, skBmp.Width / 4, paint);
        }
        canvas.Translate(100, 100);
        canvas.DrawBitmap(skBmp, 0, 0, paint);
        paint.IsStroke = true;
        canvas.DrawRect(skBmp.Info.Rect, paint);
    }                   
}

SKBitmap

SKBitmap属性

AlphaType

public SkiaSharp.SKAlphaType AlphaType { get; }

定义了位图像素的透明度处理方式。透明度(或Alpha通道)在图形处理和图像合成中起着关键作用,因为它决定了像素的透明度或不透明度。
不同枚举值的意义:

  1. Unknown:

    • 描述:Alpha 通道的类型未知。这通常用于未明确指定 alpha 类型的图像。
    • 应用场景:较少使用,因为不明确的 alpha 类型会导致不确定的渲染结果。
  2. Opaque:

    • 描述:图像是完全不透明的,没有透明度信息。Alpha 通道的值被忽略。
    • 应用场景:用于不需要处理透明度的图像,提高渲染效率。
  3. Premul (Pre-multiplied alpha):

    • 描述:RGB 值已经被 alpha 通道值预乘,即每个颜色分量已经乘以其对应的 alpha 值。例如,如果 alpha 为 0.5(半透明),则红色分量被乘以 0.5。
    • 应用场景:常用于图像合成,因为这种方式可以简化混合操作,减少计算开销。
  4. Unpremul (Unpremultiplied alpha):

    • 描述:RGB 值没有被 alpha 通道值预乘。颜色和 alpha 是独立存储的。
    • 应用场景:在图像编辑和处理时使用,因为它保留了原始颜色值,适合需要精细调整颜色和透明度的操作。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);

using (var paint = new SKPaint())
{
    paint.IsAntialias = true;
    paint.TextSize = 18F;
    paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");

    // 定义位图的宽度和高度
    int width = 150;
    int height = 150;

    // 定义颜色类型、透明度类型和颜色空间
    SKColorType colorType = SKColorType.Rgba8888;

    var skColors = new SKColor[] { new SKColor(255, 0, 0, 128), new SKColor(0, 255, 0, 128), new SKColor(0, 0, 255, 128) };
    var skAlphaTypes = new SKAlphaType[] { SKAlphaType.Opaque, SKAlphaType.Premul, SKAlphaType.Unpremul };

    var pts = new SKPoint[] { new SKPoint(100, 30), new SKPoint(200, 30), new SKPoint(150, 90) };

    var bmps = new List<SKBitmap>();

    foreach (var alphaType in skAlphaTypes)
    {
        var index = 0;
        var y = 40F;
        canvas.DrawText($"AlphaType:{alphaType}", 400, y += paint.FontSpacing, paint);
        foreach (var skColor in skColors)
        {
            using (var skBmp = new SKBitmap(width, height, colorType, alphaType))
            {
                using (var sCanvas = new SKCanvas(skBmp))
                {
                    paint.Color = skColor;
                    sCanvas.DrawCircle(skBmp.Width / 2, skBmp.Height / 2, skBmp.Width / 2, paint);
                }
                canvas.DrawBitmap(skBmp, pts[index++], paint);

                var color = skBmp.GetPixel(width / 2, height / 2);

                canvas.DrawText($"R:{color.Red},G:{color.Green},B:{color.Blue},A:{color.Alpha}", 400, y += paint.FontSpacing, paint);
            }
        }
        canvas.Translate(0, 240);
    }
}

AlphaType

ByteCount

public int ByteCount { get; }

根据RowBytes*Height,返回像素的字节大小。

Bytes

public byte[] Bytes { get; }

获取所有像素数据的副本。

BytesPerPixel

public int BytesPerPixel { get; }

获取每个像素的字节数。如果ColorType为Unknown,则该值为0。

ColorSpace

public SkiaSharp.SKColorSpace ColorSpace { get; }

获取和设置位图的色彩空间。

ColorType

public SkiaSharp.SKColorType ColorType { get; }

获取位图的颜色类型。

DrawsNothing

public bool DrawsNothing { get; }

判断位图是否有影响绘制效果。无效果,返回true,若则返回false。

Info

public SkiaSharp.SKImageInfo Info { get; }

获取具有位图所有属性的 SKImageInfo 实例。

IsEmpty

public bool IsEmpty { get; }

判断位图的尺寸是否为0。
DrawsNothing除了判断尺寸,还判断其它,而IsEmpty只判断尺寸。

IsImmutable

public bool IsImmutable { get; }

判断位图内容是否不可变。
不可变的位图性能更优,可通过SKBitmap对的的SetImmutable()方法设置。

IsNull

public bool IsNull { get; }

直接new SKBitmap()返回true,new SKBitmap(0,0)返回的是false。

Pixels

public SkiaSharp.SKColor[] Pixels { get; set; }

返回所有像素的颜色数组。

ReadyToDraw

public bool ReadyToDraw { get; }

获取位图是否可以有效绘制。

RowBytes

public int RowBytes { get; }

返回每行的字节数。

Width、Height

public int Width { get; }
public int Height { get; }

获取位图的宽与高。

示例

 var canvas = e.Surface.Canvas;
 var info = e.Info;
 canvas.Clear(SKColors.White);

 using (var paint = new SKPaint())
 {
     paint.IsAntialias = true;
     paint.TextSize = 18F;
     paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");

     var yOffset = 50F;

     using (var skBmp0x0 = new SKBitmap(0, 0))
     using (var skBmp1x1 = new SKBitmap(1, 1))
     {
         
         canvas.DrawText($"0x0SKBitmap,DrawsNothing:{skBmp0x0.DrawsNothing}", 20, yOffset += paint.FontSpacing, paint);
         canvas.DrawText($"1x1SKBitmap,DrawsNothing:{skBmp1x1.DrawsNothing}", 20, yOffset += paint.FontSpacing, paint);

         canvas.DrawText($"0x0SKBitmap,IsEmpty:{skBmp0x0.IsEmpty}", 20, yOffset += paint.FontSpacing, paint);
         canvas.DrawText($"1x1SKBitmap,IsEmpty:{skBmp1x1.IsEmpty}", 20, yOffset += paint.FontSpacing, paint);

         canvas.DrawText($"0x0SKBitmap,IsNull:{skBmp0x0.IsNull}", 20, yOffset += paint.FontSpacing, paint);
         canvas.DrawText($"1x1SKBitmap,IsNull:{skBmp1x1.IsNull}", 20, yOffset += paint.FontSpacing, paint);

         canvas.DrawText($"0x0SKBitmap,ByteCount:{skBmp0x0.ByteCount}", 20, yOffset += paint.FontSpacing, paint);
         canvas.DrawText($"1x1SKBitmap,ByteCount:{skBmp1x1.ByteCount}", 20, yOffset += paint.FontSpacing, paint);

         canvas.DrawText($"0x0SKBitmap,BytesPerPixel:{skBmp0x0.BytesPerPixel}", 20, yOffset += paint.FontSpacing, paint);
         canvas.DrawText($"1x1SKBitmap,BytesPerPixel:{skBmp1x1.BytesPerPixel}", 20, yOffset += paint.FontSpacing, paint);

         canvas.DrawText($"0x0SKBitmap,IsImmutable:{skBmp0x0.IsImmutable}", 20, yOffset += paint.FontSpacing, paint);
         canvas.DrawText($"1x1SKBitmap,IsImmutable:{skBmp1x1.IsImmutable}", 20, yOffset += paint.FontSpacing, paint);
         skBmp1x1.SetImmutable();
         canvas.DrawText($"1x1SKBitmap,IsImmutable:{skBmp1x1.IsImmutable}", 20, yOffset += paint.FontSpacing, paint);

         canvas.DrawText($"0x0SKBitmap,RowBytes:{skBmp0x0.RowBytes}", 20, yOffset += paint.FontSpacing, paint);
         canvas.DrawText($"1x1SKBitmap,RowBytes:{skBmp1x1.RowBytes}", 20, yOffset += paint.FontSpacing, paint);

         canvas.DrawText($"0x0SKBitmap,Width:{skBmp0x0.Width},Height:{skBmp0x0.Height}", 20, yOffset += paint.FontSpacing, paint);
         canvas.DrawText($"1x1SKBitmap,Width:{skBmp1x1.Width},Height:{skBmp1x1.Height}", 20, yOffset += paint.FontSpacing, paint);
     }
 }

SKBitmap属性相关

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/733738.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

投资者回归理性?美股去年备受追捧的AI概念股,今年超过一半在下跌

喊两句AI就能圈钱的日子一去不复返了&#xff0c;未来企业要用实打实的业绩说话。 正文 去年备受追捧的AI概念股中&#xff0c;今年绝大多数已经开始下跌。面对越来越谨慎的投资者&#xff0c; 上市公司或许很难再打着AI的旗号圈钱。 今年&#xff0c;标普500指数中有60%的股…

动态规划:基本概念

Dynamic Programming 动态规划&#xff08;Dynamic Programming, DP&#xff09; 是一种算法设计技巧&#xff0c;通常用来解决具有重叠子问题和最优子结构性质的问题。它通过将问题分解为更小的子问题&#xff0c;逐步解决这些子问题并将结果存储起来&#xff0c;以避免重复计…

U-Net for Image Segmentation

1.Unet for Image Segmentation 笔记来源&#xff1a;使用Pytorch搭建U-Net网络并基于DRIVE数据集训练(语义分割) 1.1 DoubleConv (Conv2dBatchNorm2dReLU) import torch import torch.nn as nn import torch.nn.functional as F# nn.Sequential 按照类定义的顺序去执行模型&…

win10/11磁盘管理

win10/11磁盘管理 合并磁盘分区的前提是你的两个磁盘区域是相邻的&#xff0c;比如如下&#xff1a; 如果需要吧这个磁盘进行分解&#xff0c;你可以选择压缩一部分磁盘或者是直接删除卷 我这里的话&#xff0c;因为压缩出来的卷和C盘好像是不相邻的&#xff08;我之前做过&…

【SpringCloud-Seata源码分析2】

文章目录 分支事务注册-客户端分支事务服务端的执行 分支事务注册-客户端 第一篇我们将全局事务启动&#xff0c;以及开启源码分析完成了&#xff0c;现在我们需要看一下分支事务注册。 我们分支事务的开始需要从PreparedStatementProxy#executeUpdate中去看。 public class…

GPT-4o一夜被赶超,Claude 3.5一夜封王|快手可灵大模型推出图生视频功能|“纯血”鸿蒙大战苹果AI|智谱AI“钱途”黯淡|月之暗面被曝进军美国

快手可灵大模型推出图生视频功能“纯血”鸿蒙大战苹果AI&#xff0c;华为成败在此一举大模型低价火拼间&#xff0c;智谱AI“钱途”黯淡手握新“王者”&#xff0c;腾讯又跟渠道干上了“美食荒漠”杭州&#xff0c;走出一个餐饮IPOGPT-4o一夜被赶超&#xff0c;Anthropic推出Cl…

Rocky Linux archive下载地址

Index of /vault/rocky/https://dl.rockylinux.org/vault/rocky/

利口 202. 快乐数

力扣 202. 快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。如果这个过程 结…

猫头虎分享已解决Bug || Null Pointer Exception: `java.lang.NullPointerException`

猫头虎分享已解决Bug || Null Pointer Exception: java.lang.NullPointerException &#x1f63a;&#x1f42f; 关于猫头虎 大家好&#xff0c;我是猫头虎&#xff0c;别名猫头虎博主&#xff0c;擅长的技术领域包括云原生、前端、后端、运维和AI。我的博客主要分享技术教程…

营业性演出许可证:直播行业规范与繁荣的关键

随着互联网和直播行业的迅猛发展&#xff0c;营业性演出许可证的重要性愈加凸显。《网络表演经纪机构管理办法》明确指出&#xff0c;任何形式的盈利性演出活动&#xff0c;无论是线下还是线上&#xff0c;都必须取得营业性演出许可证。这一规定为行业规范提供了法律基础&#…

钓鱼隐藏--文件后缀压缩文件捆绑文件

免责声明:本文仅做技术交流与学习... 目录 文件后缀-钓鱼伪装-RLO 压缩文件-自解压-释放执行 捆绑文件-打包加载-释放执行 文件后缀-钓鱼伪装-RLO 改后缀--伪装 w.exe wgpj.exe (要改的后缀反写)(jpg--->gpj) | (光标移到要改的后缀的前边)(w和g中间) …

idea导入文件里面的子模块maven未识别处理解决办法

1、File → Project Structure → 点击“Modules” → 点击“” → “Import Model” 2、可以看到很多子模块&#xff0c;选择子模块下的 pom.xml 文件导入一个一个点累死了&#xff0c;父目录下也没有pom文件 解决办法&#xff1a;找到子模块中有一个pom.xml文件&#xff0c;…

CentOS9镜像下载地址加速下载

CentOS 9 是 CentOS 项目的最新版本之一&#xff0c;它基于 RHEL&#xff08;Red Hat Enterprise Linux&#xff09;9 的源代码构建。CentOS&#xff08;Community ENTerprise Operating System&#xff09;是一个免费的企业级 Linux 发行版&#xff0c;旨在提供一个与 RHEL 兼…

基于YOLOv5的PCB板缺陷检测系统的设计与实现

简介 随着电子设备的广泛应用,PCB(印刷电路板)作为其核心部件,其质量和可靠性至关重要。然而,PCB生产过程中常常会出现各种缺陷,如鼠咬伤、开路、短路、杂散、伪铜等。这些缺陷可能导致设备故障,甚至引发严重的安全问题。为了提高PCB检测的效率和准确性,我们基于YOLOv…

【C语言】操作符(上)

目录 1. 操作符的分类 2. 原码、反码、补码 3. 移位操作符 3.1 左移操作符 3.2 右移操作符 4. 位操作符&#xff1a;&、|、^、~ 5. 单目操作符 6. 逗号表达式 最近准备期末考试&#xff0c;好久不见啦&#xff0c;现在回归—— 正文开始—— 1. …

基于CPWM与DPWM综合调制的光伏逆变器

1. 光伏并网逆变器矢量控制 图 1 为光伏发电系统常用的逆变器拓扑结 构,太阳能光伏电池板发电所产生的直流电能接 入光伏并网逆变器直流侧。逆变器将电能逆变, 经过滤波器与隔离升压变压器连接,最终并入电 网。其中隔离变压器低压侧漏感与LC滤波器组 成LCL滤波。为便于分析…

C语言小例程

题目&#xff1a;两个乒乓球队进行比赛&#xff0c;各出三人。甲队为a,b,c三人&#xff0c;乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比&#xff0c;c说他不和x,z比&#xff0c;请编程序找出三队赛手的名单。 #include <stdio.h> #in…

Windows11系统自动获取电脑IPV6地址,并且开机自动发送到指定邮箱

废话&#xff1a;最近放假回家&#xff0c;在家里突然想玩游戏了&#xff0c;Steamdeck性能终归有限。部分游戏始终玩的不爽&#xff0c;想到之前了解到的SunshnieMoonlight串流的方案&#xff0c;远程调用家里的电脑打游戏&#xff0c;简直不要太爽。 一顿折腾之后配置好了所有…

算法05 模拟算法之二维数组相关内容详解【C++实现】

大家好&#xff0c;我是bigbigli&#xff0c;前面一节我们一节讲过一维数组的模拟了&#xff0c;如果还没看的话&#xff0c;可以&#x1f449;点击此处。模拟算法还有很多内容需要讲&#xff0c;比如图像、日期相关的模拟算法&#xff0c;后续将继续更新&#xff0c;今天先来讲…

C语言| 数组的顺序查找

顺序查找 查找数组a中第一次出现数字m的下标&#xff0c;并输出该下标&#xff1b; 如果没有则输出sorry。 1 定义变量 数组a&#xff0c;n表示数组的个数&#xff0c; m要查找的数字 2 用sizeof()函数&#xff0c;求出数组元素的个数 3 从键盘中任意输出一个数字m&#xff0c;…