我在HDD上有几个(~2GB)原始24bpp RGB文件.现在我想要检索它的一部分并将其缩放到所需的大小.
(唯一允许的比例是1,1/2,1/4,1/8,......,1/256)
所以我现在正在从感兴趣的矩形中读取每一行到一个数组,这给我留下了一个高度正确但宽度错误的位图.
下一步我是从新创建的数组创建一个Bitmap.
这是通过使用指针完成的,因此不会复制涉及的数据.
接下来,我在Bitmap上调用GetThumbnailImage,它创建一个具有正确尺寸的新位图.
现在我想返回新创建的位图的原始像素数据(作为字节数组).但要实现这一点,我目前正在使用LockBits将数据复制到一个新数组中.
所以我的问题是:有没有办法将像素数据从Bitmap转换为字节数组而不复制它?
就像是:
var bitmapData = scaledBitmap.LockBits(...)
byte[] rawBitmapData = (byte[])bitmapData.Scan0.ToPointer()
scaledBitmap.UnlockBits(bitmapData)
return rawBitmapData
Run Code Online (Sandbox Code Playgroud)
我很清楚这不起作用,它只是我基本上想要实现的一个例子.
我正在编写一个使用最新MediaInfoLib Dll的C#.NET 3.5程序.
它似乎导致某些文件的异常.
我想捕获这些异常并确保我的程序继续运行,
但由于某种原因我无法通过简单的try/catch语句捕获它.
PInvoke方法:
[DllImport("MediaInfo.dll")]
private static extern IntPtr MediaInfo_New();
[DllImport("MediaInfo.dll")]
private static extern IntPtr MediaInfo_Open(IntPtr Handle,MarshalAs(UnmanagedType.LPWStr)] string FileName);
Run Code Online (Sandbox Code Playgroud)
用法:
Handle = MediaInfo_New();
try{
MediaInfo_Open(Handle, FileName)
} catch { }
Run Code Online (Sandbox Code Playgroud)
调用MediaInfo_Open(Handle,FileName)可能会导致异常.
我的程序退出并且"vshost32-clr2.exe"崩溃,而不是使用try/catch语句捕获错误.(它也作为发布版本崩溃并且没有附带调试器)
在搜索网络后,我发现有人建议检查"启用非托管代码调试",这只导致我的程序退出而没有vshost32-clr2.exe崩溃.
知道如何捕捉异常吗?
我有大约270k个数据块对,每对包含一个32KiB和一个16KiB块.
当我将它们保存到一个文件时,我当然得到一个非常大的文件.但数据很容易压缩.
使用WinRAR压缩5.48GiB文件后,压缩率很高,生成的文件大小为37.4MiB.
但我需要随机访问每个单独的块,所以我只能单独压缩块.
为此我使用了.NET提供的Deflate类,它将文件大小减小到382MiB(我可以使用).
但速度不够好.
很多速度损失可能是因为总是为每个块创建一个新的MemoryStream和Deflate实例.但似乎它们不是为了重复使用而设计的.
我猜(很多?)当使用"全局"字典而不是每个块有一个时,可以实现更好的压缩.
是否有适合该任务的压缩算法(最好是在C#中)的实现?
以下链接包含每个字节数出现的百分比,分为三种块类型(仅限32KiB块).第一种和第三种类型的出现率为37.5%,第二种类型为25%. 块类型百分比
长文件短篇小说:Type1主要包含一个.Type2主要由零组成,Type3主要由零组成.大于128的值不会出现(尚未).
16KiB块几乎总是由零组成
我正在实现一个 UserControl ,它应该显示设置列表:
public class SettingPropertyItem {
string Name { get; }
Type ValueType { get; }
object Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
基于每种类型,ValueType应使用不同的 DataTemplate。
为了促进这一点,UserControl 有以下 Control,并以 aSettingPropertyItem作为其 DataContext:
<UserControl x:Class="AVDump3Gui.Controls.Settings.SettingsView">
...
<ItemsControl Items="{Binding Properties}" Margin="16,0,0,0">
<ItemsControl.ItemTemplate>
<DataTemplate>
...
<ContentControl Content="{Binding}"/>
...
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
...
</UserControl>
Run Code Online (Sandbox Code Playgroud)
然后在使用 Usercontrol 的视图中,我在其 DataTemplates 中添加了一个 DataTemplate:
<sv:SettingsView.DataTemplates>
<DataTemplate DataType="{x:Type vm:SettingPropertyItem}">
...
</DataTemplate>
</sv:SettingsView.DataTemplates>
Run Code Online (Sandbox Code Playgroud)
到目前为止一切顺利,一切都按预期进行。但现在我有点困惑,因为我不知道如何基于 DataContext 中的属性应用不同的 DataTemplate。
对于 WPF,DataTemplateSelector 或触发器似乎是可行的方法(忽略其他框架),但它们在 Avalonia 中似乎不存在。我也尝试过样式,但选择器似乎无法访问 DataContext 属性。
如何才能做到这一点?
我一直在调试我的程序,因为它抛出Out Of Memory异常.
剥离后,看起来任务正在保持参考,尽管它已经完成.
这是我的精简代码:
public class Program {
static void Main(string[] args) {
var cts = new CancellationTokenSource();
ConsumeFiles(cts.Token);
}
public static void ConsumeFiles(CancellationToken ct) {
while(true) {
var dataSource = new Queue<byte[]>();
for(int i = 0;i < 16;i++) {
var block = new byte[4 * 1024 * 1024];
for(int j = 0;j < block.Length;j++) block[j] = (byte)j;
dataSource.Enqueue(block);
}
var cts = new CancellationTokenSource();
ct.Register(() => cts.Cancel()); //Remove this line => No OOM
Task.Factory.StartNew(() => { //Remove Task …Run Code Online (Sandbox Code Playgroud) c# ×5
.net-3.5 ×1
avaloniaui ×1
bitmap ×1
block ×1
compression ×1
datatemplate ×1
exception ×1
pinvoke ×1
pixel ×1
reference ×1
resize ×1
task ×1
try-catch ×1