Author Topic: How to create a RasterImage in AutoCAD  (Read 5309 times)

0 Members and 1 Guest are viewing this topic.

huiz

  • Swamp Rat
  • Posts: 913
  • Certified Prof C3D
How to create a RasterImage in AutoCAD
« on: June 27, 2010, 02:39:31 PM »
I tried to get a PNG file into AutoCAD with VB.NET but sofar I did not succeed. There is really little documentation about this so I hope someone of you can help me further.

A raster object is firstly added to an imagedictionary as a RasterImageDef. Then you need to create a RasterImage object and refer to the ObjectID of the RasterImageDef. I have my code till sofar, I do get an ObjectID so the RasterImageDef is added to the dictionary.

But I can't get the RasterImage into AutoCAD. There is no reference in the References Palette, no errors, etc. Does someone have code to put an image object into AutoCAD from which I can learn how to do it? :-)
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 create a RasterImage in AutoCAD
« Reply #1 on: June 28, 2010, 03:57:40 AM »
I have this code so far:

Code: [Select]
  Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
    ' we have coördinates in pntLinksOnder
    ' we have a directory from where we want the PNG's in strFilePath
    Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
    Dim acCurDb As Database = acDoc.Database
    Dim acBT As BlockTable
    Dim acBTR As BlockTableRecord
    Dim acImageDefPNG As DatabaseServices.RasterImageDef
    Dim acImagePNG As DatabaseServices.RasterImage

    ' Start a transaction
    Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
      acBT = acDoc.Database.BlockTableId.GetObject(DatabaseServices.OpenMode.ForRead)
      acBTR = acBT(BlockTableRecord.ModelSpace).GetObject(DatabaseServices.OpenMode.ForWrite)

      Try

        Dim myDI As New IO.DirectoryInfo(strFilePath)
        Dim myArrayFI As IO.FileInfo() = myDI.GetFiles("*.png")

        For Each myFI In myArrayFI
          If Microsoft.VisualBasic.Left(myFI.Name.ToUpper, 2) = "LG" Then
            acImageDefPNG = New DatabaseServices.RasterImageDef
            acImageDefPNG = AddImageDef(acDoc.Database, acTrans, myFI.FullName.ToString)

            If (Not (acImageDefPNG) Is Nothing) Then
              acImagePNG = New DatabaseServices.RasterImage
              acImagePNG.ImageDefId = acImageDefPNG.ObjectId

              acTrans.AddNewlyCreatedDBObject(acImagePNG, True)

              acImagePNG.AssociateRasterDef(acImageDefPNG)

              Dim acImageOrigin As Geometry.Point3d = pntLinksOnder

              acImagePNG.Orientation = New Geometry.CoordinateSystem3d(acImageOrigin, Geometry.Vector3d.XAxis, Geometry.Vector3d.YAxis)
              ' acImagePNG.Position = pntLinksOnder

              acImagePNG.ImageTransparency = True

              acTrans.Commit()
            End If

          End If
        Next

      Catch ex As Exception

      End Try

      ' Close transaction
      acTrans.Dispose()
      Me.Close()
    End Using

  End Sub

  ' function to load image into dictionary
  Public Shared Function AddImageDef(ByVal db As Database, ByVal trans As Transaction, ByVal imageFilespec As String) As RasterImageDef
    If Not File.Exists(imageFilespec) Then
      Throw New FileNotFoundException(imageFilespec)
    End If
    Dim idImageDict As ObjectId = RasterImageDef.GetImageDictionary(db)
    If idImageDict.IsNull Then
      idImageDict = RasterImageDef.CreateImageDictionary(db)
    End If
    If idImageDict.IsNull Then
      Throw New InvalidOperationException("failed to get or create image dictionary")
    End If
    Dim imageDictionary As DBDictionary = CType(trans.GetObject(idImageDict, DatabaseServices.OpenMode.ForRead), DBDictionary)
    If (imageDictionary Is Nothing) Then
      Throw New InvalidOperationException("Failed to open image dictionary")
    End If
    Dim imageDef As RasterImageDef = New RasterImageDef
    Try
      imageDef.SourceFileName = imageFilespec
      imageDef.Load()
      Dim name As String = RasterImageDef.SuggestName(imageDictionary, imageFilespec)
      imageDictionary.UpgradeOpen()
      Dim idEntry As ObjectId = imageDictionary.SetAt(name, imageDef)
      If idEntry.IsNull Then
        Throw New InvalidOperationException("Failed to add image definition to image dictionary")
      End If
      trans.AddNewlyCreatedDBObject(imageDef, True)
      Return imageDef
    Catch
      imageDef.Dispose()
      Throw
    End Try
  End Function

