Author Topic: how to get preview dwg without autocad ?  (Read 48324 times)

0 Members and 1 Guest are viewing this topic.

Irvin

  • Guest
Re: how to get preview dwg without autocad ?
« Reply #15 on: June 20, 2011, 08:03:00 AM »
Hi there,

Iv'e created a new component based on the standard picturebox.
Iv'e added 2 properties 1 is a file string of the dwg that needs to be showed.

here's the code. Don't know how to upload files here:

Code: [Select]
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace AcDgLibrary.Components
{
    public class AcDgDwgThumbnail : PictureBox
    {
        private string _dwgfile = string.Empty;
        private bool _retainbackcolor= true;

        [StructLayout(LayoutKind.Sequential)]
        private 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;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct IMGREC
        {
            public byte bytType;
            public int lngStart;
            public int lngLen;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct RGBQUAD
        {
            public byte rgbBlue;
            public byte rgbGreen;
            public byte rgbRed;
            public byte rgbReserved;
        }

        [Description("Gets or Sets the AutoCAD drawingfile to show it's thumbnail")]
        [Category("AutoCAD")]
        public string DwgFile
        {
            get { return _dwgfile; }
            set
            {
                _dwgfile = value;
                if (DwgFile == string.Empty) return;
                this.Image = GetThumbnail(_dwgfile, _retainbackcolor);
            }
        }

        [Description("Gets or Sets whether the image backcolor is retained.")]
        [Category("AutoCAD")]
        public bool RetainBackColor
        {
            get { return _retainbackcolor; }
            set { _retainbackcolor = value; }
        }

        private Bitmap GetThumbnail(string strFile, bool boolRetainBackColor)
        {
            Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed);
            byte bytCnt;
            byte[] bytBMPBuff;
            int lngImgLoc;
            FileStream fs = null;
            BinaryReader br = null;
            int lngCurLoc;
            int lngY;
            int lngX;
            int lngColor;
            int lngCnt;
            short intCnt;
            IMGREC udtRec;
            RGBQUAD[] udtColors;
            RGBQUAD udtColor;
            BITMAPINFOHEADER udtHeader;
            short intRed;
            short intGreen;
            short intBlue;
            try
            {
                if (File.Exists(strFile))
                {
                    fs = File.OpenRead(strFile);
                    br = new BinaryReader(fs);
                    fs.Seek(13, SeekOrigin.Begin);
                    lngImgLoc = br.ReadInt32();
                    fs.Seek(lngImgLoc + 17, SeekOrigin.Begin);
                    lngCurLoc = lngImgLoc + 17;
                    fs.Seek(lngCurLoc + 3, SeekOrigin.Begin);
                    bytCnt = br.ReadByte();
                    if (bytCnt > 1)
                    {
                        for (intCnt = 0; intCnt < bytCnt; intCnt++)
                        {
                            udtRec.bytType = br.ReadByte();
                            udtRec.lngStart = br.ReadInt32();
                            udtRec.lngLen = br.ReadInt32();
                            if (udtRec.bytType == 2)
                            {
                                fs.Seek(udtRec.lngStart, SeekOrigin.Begin);
                                udtHeader.biSize = br.ReadInt32();
                                udtHeader.biWidth = br.ReadInt32();
                                udtHeader.biHeight = br.ReadInt32();
                                udtHeader.biPlanes = br.ReadInt16();
                                udtHeader.biBitCount = br.ReadInt16();
                                udtHeader.biCompression = br.ReadInt32();
                                udtHeader.biSizeImage = br.ReadInt32();
                                udtHeader.biXPelsPerMeter = br.ReadInt32();
                                udtHeader.biYPelsPerMeter = br.ReadInt32();
                                udtHeader.biClrUsed = br.ReadInt32();
                                udtHeader.biClrImportant = br.ReadInt32();
                                bytBMPBuff = new byte[udtRec.lngLen + 1];
                                if (udtHeader.biBitCount == 8)
                                {
                                    udtColors = new RGBQUAD[256];
                                    for (int count = 0; count < 256; count++)
                                    {
                                        udtColors[count].rgbBlue = br.ReadByte();
                                        udtColors[count].rgbGreen = br.ReadByte();
                                        udtColors[count].rgbRed = br.ReadByte();
                                        udtColors[count].rgbReserved = br.ReadByte();
                                    }
                                fs.Seek(udtRec.lngStart - 1, SeekOrigin.Begin);
                                for (int count = 0; count <= udtRec.lngLen; count++)
                                {
                                    bytBMPBuff[count] = br.ReadByte();
                                }
                                bmp = new Bitmap(udtHeader.biWidth, udtHeader.biHeight);
                                lngCnt = 0;
                                for (lngY = 1; lngY <= udtHeader.biHeight; lngY++)
                                {
                                    for (lngX = udtHeader.biWidth; lngX >= 1; lngX--)
                                    {
                                        lngColor = bytBMPBuff[bytBMPBuff.GetUpperBound(0) - lngCnt];
                                        udtColor = udtColors[lngColor];
                                        intRed = Convert.ToInt16(udtColor.rgbRed);
                                        intGreen = Convert.ToInt16(udtColor.rgbGreen);
                                        intBlue = Convert.ToInt16(udtColor.rgbBlue);
                                        lngColor = ColorTranslator.ToOle(Color.FromArgb(intRed, intGreen, intBlue));
                                        if (boolRetainBackColor == false)
                                        {
                                            if (lngColor == ColorTranslator.ToOle(Color.Black))
                                            {
                                                lngColor = ColorTranslator.ToOle(Color.White);
                                            }
                                            else
                                            {
                                                if (lngColor == ColorTranslator.ToOle(Color.White))
                                                {
                                                    lngColor = ColorTranslator.ToOle(Color.Black);
                                                }
                                            }
                                        }
                                        bmp.SetPixel(lngX - 1, lngY - 1, ColorTranslator.FromOle(lngColor));
                                        lngCnt++;
                                    }
                                }
                            }
                            goto Exit_Here;
                            }
                            else
                            {
                                if (udtRec.bytType == 3)
                                {
                                    goto Exit_Here;
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
                goto Exit_Here;
            }
            Exit_Here:
            if (br != null)
            {
                br.Close();
                fs.Close();
                fs.Dispose();
       
            }
            return bmp;
        }
    }
}

Hop this will help you.

Kind regards,

irvin

jgr

  • Guest
Re: how to get preview dwg without autocad ?
« Reply #16 on: August 06, 2011, 12:26:03 AM »
jgr's version:
Also works with 32-bit images (Yes, .dwg files can also contain 32-bit images!).

Code: [Select]
using System;
using System.Drawing;
using System.IO;

namespace DwgUtilities {
    internal static class ThumbnailReader {
        internal static Bitmap GetBitmap(string fileName) {
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
                using (BinaryReader br = new BinaryReader(fs)) {                   
                    fs.Seek(0xD, SeekOrigin.Begin);
                    fs.Seek(0x14 + br.ReadInt32(), SeekOrigin.Begin);
                    byte bytCnt = br.ReadByte();
                    if (bytCnt <= 1)
                        return null;
                    int imageHeaderStart;
                    int imageHeaderSize;
                    byte imageCode;
                    for (short i = 1; i <= bytCnt; i++) {
                        imageCode = br.ReadByte();
                        imageHeaderStart = br.ReadInt32();
                        imageHeaderSize = br.ReadInt32();
                        if (imageCode == 2) {
                            fs.Seek(imageHeaderStart, SeekOrigin.Begin);
                            //-----------------------------------------------------
                            // BITMAPINFOHEADER (40 bytes)
                            br.ReadBytes(0xE); //biSize, biWidth, biHeight, biPlanes
                            ushort biBitCount = br.ReadUInt16();
                            br.ReadBytes(4); //biCompression
                            uint biSizeImage = br.ReadUInt32();
                            //br.ReadBytes(0x10); //biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant
                            //-----------------------------------------------------
                            fs.Seek(imageHeaderStart, SeekOrigin.Begin);
                            byte[] bitmapBuffer = br.ReadBytes(imageHeaderSize);
                            uint colorTableSize =(uint)((biBitCount < 9) ? 4 * Math.Pow(2, biBitCount) : 0);
                            using (MemoryStream ms = new MemoryStream()) {
                                using (BinaryWriter bw = new BinaryWriter(ms)) {                                 
                                    //bw.Write(new byte[] { 0x42, 0x4D });
                                    bw.Write((ushort)0x4D42);
                                    bw.Write(54U + colorTableSize + biSizeImage);
                                    bw.Write(new ushort());
                                    bw.Write(new ushort());
                                    bw.Write(54U + colorTableSize);
                                    bw.Write(bitmapBuffer);
                                    return new Bitmap(ms);
                                }
                            }
                        } else if (imageCode == 3) {
                            return null;
                        }
                    }
                }
            }
            return null;
        }
    }
}

huiz

  • Swamp Rat
  • Posts: 913
  • Certified Prof C3D
Re: how to get preview dwg without autocad ?
« Reply #17 on: June 11, 2012, 03:11:06 PM »
Code by jgr=&jgr and Keith does work perfectly with drawing files up to 2010 format but not with 2013 file format. There were a few changes I've read. Is there anybody who has found out how to read the file thumbs of 2013 files?
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: how to get preview dwg without autocad ?
« Reply #18 on: June 11, 2012, 05:24:02 PM »
I've not looked at the 2013 file version so I couldn't tell you.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

twdotson

  • Mosquito
  • Posts: 17
Re: how to get preview dwg without autocad ?
« Reply #19 on: June 11, 2012, 06:20:50 PM »
The 2013 format uses a PNG file instead of BMP, you will see an object type code of 6.

huiz

  • Swamp Rat
  • Posts: 913
  • Certified Prof C3D
Re: how to get preview dwg without autocad ?
« Reply #20 on: June 12, 2012, 03:04:09 AM »
The 2013 format uses a PNG file instead of BMP, you will see an object type code of 6.

Ah indeed, BMP is 2. Thanks!
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

huiz

  • Swamp Rat
  • Posts: 913
  • Certified Prof C3D
Re: how to get preview dwg without autocad ?
« Reply #21 on: June 12, 2012, 04:00:11 AM »
Wow, that was easy. For who is interested, here the code to read thumbs, file format very old up to 2013:


Code: [Select]
Imports System.Drawing
Imports System.IO

' 2011 Copyright (C) jgr=&jgr, via http://www.theswamp.org
' 2012 (me): Added code to read PNG Thumbnails from DWG (2013 file format)
Friend NotInheritable Class ThumbnailReader
  Private Sub New()
  End Sub
  Friend Shared Function GetBitmap(fileName As String) As Bitmap
    Using fs As New FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
      Using br As New BinaryReader(fs)
        fs.Seek(&HD, SeekOrigin.Begin)
        fs.Seek(&H14 + br.ReadInt32(), SeekOrigin.Begin)
        Dim bytCnt As Byte = br.ReadByte()
        If bytCnt <= 1 Then
          Return Nothing
        End If
        Dim imageHeaderStart As Integer
        Dim imageHeaderSize As Integer
        Dim imageCode As Byte
        For i As Short = 1 To bytCnt
          imageCode = br.ReadByte()
          imageHeaderStart = br.ReadInt32()
          imageHeaderSize = br.ReadInt32()
          If imageCode = 2 Then ' BMP Preview (2012 file format)
            ' BITMAPINFOHEADER (40 bytes)
            br.ReadBytes(&HE)
            'biSize, biWidth, biHeight, biPlanes
            Dim biBitCount As UShort = br.ReadUInt16()
            br.ReadBytes(4)
            'biCompression
            Dim biSizeImage As UInteger = br.ReadUInt32()
            'br.ReadBytes(0x10); //biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant
            '-----------------------------------------------------
            fs.Seek(imageHeaderStart, SeekOrigin.Begin)
            Dim bitmapBuffer As Byte() = br.ReadBytes(imageHeaderSize)
            Dim colorTableSize As UInteger = CUInt(Math.Truncate(If((biBitCount < 9), 4 * Math.Pow(2, biBitCount), 0)))
            Using ms As New MemoryStream()
              Using bw As New BinaryWriter(ms)
                bw.Write(CUShort(&H4D42))
                bw.Write(54UI + colorTableSize + biSizeImage)
                bw.Write(New UShort())
                bw.Write(New UShort())
                bw.Write(54UI + colorTableSize)
                bw.Write(bitmapBuffer)
                Return New Bitmap(ms)
              End Using
            End Using
          ElseIf imageCode = 6 Then ' PNG Preview (2013 file format)
            fs.Seek(imageHeaderStart, SeekOrigin.Begin)
            Using ms As New MemoryStream
              fs.CopyTo(ms, imageHeaderStart)
              Dim img = Image.FromStream(ms)
              Return img
            End Using
          ElseIf imageCode = 3 Then
            Return Nothing
          End If
        Next
      End Using
    End Using
    Return Nothing
  End Function
End Class
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

TJK44

  • Guest
Re: how to get preview dwg without autocad ?
« Reply #22 on: August 07, 2012, 09:13:16 AM »
Hi,

Wondering if anyone has been able to make the preview sharper. I don't have an overwhelmingly big picturebox displaying the preview, but the preview it generates isn't very clear. Anyway to make it look better?

Thanks

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: how to get preview dwg without autocad ?
« Reply #23 on: August 07, 2012, 09:19:49 AM »
The drawing preview is generated by AutoCAD and is stored in the drawing file. As far as I know, the preview image resolution is not able to be changed.

However, my understanding is that there might be a way to dynamically generate your own preview from the objects withing the drawing. Maybe someone can shed some light on that idea.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

BillZndl

  • Guest
Re: how to get preview dwg without autocad ?
« Reply #24 on: August 09, 2012, 01:04:41 PM »
vs2010EX acad2012.

I have been converting this code to C# but evidently there are methods in vb.net that are not in C#.
The FileStream (fs) does not contain "CopyTo" in my intellisense. Any way to work around that?
Code: [Select]
if (imageCode == 6)       //PNG Preview (2013 file format);
           {
              fs.Seek(imageHeaderStart, SeekOrigin.Begin);         

              using (MemoryStream ms = new MemoryStream())
                {
                 
                 fs.CopyTo(ms, imageHeaderStart);
                 Image img = Image.FromStream(ms);
                 return new Bitmap(img);
                }   //end using
           } //end if

This is not an emergency I am just doing this for my own education.
I can't test it right now anyways but they are threatening me with an upgrade to 2013 Acad.
The entire file is attached.

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: how to get preview dwg without autocad ?
« Reply #25 on: August 09, 2012, 02:14:11 PM »
vs2010EX acad2012.

I have been converting this code to C# but evidently there are methods in vb.net that are not in C#.
The FileStream (fs) does not contain "CopyTo" in my intellisense. Any way to work around that?

The CopyTo() is there in C#.  Look for other errors preventing the Intellisense from working. (Sometimes unclosed braces will do this to me.)

TJK44

  • Guest
Re: how to get preview dwg without autocad ?
« Reply #26 on: August 09, 2012, 03:12:42 PM »
The Stream.CopyTo Method only became available with .NET Framework 4.0. Is your project targeting the 4.0 framework?

BillZndl

  • Guest
Re: how to get preview dwg without autocad ?
« Reply #27 on: August 13, 2012, 07:01:48 AM »
@JeffM

Entirely possible.
I cut & paste the VB.net in to a new project and am debugging on a "most obvious comes first" scenario.
I'll isolate the irrellevant code as I should have done in the first place.

@TJK44

Yes, using .net framework 4 Client Profile.

Thanks!

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: how to get preview dwg without autocad ?
« Reply #28 on: March 17, 2013, 06:09:07 PM »
The options in AutoCAD 2013 shows the ability to save larger preview icons, but both the out of process and in process methods only get an image with a max width or height of 256 pixels. Anybody know how to get a larger image out?

Rusel

  • Guest
Re: how to get preview dwg without autocad ?
« Reply #29 on: June 08, 2014, 05:38:30 AM »
Wow, that was easy. For who is interested, here the code to read thumbs, file format very old up to 2013:


Code: [Select]
Imports System.Drawing
Imports System.IO

' 2011 Copyright (C) jgr=&jgr, via http://www.theswamp.org
' 2012 (me): Added code to read PNG Thumbnails from DWG (2013 file format)
Friend NotInheritable Class ThumbnailReader
  Private Sub New()
  End Sub
  Friend Shared Function GetBitmap(fileName As String) As Bitmap
    Using fs As New FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
      Using br As New BinaryReader(fs)
        fs.Seek(&HD, SeekOrigin.Begin)
        fs.Seek(&H14 + br.ReadInt32(), SeekOrigin.Begin)
        Dim bytCnt As Byte = br.ReadByte()
        If bytCnt <= 1 Then
          Return Nothing
        End If
        Dim imageHeaderStart As Integer
        Dim imageHeaderSize As Integer
        Dim imageCode As Byte
        For i As Short = 1 To bytCnt
          imageCode = br.ReadByte()
          imageHeaderStart = br.ReadInt32()
          imageHeaderSize = br.ReadInt32()
          If imageCode = 2 Then ' BMP Preview (2012 file format)
            ' BITMAPINFOHEADER (40 bytes)
            br.ReadBytes(&HE)
            'biSize, biWidth, biHeight, biPlanes
            Dim biBitCount As UShort = br.ReadUInt16()
            br.ReadBytes(4)
            'biCompression
            Dim biSizeImage As UInteger = br.ReadUInt32()
            'br.ReadBytes(0x10); //biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant
            '-----------------------------------------------------
            fs.Seek(imageHeaderStart, SeekOrigin.Begin)
            Dim bitmapBuffer As Byte() = br.ReadBytes(imageHeaderSize)
            Dim colorTableSize As UInteger = CUInt(Math.Truncate(If((biBitCount < 9), 4 * Math.Pow(2, biBitCount), 0)))
            Using ms As New MemoryStream()
              Using bw As New BinaryWriter(ms)
                bw.Write(CUShort(&H4D42))
                bw.Write(54UI + colorTableSize + biSizeImage)
                bw.Write(New UShort())
                bw.Write(New UShort())
                bw.Write(54UI + colorTableSize)
                bw.Write(bitmapBuffer)
                Return New Bitmap(ms)
              End Using
            End Using
          ElseIf imageCode = 6 Then ' PNG Preview (2013 file format)
            fs.Seek(imageHeaderStart, SeekOrigin.Begin)
            Using ms As New MemoryStream
              fs.CopyTo(ms, imageHeaderStart)
              Dim img = Image.FromStream(ms)
              Return img
            End Using
          ElseIf imageCode = 3 Then
            Return Nothing
          End If
        Next
      End Using
    End Using
    Return Nothing
  End Function
End Class


Thank you for the code, but how do I make the background black? It is always gray in the picturbox.
Thanks,