两种方式获取revit族文件预览缩略图
问题描述
想做一个族库管理插件,其中有一个功能是预览其缩略图.
解决方案1
revit api中有一个ElementType.GetPreviewImage方法,ElementType的常用子类就是familySymbol
需要注意的是GetPreviewImage返回的是一个Bitmap,在winform中是直接可以用于pictureBox的image控件的,
但是wpf中的image控件的source一般接受的是一个BitmapImage.
bitmap和bitmapimage的区别以及如何相互转换在此不说,搜一搜即可,但要注意一点:
bitmap转换为bitmapImage或者bitmap.save()时,一定要保证创建bitmap的stream没有关闭,也就是说要避免使用using语句!
解决方案2
不使用任何revit api,使用System.IO.Packaging.StorageInfo的GetStreams方法,以下是链接:
https://thebuildingcoder.typepad.com/blog/2010/06/open-revit-ole-storage.html
他提供了一个示例文件的下载:
https://thebuildingcoder.typepad.com/files/openrevitolestorage.zip
简单概括下原理:反射System.IO.Packaging.StorageRoot的Open方法获取rfa文件的package信息,其中有一个叫做RevitPreview4.0的就存储着预览缩略图信息.将其读取为byte[],然后跳过revit的metadata,得到缩略图的原始二进制数据,
接下来就是byte[]转BitmapImage或者Bitmap的问题了,同样的要注意在某些地方避免使用using语句
抛砖引玉的代码
提供如何解析rfa文件和获得其跳过metadata后的起始位置的两个方法的代码:
/// <summary>/// rfa等格式实际上是一个package,需通过StorageInfo来访问,但是要获得StorageInfo必须/// 通过反射调用StorageRoot的一个Open方法来获得之/// </summary>/// <param name="filename"></param>/// <returns></returns>private byte[] ParseRevitPreview4_0(string filename){var srType = typeof(StorageInfo).Assembly.GetType("System.IO.Packaging.StorageRoot");if (srType?.InvokeMember("Open",BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, new object[]{filename,FileMode.Open,FileAccess.Read,FileShare.Read}) is StorageInfo stInfo){foreach (StreamInfo streamInfo in stInfo.GetStreams()){if (streamInfo.Name.Equals("RevitPreview4.0", StringComparison.Ordinal)){using (var reader = streamInfo.GetStream(FileMode.Open, FileAccess.Read)){var imageData = new byte[reader.Length];reader.Read(imageData, 0, imageData.Length);return imageData;}}}}return default;}/// <summary>/// RevitPreview4.0的二进制流中需要跳过revit的一些metadata,来获得图片的起始位置/// </summary>/// <param name="rawData"></param>/// <returns></returns>private int GetPngStartingOffset(byte[] rawData){bool markerFound = false;int startingOffset = 0;int previousValue = 0;using (MemoryStream ms = new MemoryStream(rawData)){for (int i = 0; i < rawData.Length; i++){int currentValue = ms.ReadByte();// possible start of PNG file dataif (currentValue == 137) // 0x89{markerFound = true;startingOffset = i;previousValue = currentValue;continue;}switch (currentValue){case 80: // 0x50if (markerFound && (previousValue == 137)){previousValue = currentValue;continue;}markerFound = false;break;case 78: // 0x4Eif (markerFound && (previousValue == 80)){previousValue = currentValue;continue;}markerFound = false;break;case 71: // 0x47if (markerFound && (previousValue == 78)){previousValue = currentValue;continue;}markerFound = false;break;case 13: // 0x0Dif (markerFound && (previousValue == 71)){previousValue = currentValue;continue;}markerFound = false;break;case 10: // 0x0Aif (markerFound && (previousValue == 26)){return startingOffset;}if (markerFound && (previousValue == 13)){previousValue = currentValue;continue;}markerFound = false;break;case 26: // 0x1Aif (markerFound && (previousValue == 10)){previousValue = currentValue;continue;}markerFound = false;break;}}}return 0;}
两种方式获取revit族文件预览缩略图相关推荐
- jvm两种方式获取对象所占用的内存
在开发过程中,我们有时需要来获取某个对象的大小,以方便我们参考,来决定开发的技术方案.jvm中提供了两种方式来获取一个对象的大小. 通过Instrumentation来计算对象的大小 编写计算代码: ...
- shell和javaAPI两种方式创建hbase表并预分区
在hbase里面,如果我们建表不预分区,那么一个表的数据都会被一个region处理,如果数据过多就会执行region的split,如果数据量很大这样会很费性能,所以最好我们先根据业务的数据量在建表的时 ...
- 使用两种方式,Android 发送文件到指定邮箱(带多个附件)
第一种方法,调用系统的邮件软件来发送 众所周知在Android中调用其他程序进行相关处理,都是使用的Intent.当然,Email也不例外. 在Android中,调用Email有三种类型的Intent ...
- Webpack/Vue-cli两种方式加载markdown文件并实现代码高亮
准备的资源: highlight.js : 实现代码高亮,通过npm install highlight.js -D安装 vue-markdown-loader:解析md文件的必备loader,通过n ...
- android手机两种方式获取IP地址
http://www.cnblogs.com/android100/p/Android-get-ip.html 1.使用WIFI 首先设置用户权限 Xml代码 <uses-permissio ...
- java 实现BufferedImage和ImageReader两种方式获取图片宽高、判断图片类型、获取图片大小工具类代码以及测试响应结果
源码: import org.springframework.web.multipart.MultipartFile;import javax.imageio.ImageIO; import java ...
- springMVC两种方式实现多文件上传及效率比较
springMVC实现多文件上传的方式有两种,一种是我们经常使用的以字节流的方式进行文件上传,另外一种是使用springMVC包装好的解析器进行上传.这两种方式对于实现多文件上传效率上却有着很大的差距 ...
- 获取checkbox选中状态的两种方式_张童瑶的博客
获取checkbox选中状态的两种方式 获取checkbox选中状态的两种方式 第一种方式 第二种方式 我的其他文章 我的其他网站 获取checkbox选中状态的两种方式 我在开发项目的时候遇到这个问 ...
- 【Android】Android 彩信发送的两种方式+源代码
Android 彩信发送的两种方式 第一种:直接调用彩信发送接口 实现代码如下, Intent intent = new Intent(Intent.ACTION_SEND); intent.add ...
- Delphi 读取文本文件的两种方式
用两种方式读取文本文件:文件流读取和文件变量读取 一.文件流方式 {*******************************************************} {功能:读取文本文 ...
最新文章
- 为什么说能源管理是分布式光伏发电的突破口?
- 对接口运用扩展方法 Applying Extension Methods to an Interface 精通ASP-NET-MVC-5-弗瑞曼 Listing 4-15...
- 邮件实用技巧一:如何让你的邮件畅通全球
- 厉害了,ES 如何做到几十亿数据检索 3 秒返回!
- mysql中varchar与integer的互转
- JAVA程序设计----多线程(上)
- display:block的注意
- 如何在 C# 中使用 RabbitMQ
- DirectX 矩阵
- kafka partition分配_logstash消费kafka数据,partition分配不均衡
- 百战程序员JavaWeb系列教程-监听器视频教程
- 中国(龙港)首届 “港为人先”全球创新创业大赛
- 计算机excel按F4是那个公式,excel中键盘F4到底怎么用?_excle 中的f4
- yum.repos.d没有这个文件和目录解决方法
- 爱帮网CEO刘建国:垂直化是搜索发展的趋势
- Joan Baez - Jackaroe
- Windows下迁移nexus
- Anaconda安装教程(超详细)
- excel表显示与服务器通信失败,安装通用Excel服务器端,在连接数据库的时候提示:“用户 'sa' 登录失败。原因: 未与信任 SQL Server 连接相关联”...
- PHPCMS教程,手把手教你建网站