There are no errors so I assume I forget something. Unfortunately a RasterImage is not that simple as adding a line and I can't find useful information about this.
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.

Glenn R

  • Guest
Re: How to create a RasterImage in AutoCAD
« Reply #2 on: June 28, 2010, 09:27:52 AM »
That looks like code that Tony posted, which I just tested and it works as expected. The difference between Tony's and yours, in the brief glance I gave it, is the insert/position point.

Actually, your problem is that you're not using AppendEntity to add the newly created RasterImage to the ModelSpace block table record...

huiz

  • Swamp Rat
  • Posts: 913
  • Certified Prof C3D
Re: How to create a RasterImage in AutoCAD
« Reply #3 on: June 28, 2010, 04:26:14 PM »
It is indeed the code from Tony, translated to VB. There is hardly any other code example of RasterImages.

I was not able to debug with VB2010 Express so I tried in VB2008 Express (now I can debug) and now I seem to get errors at the second image. I receive an error here:

Dim imageDictionary As DBDictionary = CType(trans.GetObject(idImageDict, DatabaseServices.OpenMode.ForRead), DBDictionary)

Which says that the object reference is not set to an instance of an object.

The first image is not a problem, that will show up (even while I do not use AppendEntity), but the second probably tries to set a new image dictionary or so? And then the code will stop.
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.

Glenn R

  • Guest
Re: How to create a RasterImage in AutoCAD
« Reply #4 on: June 28, 2010, 04:39:28 PM »
Second image...??? As far as I can tell, you're only attaching one...

huiz

  • Swamp Rat
  • Posts: 913
  • Certified Prof C3D
Re: How to create a RasterImage in AutoCAD
« Reply #5 on: June 28, 2010, 04:48:24 PM »
Dim myDI As New IO.DirectoryInfo(strFilePath)
        Dim myArrayFI As IO.FileInfo() = myDI.GetFiles("*.png")

        For Each myFI In myArrayFI



^^ I read all PNG's from a map and I try to load them in the loop. The first one gets loaded, the second one gives the error.

But as far as I understand the function of Tony, it should not give problems but it does so.
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.

Glenn R

  • Guest
Re: How to create a RasterImage in AutoCAD
« Reply #6 on: June 28, 2010, 05:29:13 PM »
1. You didn't mention or show the actual code you are using. The code you originally showed does not do a batch insertion, which is now clearly what you are trying to do.

2. You need to use AppendEntity.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8662
  • AKA Daniel
Re: How to create a RasterImage in AutoCAD
« Reply #7 on: June 28, 2010, 07:01:56 PM »
It is indeed the code from Tony, translated to VB.

blasphemy

GTVic

  • Guest
Re: How to create a RasterImage in AutoCAD
« Reply #8 on: June 28, 2010, 07:26:08 PM »

I think I used Tony's code as a starting point a while back. And after fiddling for a while, I came up with this function which you can call once for each image you want to insert.

