azer89
azer89

Reputation: 1559

Creating ppt slide thumbnail without exporting to a file

i'm developing a ppt add in form of side panel on powerpoint window what i need is customized slide thumbnails, what i've done so far i use Export() method to convert all of slides to temporary images and display them. but this approach is too slow since i need to save/load from disk and my requirement is to display them in an interactive way (need to be fast enough)

i'm wondering if there's a way to export slide thumbnail in the memory...

Upvotes: 0

Views: 2322

Answers (2)

azer89
azer89

Reputation: 1559

thanks for Steve for the idea using clipboard,

EDIT it works but is still slow, when i generate 70 slides it took 4-5 seconds it seems that Copy() method is quite slow so the overhead is not in the bitmap image of clipboard...

here's what I've done

slide.Copy();
if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Bitmap))
{
    ImageSource imgSource = BinaryStructConverter.ImageFromClipboardDib();
}

For BinaryStructConverter i got a nice code from here: http://www.thomaslevesque.com/2009/02/05/wpf-paste-an-image-from-the-clipboard/ (somehow we need to convert it because if you just copy it directly from clipboard, the bitmap image format is likely to be messed up)

[StructLayout(LayoutKind.Sequential, Pack = 2)]
public struct BITMAPFILEHEADER
{
    public static readonly short BM = 0x4d42; // BM

    public short bfType;
    public int bfSize;
    public short bfReserved1;
    public short bfReserved2;
    public int bfOffBits;
}

[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFOHEADER
{
    public int biSize;
    public int biWidth;
    public int biHeight;
    public short biPlanes;
    public short biBitCount;
    public int biCompression;
    public int biSizeImage;
    public int biXPelsPerMeter;
    public int biYPelsPerMeter;
    public int biClrUsed;
    public int biClrImportant;
}

public static class BinaryStructConverter
{
    public static ImageSource ImageFromClipboardDib()
    {
        MemoryStream ms = Clipboard.GetData("DeviceIndependentBitmap") as MemoryStream;
        if (ms != null)
        {
            byte[] dibBuffer = new byte[ms.Length];
            ms.Read(dibBuffer, 0, dibBuffer.Length);

            BITMAPINFOHEADER infoHeader =
                BinaryStructConverter.FromByteArray<BITMAPINFOHEADER>(dibBuffer);

            int fileHeaderSize = Marshal.SizeOf(typeof(BITMAPFILEHEADER));
            int infoHeaderSize = infoHeader.biSize;
            int fileSize = fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage;

            BITMAPFILEHEADER fileHeader = new BITMAPFILEHEADER();
            fileHeader.bfType = BITMAPFILEHEADER.BM;
            fileHeader.bfSize = fileSize;
            fileHeader.bfReserved1 = 0;
            fileHeader.bfReserved2 = 0;
            fileHeader.bfOffBits = fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4;

            byte[] fileHeaderBytes =
                BinaryStructConverter.ToByteArray<BITMAPFILEHEADER>(fileHeader);

            MemoryStream msBitmap = new MemoryStream();
            msBitmap.Write(fileHeaderBytes, 0, fileHeaderSize);
            msBitmap.Write(dibBuffer, 0, dibBuffer.Length);
            msBitmap.Seek(0, SeekOrigin.Begin);

            return BitmapFrame.Create(msBitmap);
        }
        return null;
    }

    public static T FromByteArray<T>(byte[] bytes) where T : struct
    {
        IntPtr ptr = IntPtr.Zero;
        try
        {
            int size = Marshal.SizeOf(typeof(T));
            ptr = Marshal.AllocHGlobal(size);
            Marshal.Copy(bytes, 0, ptr, size);
            object obj = Marshal.PtrToStructure(ptr, typeof(T));
            return (T)obj;
        }
        finally
        {
            if (ptr != IntPtr.Zero)
                Marshal.FreeHGlobal(ptr);
        }
    }

    public static byte[] ToByteArray<T>(T obj) where T : struct
    {
        IntPtr ptr = IntPtr.Zero;
        try
        {
            int size = Marshal.SizeOf(typeof(T));
            ptr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(obj, ptr, true);
            byte[] bytes = new byte[size];
            Marshal.Copy(ptr, bytes, 0, size);
            return bytes;
        }
        finally
        {
            if (ptr != IntPtr.Zero)
                Marshal.FreeHGlobal(ptr);
        }
    }
}

Upvotes: 0

Steve Rindsberg
Steve Rindsberg

Reputation: 14809

One possible approach:

ActivePresentation.Slides(x).Copy

That will put the slide on the Windows clipboard in a number of formats, including bitmap, PNG, JPG, etc.

If you have a way of loading the image from the clipboard into whatever you're doing, you're good to go.

Upvotes: 1

Related Questions