C#将1GB大图裁剪为8张图片
C#处理超大图片(1GB)需要特别注意内存管理和性能优化。以下是几种高效裁剪方案:
方法1:使用System.Drawing分块处理(内存优化版)
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;class Program
{static void Main(){string sourceImagePath = "1GB_Image.bmp";string outputFolder = "CroppedImages";if (!Directory.Exists(outputFolder)){Directory.CreateDirectory(outputFolder);}// 获取图片尺寸但不加载全部内容using (var image = Image.FromFile(sourceImagePath)){int totalWidth = image.Width;int totalHeight = image.Height;// 计算每块尺寸 (2x4网格)int chunkWidth = totalWidth / 2;int chunkHeight = totalHeight / 4;// 分块裁剪for (int row = 0; row < 4; row++){for (int col = 0; col < 2; col++){int x = col * chunkWidth;int y = row * chunkHeight;// 确保最后一块包含剩余部分int width = (col == 1) ? totalWidth - x : chunkWidth;int height = (row == 3) ? totalHeight - y : chunkHeight;CropImage(sourceImagePath,Path.Combine(outputFolder, $"part_{row}_{col}.jpg"),x, y, width, height);}}}}static void CropImage(string sourcePath, string destPath, int x, int y, int width, int height){// 使用流式处理避免全图加载using (var source = new Bitmap(sourcePath))using (var dest = new Bitmap(width, height))using (var graphics = Graphics.FromImage(dest)){graphics.DrawImage(source,new Rectangle(0, 0, width, height),new Rectangle(x, y, width, height),GraphicsUnit.Pixel);// 保存为JPEG减少体积dest.Save(destPath, ImageFormat.Jpeg);Console.WriteLine($"已保存: {destPath} ({width}x{height})");}}
}
方法2:使用ImageSharp(现代跨平台方案)
首先安装NuGet包:
Install-Package SixLabors.ImageSharp
实现代码:
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Jpeg;class Program
{static async Task Main(){string sourcePath = "1GB_Image.jpg";string outputDir = "CroppedImages";Directory.CreateDirectory(outputDir);// 配置内存选项处理大图var configuration = Configuration.Default.Clone();configuration.MemoryAllocator = new SixLabors.ImageSharp.Memory.ArrayPoolMemoryAllocator();// 分块加载和处理using (var image = await Image.LoadAsync(configuration, sourcePath)){int totalWidth = image.Width;int totalHeight = image.Height;int chunkWidth = totalWidth / 2;int chunkHeight = totalHeight / 4;for (int row = 0; row < 4; row++){for (int col = 0; col < 2; col++){int x = col * chunkWidth;int y = row * chunkHeight;int width = (col == 1) ? totalWidth - x : chunkWidth;int height = (row == 3) ? totalHeight - y : chunkHeight;// 克隆并裁剪区域using (var cropped = image.Clone(ctx => ctx.Crop(new Rectangle(x, y, width, height)))){string outputPath = Path.Combine(outputDir, $"part_{row}_{col}.jpg");await cropped.SaveAsync(outputPath, new JpegEncoder {Quality = 80 // 适当压缩});Console.WriteLine($"已保存: {outputPath}");}}}}}
}
方法3:使用内存映射文件处理超大图
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Drawing;
using System.Drawing.Imaging;class Program
{static void Main(){string sourcePath = "1GB_Image.bmp";string outputDir = "CroppedImages";Directory.CreateDirectory(outputDir);// 获取BMP文件头信息var bmpInfo = GetBmpInfo(sourcePath);int width = bmpInfo.Width;int height = bmpInfo.Height;int bytesPerPixel = bmpInfo.BitsPerPixel / 8;int stride = width * bytesPerPixel;// 计算分块int chunkWidth = width / 2;int chunkHeight = height / 4;// 使用内存映射文件处理using (var mmf = MemoryMappedFile.CreateFromFile(sourcePath, FileMode.Open)){for (int row = 0; row < 4; row++){for (int col = 0; col < 2; col++){int x = col * chunkWidth;int y = row * chunkHeight;int cropWidth = (col == 1) ? width - x : chunkWidth;int cropHeight = (row == 3) ? height - y : chunkHeight;// 创建目标位图using (var dest = new Bitmap(cropWidth, cropHeight, PixelFormat.Format24bppRgb)){var destData = dest.LockBits(new Rectangle(0, 0, cropWidth, cropHeight),ImageLockMode.WriteOnly,dest.PixelFormat);try{// 计算源文件偏移量(BMP文件头54字节 + 数据偏移)long offset = 54 + (height - y - 1) * stride + x * bytesPerPixel;// 逐行复制for (int line = 0; line < cropHeight; line++){using (var accessor = mmf.CreateViewAccessor(offset - line * stride, cropWidth * bytesPerPixel)){byte[] lineData = new byte[cropWidth * bytesPerPixel];accessor.ReadArray(0, lineData, 0, lineData.Length);IntPtr destPtr = destData.Scan0 + (line * destData.Stride);System.Runtime.InteropServices.Marshal.Copy(lineData, 0, destPtr, lineData.Length);}}}finally{dest.UnlockBits(destData);}string outputPath = Path.Combine(outputDir, $"part_{row}_{col}.jpg");dest.Save(outputPath, ImageFormat.Jpeg);Console.WriteLine($"已保存: {outputPath}");}}}}}static (int Width, int Height, int BitsPerPixel) GetBmpInfo(string filePath){using (var fs = new FileStream(filePath, FileMode.Open))using (var reader = new BinaryReader(fs)){// 读取BMP头if (reader.ReadChar() != 'B' || reader.ReadChar() != 'M')throw new Exception("不是有效的BMP文件");fs.Seek(18, SeekOrigin.Begin); // 跳转到宽度信息int width = reader.ReadInt32();int height = reader.ReadInt32();fs.Seek(28, SeekOrigin.Begin); // 跳转到位深信息int bitsPerPixel = reader.ReadInt16();return (width, height, bitsPerPixel);}}
}
方法4:使用Magick.NET(专业图像处理)
首先安装NuGet包:
Install-Package Magick.NET-Q16-x64
实现代码:
using ImageMagick;
using System;
using System.IO;class Program
{static void Main(){string sourcePath = "1GB_Image.tif";string outputDir = "CroppedImages";Directory.CreateDirectory(outputDir);// 设置资源限制MagickNET.SetResourceLimit(ResourceType.Memory, 1024 * 1024 * 1024); // 1GB// 使用像素流处理大图using (var image = new MagickImage(sourcePath)){int width = image.Width;int height = image.Height;int chunkWidth = width / 2;int chunkHeight = height / 4;for (int row = 0; row < 4; row++){for (int col = 0; col < 2; col++){int x = col * chunkWidth;int y = row * chunkHeight;int cropWidth = (col == 1) ? width - x : chunkWidth;int cropHeight = (row == 3) ? height - y : chunkHeight;using (var cropped = image.Clone(new MagickGeometry{X = x,Y = y,Width = cropWidth,Height = cropHeight})){string outputPath = Path.Combine(outputDir, $"part_{row}_{col}.jpg");cropped.Quality = 85;cropped.Write(outputPath);Console.WriteLine($"已保存: {outputPath}");}}}}}
}
裁剪方案选择建议
方法 | 优点 | 缺点 | 使用场景 |
System.Drawing | 内置库,简单 | 内存占用高 | Windows小图处理 |
ImageSharp | 跨平台,现代API | 学习曲线 | 需要跨平台支持 |
内存映射 | 内存效率高 | 复杂,仅限BMP | 超大图处理 |
Magick.NET | 功能强大 | 需要安装 | 专业图像处理 |
注意事项
- 内存管理:处理1GB图片需要至少2-3GB可用内存
- 文件格式:BMP/TIFF适合处理,JPEG可能有压缩问题
- 磁盘空间:确保有足够空间存放输出文件
- 异常处理:添加try-catch处理IO和内存不足情况
- 性能优化:
- 使用64位应用程序
- 增加GC内存限制:<gcAllowVeryLargeObjects enabled="true"/>
- 分批处理减少内存压力
相关文章:
C#将1GB大图裁剪为8张图片
C#处理超大图片(1GB)需要特别注意内存管理和性能优化。以下是几种高效裁剪方案: 方法1:使用System.Drawing分块处理(内存优化版) using System; using System.Drawing; using System.Drawing.Imaging; us…...
数据库——SQL约束窗口函数介绍
4.SQL约束介绍 (1)主键约束 A、基本内容 基本内容 p r i m a r y primary primary k e y key key约束唯一表示数据库中的每条记录主键必须包含唯一的值(UNIQUE)主键不能包含NULL值(NOT NULL)每个表都应…...
Linux系统启动相关:vmlinux、vmlinuz、zImage,和initrd 、 initramfs,以及SystemV 和 SystemD
目录 一、vmlinux、vmlinuz、zImage、bzImage、uImage 二、initrd 和 initramfs 1、initrd(Initial RAM Disk) 2、initramfs(Initial RAM Filesystem) 3、initrd vs. initramfs 对比 4. 如何查看和生成 initramfs 三、Syste…...

JSP链接MySQL8.0(Eclipse+Tomcat9.0+MySQL8.0)
所用环境 Eclipse Tomcat9.0 MySQL8.0.21(下载:MySQL Community Server 8.0.21 官方镜像源下载 | Renwole) mysql-connector-java-8.0.21(下载:MySQL :: Begin Your Download) .NET Framework 4.5.2(下…...
Python爬虫-爬取百度指数之人群兴趣分布数据,进行数据分析
前言 本文是该专栏的第56篇,后面会持续分享python爬虫干货知识,记得关注。 在本专栏之前的文章《Python爬虫-爬取百度指数之需求图谱近一年数据》中,笔者有详细介绍过爬取需求图谱的数据教程。 而本文,笔者将再以百度指数为例子,基于Python爬虫获取指定关键词的人群“兴…...

SEO长尾词与关键词优化实战
内容概要 在SEO优化体系中,长尾关键词与核心关键词的协同作用直接影响流量获取效率与用户转化路径。长尾词通常由3-5个词组构成,搜索量较低但意图明确,能精准触达细分需求用户;核心关键词则具备高搜索量与广泛覆盖能力࿰…...

机器学习-人与机器生数据的区分模型测试-数据处理1
附件为训练数据,总体的流程可以作为参考。 导入依赖 import pandas as pd import os import numpy as np from sklearn.model_selection import train_test_split,GridSearchCV from sklearn.ensemble import RandomForestClassifier,VotingClassifier from skle…...

HelloWorld
HelloWorld 新建一个java文件 文件后缀名为 .javahello.java【注意】系统可能没有显示文件后缀名,我们需要手动打开 编写代码 public class hello {public static void main(String[] args) {System.out.print(Hello,World)} }编译 javac java文件,会生…...
令牌桶和漏桶算法使用场景解析
文章目录 什么时候用令牌桶,什么时候用漏桶算法??先放结论 两个算法一眼看懂什么时候选令牌桶?什么时候选漏桶?组合用法(90% 的真实系统都会这么干)小结记忆 对令牌桶和漏桶组合用法再次详细叙述…...
轻量、优雅、高扩展的事件驱动框架——Hibiscus-Signal
在现代企业级应用中,事件驱动架构(EDA)已成为解耦系统、提升扩展性的利器。今天给大家推荐一个非常优秀的国产轻量级事件驱动框架 —— Hibiscus Signal,它不仅天然整合 Spring Boot,还提供完整的事件生命周期支持&…...

SEO 优化实战:ZKmall模板商城的 B2C商城的 URL 重构与结构化数据
在搜索引擎算法日益复杂的今天,B2C商城想要在海量信息中脱颖而出,仅靠优质商品和营销活动远远不够。ZKmall模板商城以实战为导向,通过URL 重构与结构化数据优化两大核心策略,帮助 B2C 商城实现从底层架构到搜索展示的全面升级&…...
2020CCPC河南省赛题解
A. 班委竞选 签到题,模拟。 #include <bits/stdc.h> #define x first #define y second #define int long long //#define double long doubleusing namespace std; typedef unsigned long long ULL ; typedef pair<int,int> PII ; typedef pair<d…...

数字万用表与指针万用表使用方法及注意事项
在电子测量领域,万用表是极为常用的工具,数字万用表和指针万用表各具特点。熟练掌握它们的使用方法与注意事项,能确保测量的准确性与安全性。下面为您详细介绍: 一 、数字万用表按钮功能 > 进入及退出手动量程模式 每 按 […...
虚拟主播肖像权保护,数字时代的法律博弈
首席数据官高鹏律师团队 在虚拟主播行业蓬勃发展的表象之下,潜藏着一场关乎法律边界的隐形战争。当一位虚拟偶像的3D模型被非法拆解、面部数据被批量复制,运营方惊讶地发现——传统的肖像权保护体系,竟难以完全覆盖这具由代码与数据构成的“…...

【读代码】端到端多模态语言模型Ultravox深度解析
一、项目基本介绍 Ultravox是由Fixie AI团队开发的开源多模态大语言模型,专注于实现音频-文本的端到端实时交互。项目基于Llama 3、Mistral等开源模型,通过创新的跨模态投影架构,绕过了传统语音识别(ASR)的中间步骤,可直接将音频特征映射到语言模型的高维空间。 核心优…...

RabbitMQ工作流程及使用方法
一、什么是RabbitMQ RabbitMQ 是一款基于 AMQP(高级,消息队列协议) 的开源消息中间件,专为分布式系统设计,用于实现应用程序间的异步通信,其核心功能是通过 消息代理(Message Broker&…...
Java 面向对象进阶:解锁多态、内部类与包管理
Java 面向对象进阶:解锁多态、内部类与包管理 🔑 在 Java 的面向对象编程中,多态赋予了对象“多种形态”的能力,内部类提供了更精细的代码组织方式,而包则帮助我们管理和组织大量的类。今天,我们将深入探讨…...

算法:分治法
实验内容 在一个2kⅹ2k个方格组成的棋盘中,若恰有一个方格与其他方格不同,则称该方格为特殊方格,且称该棋盘为一特殊棋盘。 显然,特殊方格出现的位置有4k 种情况,即k>0,有4k 种不同的特殊棋盘 棋盘覆盖:…...

MySQL初阶:sql事务和索引
索引(index) 可以类似理解为一本书的目录,一个表可以有多个索引。 索引的意义和代价 在MySQL中使用select进行查询时会经过: 1.先遍历表 2.将条件带入每行记录中进行判断,看是否符合 3.不符合就跳过 但当表中的…...

docker部署第一个Go项目
1.前期准备 目录结构 main.go package mainimport ("fmt""github.com/gin-gonic/gin""net/http" )func main() {fmt.Println("\n .::::.\n .::::::::.\n :::::::::::\n …...
day27 python 装饰器
目录 一、装饰器的基本概念 示例:用装饰器优化质数查找函数 二、装饰器的高级用法 1. 支持任意参数的装饰器 2. 装饰器的返回值处理 在 Python 编程中,装饰器是一个非常强大的功能,它可以让其他函数或方法在不需要做任何代码修改的前提下…...

Visual Studio2022跨平台Avalonia开发搭建
由于我已经下载并安装了 VS2022版本,这里就跳过不做阐述。 1.安装 Visual Studio 2022 安装时工作负荷Tab页勾选 “.NET 桌面开发” 和“Visual Studio扩展开发” ,这里由于不是用的微软的MAUI,所以不用选择其他的来支持跨平台开发&a…...

css iconfont图标样式修改,js 点击后更改样式
背景: 在vue项目中,通过点击/鼠标覆盖,更改选中元素的样式,可以通过js逻辑,也可以根据css样式修改。包括以下内容:iconfont图标的引入以及使用,iconfont图标样式修改【导入文件是纯白࿰…...

开源项目实战学习之YOLO11:12.4 ultralytics-models-sam-memory_attention.py源码分析
👉 点击关注不迷路 👉 点击关注不迷路 👉 另外,前些天发现了一个巨牛的AI人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。感兴趣的可以点击相关跳转链接。 点击跳转到网站。 ultralytics-models-sam 1.sam-modules-memory_attention.pyblocks.py: 定义模…...

【沉浸式求职学习day42】【算法题:滑动窗口】
沉浸式求职学习 长度最小的子数组水果成篮 关于算法题:滑动窗口的几个题目 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组…...

LIIGO ❤️ RUST 12 YEARS
LIIGO 💖 RUST 12 YEARS 今天是RUST语言1.0发布十周年纪念日。十年前的今天,2015年的今天,Rust 1.0 正式发行。这是值得全球Rust支持者隆重纪念的日子。我借此机会衷心感谢Rust语言创始人Graydon Hoare,Mozilla公司,以…...

Linux基础开发工具二(gcc/g++,自动化构建makefile)
3. 编译器gcc/g 3.1 背景知识 1. 预处理(进行宏替换/去注释/条件编译/头文件展开等) 2. 编译(生成汇编) 3. 汇编(生成机器可识别代码) 4. 连接(生成可执行文件或库文件) 3.2 gcc编译选项 格式 : gcc …...
Linux zip、unzip 压缩和解压
zip 命令用于压缩文件,压缩后的文件后缀名为 .zip 。 对应的解压命令是 unzip 。 测试用的目录结构如下, userzn:~/test$ tree . ├── folder1 │ ├── folder111 │ │ └── file1.txt │ └── main1.c ├── folder2 │ ├── …...
muduo库TcpConnection模块详解——C++
muduo库中的TcpConnection模块详解 TcpConnection是muduo库中处理TCP连接的核心模块,负责管理单个TCP连接的生命周期、数据读写、状态转换以及事件回调。每个TCP连接对应一个TcpConnection对象,其设计体现了高性能、线程安全和灵活回调的特点。 一、核心…...
Node.js 源码架构详解
Node.js 的源码是一个庞大且复杂的项目,它主要由 C 和 JavaScript 构成。要完全理解每一部分需要大量的时间和精力。我会给你一个高层次的概述,并指出一些关键的目录和组件,帮助你开始探索。 Node.js 的核心架构 Node.js 的核心可以概括为以…...