Code: [Select]
Public Function Add_Raster(ByRef ThisDoc As Document, ByVal RasterFile As String, ByVal InsPoint As Point3d, ByVal Scale As Double, ByRef NumInserted As Integer) As RasterImage

    Dim RasterEnt As RasterImage, RasterDef As RasterImageDef
    Dim ImageDicID, ImageDefID As ObjectId, ImageDic As DBDictionary
    Dim Matrix As Geometry.Matrix3d
    Dim btr As BlockTableRecord
    Dim RasterName As String = ""

    RasterName = RasterFile.Substring(RasterFile.LastIndexOf("\") + 1)
    RasterName = RasterName.Substring(0, RasterName.IndexOf("."))

    Add_Raster = Nothing
    If ThisDoc Is Nothing Then Exit Function

    Try

        Using Trans As Transaction = ThisDoc.TransactionManager.StartTransaction()

            RasterEnt = New RasterImage
            RasterEnt.Dispose() ' force loading of RasterImage.dbx module (needed for 2009 and earlier)

            RasterDef = New RasterImageDef
            RasterDef.SourceFileName = RasterFile
            RasterDef.ActiveFileName = RasterFile
            RasterDef.Load()

            ImageDicID = RasterImageDef.GetImageDictionary(ThisDoc.Database)
            If ImageDicID.IsNull Then
                RasterImageDef.CreateImageDictionary(ThisDoc.Database)
                ImageDicID = RasterImageDef.GetImageDictionary(ThisDoc.Database)
            End If
            If ImageDicID.IsNull Then
               MsgBox("Could not create image dictionary", MsgBoxStyle.Critical, "Failed")
               'Exit Try
            End If
            ImageDic = Trans.GetObject(ImageDicID, OpenMode.ForWrite)
            If ImageDic Is Nothing Then
                MsgBox("Could not open image dictionary", MsgBoxStyle.Critical, "Failed")
            Else
                If ImageDic.Contains(RasterName) Then
                    MsgBox("That image name is already in use", MsgBoxStyle.Critical, "Failed")
                Else
                    ImageDic.UpgradeOpen()
                    ImageDefID = ImageDic.SetAt(RasterName, RasterDef)
                    Trans.AddNewlyCreatedDBObject(RasterDef, True)
                    RasterEnt = New RasterImage
                    RasterEnt.SetDatabaseDefaults(ThisDoc.Database)
                    RasterEnt.ColorIndex = 256
                    RasterEnt.Linetype = "ByLayer"
                    RasterEnt.LineWeight = LineWeight.ByLayer
                    If IsSTB Then RasterEnt.PlotStyleName = "ByLayer"
                    Matrix = New Geometry.Matrix3d
                    Matrix = Geometry.Matrix3d.Scaling(Scale / RasterDef.Size.X, New Point3d(0, 0, 0))
                    RasterEnt.TransformBy(Matrix)
                    Matrix = Geometry.Matrix3d.Displacement(New Vector3d(InsPoint.X, InsPoint.Y, InsPoint.Z))
                    RasterEnt.TransformBy(Matrix)
                    RasterEnt.ImageDefId = ImageDefID
                    btr = Trans.GetObject(ThisDoc.Database.CurrentSpaceId, OpenMode.ForWrite)
                    btr.AppendEntity(RasterEnt)
                    Trans.AddNewlyCreatedDBObject(RasterEnt, True)
                    Trans.Commit()
                    NumInserted = NumInserted + 1
                End If
            End If

        End Using

        Add_Raster = RasterEnt

    Catch ex As Exception

        MsgBox("Error inserting image " & RasterName, MsgBoxStyle.Critical, "Failed")

    End Try

End Function

huiz

  • Swamp Rat
  • Posts: 913
  • Certified Prof C3D
Re: How to create a RasterImage in AutoCAD
« Reply #9 on: June 29, 2010, 05:40:18 AM »
1. You didn't mention or show the actual code you are using. The code you originally showed does not do a batch insertion, which is now clearly what you are trying to do.

2. You need to use AppendEntity.

I did mention the complete code and it shows a loop. My code is above Tony's function.


Indeed, AppendEntity did the trick. I thought it was not nessaccary because the RasterImageDef got appended already but the RasterImage should be appended as well. It works!  :-)


Just.... only one small thing...

I also tried the cody supplied by GTVic, that works excellent! Thanks :-) But, both codes, no matter which I use, create the RasterImages as Unreferenced. They are visible in AutoCAD though but they are unreferenced. Also, the first file is shown double in the list. See image attached.


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.

Bryco

  • Water Moccasin
  • Posts: 1882
Re: How to create a RasterImage in AutoCAD
« Reply #10 on: June 29, 2010, 10:52:57 AM »
tr.AddNewlyCreatedDBObject(RasterEnt, true);
RasterEnt.AssociateRasterDef(RasterDef);

huiz

  • Swamp Rat
  • Posts: 913
  • Certified Prof C3D
Re: How to create a RasterImage in AutoCAD
« Reply #11 on: June 29, 2010, 10:59:15 AM »
Indeed! At this same second I just found out that was the last problem :-)

Thanks all! Hope my knowledge will help some other guy one day :-)
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 create a RasterImage in AutoCAD
« Reply #12 on: June 29, 2010, 03:10:44 PM »
And a function worth mentioned in the Routines topics: http://www.theswamp.org/index.php?topic=31863.msg392684#msg392684

I took GTVic's code and added transparency and layer option to it. Hope this function will help other people :-)
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.