Files
ShrlAlgoToolkit/ShrlAlgoStudio/RevitLess/PreviewImage.cs
2026-02-17 22:17:13 +08:00

294 lines
9.1 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Packaging;
using System.Windows.Media.Imaging;
namespace ShrlAlgoStudio.RevitLess
{
public class PreviewImage : RevitLess.StorageStreamBase
{
#region Private Variables
private byte[] previewData = null;
#endregion
#region Constructors
public PreviewImage(string fileName, StorageInfo storage)
: base(fileName, storage)
{
ReadStructuredStorageFile();
}
#endregion
#region Private Properties
private byte[] PreviewData
{
get
{
return previewData;
}
set
{
previewData = value;
}
}
#endregion
#region Public Methods
public Image GetPreviewAsImage()
{
if ((PreviewData == null) || (PreviewData.Length <= 0))
{
using (Bitmap newBitmap = new Bitmap(128, 128))
{
return newBitmap.Clone() as Bitmap;
}
}
// read past the Revit metadata to the start of the PNG image
int startingOffset = GetPngStartingOffset();
if (startingOffset == 0)
{
using (Bitmap newBitmap = new Bitmap(128, 128))
{
return newBitmap.Clone() as Bitmap;
}
}
try
{
byte[] pngDataBuffer = new byte[PreviewData.GetUpperBound(0) - startingOffset + 1];
// read the PNG image data into a byte array
using (MemoryStream ms = new MemoryStream(PreviewData))
{
ms.Position = startingOffset;
ms.Read(pngDataBuffer, 0, pngDataBuffer.Length);
}
byte[] decoderData = null;
// if the image data is valid
if (pngDataBuffer != null)
{
// use a memory stream to decode the PNG image data
// and copy the decoded data into a byte array
using (MemoryStream ms = new MemoryStream(pngDataBuffer))
{
PngBitmapDecoder decoder = new PngBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
decoderData = BitSourceToArray(decoder.Frames[0]);
}
}
// if the decoded data is valie
if ((decoderData != null) && (decoderData.Length > 0))
{
// use another memory stream to create a Bitmap
// and then an Image from that Bitmap
using (MemoryStream ms = new MemoryStream(decoderData))
{
using (Bitmap src = new Bitmap(ms))
{
// 创建一个与 src 无关的深拷贝,并返回该拷贝(不要对其进行 Dispose
Bitmap deepCopy = new Bitmap(src);
return (Image)deepCopy;
}
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
using (Bitmap newBitmap = new Bitmap(128, 128))
{
return newBitmap.Clone() as Bitmap;
}
}
#endregion
#region Private Methods
private byte[] BitSourceToArray(BitmapSource bitmapSource)
{
BitmapEncoder encoder = new JpegBitmapEncoder();
using (MemoryStream ms = new MemoryStream())
{
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
encoder.Save(ms);
return ms.ToArray();
}
}
//internal override void ReadStructuredStorageFile()
//{
// if(IsInitialized)
// {
// return;
// }
// try
// {
// StreamInfo[] streams = Storage.GetStreams();
// foreach(StreamInfo stream in streams)
// {
// if(stream.Name.ToUpper().Equals("REVITPREVIEW4.0"))
// {
// PreviewData = ParsePreviewInfo(stream);
// }
// }
// }
// catch(Exception ex)
// {
// LogManager.LogMessage(ex);
// IsInitialized = false;
// }
// IsInitialized = true;
//}
public void ReadStructuredStorageFile()
{
if (IsInitialized)
{
return;
}
try
{
StreamInfo[] streams = Storage.GetStreams();
foreach (StreamInfo stream in streams)
{
if (stream.Name.ToUpper().Equals("REVITPREVIEW4.0"))
{
PreviewData = ParsePreviewInfo(stream);
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
IsInitialized = false;
}
IsInitialized = true;
}
private byte[] ParsePreviewInfo(StreamInfo streamInfo)
{
byte[] streamData = null;
try
{
using (Stream streamReader = streamInfo.GetStream(FileMode.Open, FileAccess.Read))
{
streamData = new byte[streamReader.Length];
streamReader.Read(streamData, 0, streamData.Length);
return streamData;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
streamData = null;
}
}
private int GetPngStartingOffset()
{
bool markerFound = false;
int startingOffset = 0;
int previousValue = 0;
using (MemoryStream ms = new MemoryStream(PreviewData))
{
for (int i = 0; i < PreviewData.Length; i++)
{
int currentValue = ms.ReadByte();
// possible start of PNG file data
if (currentValue == 137) // 0x89
{
markerFound = true;
startingOffset = i;
previousValue = currentValue;
continue;
}
switch (currentValue)
{
case 80: // 0x50
if (markerFound && (previousValue == 137))
{
previousValue = currentValue;
continue;
}
markerFound = false;
break;
case 78: // 0x4E
if (markerFound && (previousValue == 80))
{
previousValue = currentValue;
continue;
}
markerFound = false;
break;
case 71: // 0x47
if (markerFound && (previousValue == 78))
{
previousValue = currentValue;
continue;
}
markerFound = false;
break;
case 13: // 0x0D
if (markerFound && (previousValue == 71))
{
previousValue = currentValue;
continue;
}
markerFound = false;
break;
case 10: // 0x0A
if (markerFound && (previousValue == 26))
{
return startingOffset;
}
if (markerFound && (previousValue == 13))
{
previousValue = currentValue;
continue;
}
markerFound = false;
break;
case 26: // 0x1A
if (markerFound && (previousValue == 10))
{
previousValue = currentValue;
continue;
}
markerFound = false;
break;
}
}
}
return 0;
}
#endregion
}
}