# wpf应用开发
# 1.用wpf 加载显示图像,并通过鼠标悬浮时获取图像的像素坐标以及灰度,同时包含图像缩放功能,还有上下文菜单功能
以下是使用WPF加载和显示图像,并通过鼠标悬浮获取图像的像素坐标和灰度值的一些示例代码:
- 1.XAML 布局:
<Window x:Class="ImageProcessing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 菜单 -->
<Menu>
<MenuItem Header="_File">
<MenuItem Header="_Open" Click="Open_Click"/>
<Separator/>
<MenuItem Header="_Exit" Click="Exit_Click"/>
</MenuItem>
<MenuItem Header="_Options">
<MenuItem Header="_Zoom In" Click="ZoomIn_Click"/>
<MenuItem Header="_Zoom Out" Click="ZoomOut_Click"/>
</MenuItem>
</Menu>
<!-- 显示图像的控件 -->
<Image Name="image" Grid.Row="1"
Stretch="None" MouseMove="Image_MouseMove"/>
</Grid>
</Window>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- 2.C# 代码:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using Microsoft.Win32;
using System.IO;
namespace ImageProcessing
{
public partial class MainWindow : Window
{
private BitmapSource bitmapSource; // 加载的位图
private double zoomFactor = 1.0; // 缩放系数
public MainWindow()
{
InitializeComponent();
}
// 打开文件并显示图像
private void Open_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == true)
{
byte[] bytes = File.ReadAllBytes(openFileDialog.FileName);
MemoryStream ms = new MemoryStream(bytes);
bitmapSource = BitmapFrame.Create(ms);
image.Source = bitmapSource;
}
}
// 退出应用程序
private void Exit_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
// 图像缩小
private void ZoomOut_Click(object sender, RoutedEventArgs e)
{
zoomFactor /= 2;
ScaleTransform scaleTransform = new ScaleTransform(zoomFactor, zoomFactor);
image.LayoutTransform = scaleTransform;
}
// 图像放大
private void ZoomIn_Click(object sender, RoutedEventArgs e)
{
zoomFactor *= 2;
ScaleTransform scaleTransform = new ScaleTransform(zoomFactor, zoomFactor);
image.LayoutTransform = scaleTransform;
}
// 获取鼠标悬浮的像素坐标和灰度值
private void Image_MouseMove(object sender, MouseEventArgs e)
{
Point point = e.GetPosition(image);
int x = (int)(point.X / zoomFactor);
int y = (int)(point.Y / zoomFactor);
if (bitmapSource != null &&
x >= 0 && x < bitmapSource.PixelWidth &&
y >= 0 && y < bitmapSource.PixelHeight)
{
CroppedBitmap croppedBitmap =
new CroppedBitmap(bitmapSource, new Int32Rect(x, y, 1, 1));
byte[] pixels = new byte[4];
croppedBitmap.CopyPixels(pixels, 4, 0);
int grayScale = (pixels[0] + pixels[1] + pixels[2]) / 3;
// 处理获取到的像素坐标和灰度值
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
- 此外,你可以使用WPF提供的ContextMenu类来实现上下文菜单功能。将ContextMenu对象添加到Image控件的ContextMenu属性即可。
# 2.用wpf开发加载一个图像,并在图像中心位置画出红色的十字架,状态栏显示图像类型,大小,像素坐标,灰度,位深的功能
- 1.下面是使用WPF开发加载图像并在中心位置画出红色十字架,并在状态栏上显示有关图像的信息的示例代码:
xml复制代码<Window x:Class="ImageInfo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Image Information" Height="350" Width="525">
<Grid>
<Image x:Name="imgMain" Stretch="Uniform" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Canvas x:Name="canvasCrosshair" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<StatusBar x:Name="statBar" VerticalAlignment="Bottom" Height="20">
<StatusBarItem>
<TextBlock x:Name="tbxImageInfo" TextAlignment="Right"/>
</StatusBarItem>
</StatusBar>
</Grid>
</Window>
2
3
4
5
6
7
8
9
10
11
12
13
14
-2.我们需要添加一个Image
控件和一个Canvas
控件。 Image
用于显示图像,Canvas
用于绘制十字架。
接下来是代码的C#部分:
csharp复制代码using System;
using System.Drawing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace ImageInfo
{
public partial class MainWindow : Window
{
private BitmapImage _imageSource;
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// TODO: Set image path
string imagePath = "";
try
{
_imageSource = new BitmapImage(new Uri(imagePath));
imgMain.Source = _imageSource;
// Draw crosshair
Line lineX = new Line
{
X1 = 0,
Y1 = canvasCrosshair.ActualHeight / 2,
X2 = canvasCrosshair.ActualWidth,
Y2 = canvasCrosshair.ActualHeight / 2,
Stroke = Brushes.Red,
StrokeThickness = 2
};
Line lineY = new Line
{
X1 = canvasCrosshair.ActualWidth / 2,
Y1 = canvasCrosshair.ActualHeight / 2,
X2 = canvasCrosshair.ActualWidth,
Y2 = canvasCrosshair.ActualHeight / 2,
Stroke = Brushes.Red,
StrokeThickness = 2
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 3.用wpf开发加载一个图像,并在图像中心位置画出红色的十字架,状态栏显示图像类型,大小,像素坐标,灰度,位深
- 1.以下是使用WPF开发加载图像并在中心位置绘制红色十字架的代码示例,也包括状态栏显示图像元数据信息的实现:
xml复制代码<Window x:Class="ImageInfo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Image Information" Width="600" Height="600" Loaded="Window_Loaded">
<Grid>
<StatusBar DockPanel.Dock="Bottom">
<TextBlock x:Name="statusText"/>
</StatusBar>
<Canvas x:Name="canvas" Background="White"/>
</Grid>
</Window>
2
3
4
5
6
7
8
9
10
11
- 2.在MainWindow.xaml.cs文件中可以添加以下代码,用于加载图像、计算图像元数据并在界面中绘制。
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using PixelFormat = System.Drawing.Imaging.PixelFormat;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
string imagePath = "image.png";
if (File.Exists(imagePath))
{
Image img = new Image();
Bitmap bmp = new Bitmap(imagePath);
// 计算图像元数据
BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
double pixelSize = GetPixelSize(bmp);
string info = $"{bmp.Width} x {bmp.Height}, {pixelSize.ToString("F2")} μm/pixel, {data.PixelFormat.ToString()}";
bmp.UnlockBits(data);
// 绘制图像和十字架
img.Source = ConvertBitmapToImageSource(bmp);
canvas.Children.Add(img);
double centerX = canvas.ActualWidth / 2.0;
double centerY = canvas.ActualHeight / 2.0;
Line lineX = new Line();
lineX.Stroke = Brushes.Red;
lineX.X1 = centerX - 10;
lineX.Y1 =
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 4.整理一份can通信,modbus通信,tcp通信,http通信,mqtt,S7通信的功能实现
以下是 CAN 通信、Modbus 通信、TCP 通信、HTTP 通信、MQTT 和 S7 通信的功能实现说明:
CAN 通信:CAN(Controller Area Network)总线通信协议是一种广泛使用于汽车和工业控制领域的通 信协议。CAN 通信需要通过 CAN 控制器芯片将数据发送到总线上,而接收方则需要使用相同的协议进行解析并处理数据。 在 CAN 通信中,需要编写与 CAN 控制器芯片通信的驱动程序,并设置相关参数(如位速率、过滤器等)。在 数据发送时,需要将数据格式化为 CAN 数据帧并通过控制器进行传输;在接收数据时,需要对接收到的数据进行 解析并提取需要的信息。
Modbus 通信:Modbus 是一种基于串行连接的协议,主要用于工业环境下的通信和控制。Modbus 协议包含多种传输方式,如 RTU(Remote Terminal Unit)、ASCII 等,其中 RTU 是最常用的方式。 在 Modbus 通信中,需要先建立连接(包括寻找从机、设定寻址方式、指定数据读写区域等),然后进行数 据读写操作。对于 RTU 方式,还需要进行 CRC 校验以确保数据传输的正确性。
TCP 通信:TCP(Transmission Control Protocol)是基于连接的协议,用于实现可靠的数据传 输。TCP 通信需要先建立连接,然后进行数据传输,最后再关闭连接。
在 TCP 通信中,需要编写服务器端和客户端程序,以实现双向的数据传输。服务器端需要等待客户端的 连接请求,并响应相应的请求来建立起连接;而客户端则需要指定需要连接的服务器地址和端口号,以 启动连接建立过程。在连接之后,就可以进行数据的读取和写入,当数据传输结束时,需要通过关闭连接来释放占用的资源。
- HTTP 通信:HTTP(HyperText Transfer Protocol)是一种基于网络的协议,主要用于网页数据的传输。HTTP 请求和响应都是基于文本格式,采用 MIME 类型来确定数据类型。
在 HTTP 通信中,需要构造请求报文(包括请求方式、请求头部、请求主体等),并发送到服务器端;服务器 接收到请求报文后,解析报文并生成响应报文(包括响应状态码、响应头部、响应主体等)发送回客户端。 常见的 HTTP 请求方式包括 GET、POST、PUT、DELETE 等。
- MQTT 通信:MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息通信协议,适用于低能耗 设备和不稳定网络环境。MQTT 协议采用发布/订阅模式,通过消息代理(Broker)来实现消息的转发和路由。
在 MQTT 通信中,需要编写客户端程序连接到指定的 Broker,并进行订阅或发布消息。当一个客户端发布一条 消息时,Broker 会将该消息转发给所有订阅了该主题的其他客户端,以实现消息广播的效果。
- S7 通信:S7(Simatic S7)是西门子公司开发的一种工业控制器,S7 通信协议主要用于与该控制器的通信。S7 通信采用基于 ISO-on-TCP 的协议,其中 ISO 协议是 OSI 参考模型中的数据链路层和物理层协议。
在 S7 通信中,需要编写本地通信模块和远程通信模块,并使用不同的协议号和数据区域来进行数据传输。具体地说,需 要建立一个 TCP 连接,并发送特定格式的消息来请求数据读写操作;服务端收到请求后,返回相关的响应消息,以完成 数据传输的过程。
# 5.用C++ 实现动态库类的成员,参数指针,参数结构体的导出,分别用JAVA jna调用接口,和C#调用接口
- 以下是用 C++ 实现动态库类的成员,参数指针,参数结构体的导出,并分别用 Java JNA 和 C# 调用接口的大致流程:
- 在 C++ 中实现动态库类的导出。可以使用 __declspec(dllexport) 关键字将类及其方法导出到动态库中,供其他程序调用。
cppCopy Codestruct Point {
int x;
int y;
};
class __declspec(dllexport) MyClass {
public:
void DoSomething();
int Add(int a, int b);
void Swap(int* pa, int* pb);
void SetPoint(Point* p);
};
2
3
4
5
6
7
8
9
10
11
12
- 将 C++ 动态库文件编译成 .dll 文件。可以使用 Visual Studio 或其他开发环境来生成 .dll 文件。
- 使用 JNA 连接 C++ 动态库。可以使用 JNA 提供的 NativeLibrary 和 Function 类,通过动态链接库 文件路径和方法名来调用 C++ 动态库中的方法。
javaCopy CodeNativeLibrary lib = NativeLibrary.getInstance("MyDll.dll");
Function doSomethingFunc = lib.getFunction("DoSomething");
doSomethingFunc.invoke(new Object[0]);
Function addFunc = lib.getFunction("Add");
int result = (int)addFunc.invoke(Integer.class, new Object[] { 1, 2 });
Function swapFunc = lib.getFunction("Swap");
Pointer pa = new IntByReference(1).getPointer();
Pointer pb = new IntByReference(2).getPointer();
swapFunc.invoke(new Object[] { pa, pb });
Function setPointFunc = lib.getFunction("SetPoint");
Point point = new Point();
point.x = 100;
point.y = 200;
Structure struct = new Structure.ByValue(point);
setPointFunc.invoke(new Object[] { struct.getPointer() });
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 在 C# 中使用 P/Invoke 进行调用。可以使用 DllImport 特性和 Marshal 类,通 过动态链接库文件路径和方法名来调用 C++ 动态库中的方法。
csharpCopy Codeclass Program {
[DllImport("MyDll.dll")]
public static extern void DoSomething();
[DllImport("MyDll.dll")]
public static extern int Add(int a, int b);
[DllImport("MyDll.dll")]
public static extern void Swap(ref int pa, ref int pb);
[StructLayout(LayoutKind.Sequential)]
public struct Point {
public int x;
public int y;
}
[DllImport("MyDll.dll")]
public static extern void SetPoint(ref Point p);
}
static void Main(string[] args) {
Program.DoSomething();
int result = Program.Add(1, 2);
int a = 1, b = 2;
Program.Swap(ref a, ref b);
Program.Point point = new Program.Point();
point.x = 100;
point.y = 200;
Program.SetPoint(ref point);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
以上是大致的实现思路和流程,具体实现时需要根据自己的需求进行调整和优化。希望这些信息对你有所帮助!
# 6.用C++定义一个动态库类包含图像buffer指针,图像宽高,长度,图像格式,保存图像接口参
数为图像指针对象,字符串文件名,用JAVA jna调用接口存图接口
cppCopy Code// MyImage.h
#pragma once
#include <string>
#include <cstdint>
#ifdef MYIMAGE_EXPORTS
#define MYIMAGE_API __declspec(dllexport)
#else
#define MYIMAGE_API __declspec(dllimport)
#endif
class MYIMAGE_API MyImage {
public:
MyImage(int width, int height, int length, const std::string& format);
~MyImage();
uint8_t* GetBuffer() const;
int GetWidth() const;
int GetHeight() const;
int GetLength() const;
std::string GetFormat() const;
void SaveImage(const std::string& filename);
private:
uint8_t* buffer_;
int width_;
int height_;
int length_;
std::string format_;
};
cppCopy Code// MyImage.cpp
#include "MyImage.h"
#include <fstream>
MyImage::MyImage(int width, int height, int length, const std::string& format)
: width_(width), height_(height), length_(length), format_(format)
{
buffer_ = new uint8_t[length];
}
MyImage::~MyImage()
{
delete[] buffer_;
}
uint8_t* MyImage::GetBuffer() const
{
return buffer_;
}
int MyImage::GetWidth() const
{
return width_;
}
int MyImage::GetHeight() const
{
return height_;
}
int MyImage::GetLength() const
{
return length_;
}
std::string MyImage::GetFormat() const
{
return format_;
}
void MyImage::SaveImage(const std::string& filename)
{
std::ofstream file(filename, std::ios::out | std::ios::binary);
file.write(reinterpret_cast<char*>(buffer_), length_);
file.close();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
使用 JNA 调用:
javaCopy Codeimport com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
public interface MyImageLibrary extends Library {
MyImageLibrary INSTANCE = Native.load("MyImage.dll", MyImageLibrary.class);
public static class MyImage extends Structure {
public Pointer buffer;
public int width;
public int height;
public int length;
public String format;
public MyImage(Pointer p) {
super(p);
read();
}
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "buffer", "width", "height", "length", "format" });
}
}
MyImage createMyImage(int width, int height, int length, String format);
void deleteMyImage(Pointer p);
void saveImage(Pointer pMyImage, String filename);
}
javaCopy CodeMyImageLibrary.MyImage myImage = MyImageLibrary.INSTANCE.createMyImage(640, 480, 640*480*3, "RGB24");
Pointer buffer = myImage.buffer;
// Copy image data to buffer
// ...
// Save image
MyImageLibrary.INSTANCE.saveImage(myImage.getPointer(), "test.rgb");
MyImageLibrary.INSTANCE.deleteMyImage(myImage.getPointer());
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
在 Java 中需要引入 JNA 的相关库,具体可参考 JNA 的官方文档。