0

Before an upgrade to Unity and Visual Studio I had a simple block of code that ran without errors, after the updates however the exact same logic raises a NullReferenceException.

The exception is raised when calling BitMap.Save() but I have verified that all the inputs are appropriately instantiated and I can inspect all the associated objects during debug and cannot identify any nulls. In this case the NullReferenceException is very ambiguous and I suspect it is linked specifically to the update to Unity.

Please do not close for duplicate of "What is a NullReferenceException, and how do I fix it?" like my other one. This seems to be an internal issue either with Bitmap and I am looking for specific guidance on how to resolve this.

Bitmap newBmp = new Bitmap(16, 16);
for (int i= 0; i< 16; i++)
{
    for (int j= 0; j< 16; j++)
    {
         newBmp.SetPixel(i, j, Color.blue);
    }
}
using (MemoryStream ms = new MemoryStream())
{
    newBmp.Save(ms, ImageFormat.Bmp); // Null??
    // do more stuff with ms if it didn't crap out
}

Exception Detail, raised on newBmp.Save()

NOTE: neither newBmp or ms are null, and the logic above it has set each pixel to the color blue.

NullReferenceException: Object reference not set to an instance of an object
System.Drawing.ComIStreamMarshaler+ManagedToNativeWrapper..cctor () (at <556bd4f081384ff9b1658a316bdf6616>:0)
Rethrow as TypeInitializationException: The type initializer for 'ManagedToNativeWrapper' threw an exception.
System.Drawing.ComIStreamMarshaler.MarshalManagedToNative (System.Object managedObj) (at <556bd4f081384ff9b1658a316bdf6616>:0)
System.Drawing.Image.Save (System.IO.Stream stream, System.Drawing.Imaging.ImageCodecInfo encoder, System.Drawing.Imaging.EncoderParameters encoderParams) (at <556bd4f081384ff9b1658a316bdf6616>:0)
System.Drawing.Image.Save (System.IO.Stream stream, System.Drawing.Imaging.ImageFormat format) (at <556bd4f081384ff9b1658a316bdf6616>:0)
(wrapper remoting-invoke-with-check) System.Drawing.Image.Save(System.I
CodeMonkey
  • 1,697
  • 1
  • 13
  • 34
  • 1
    _"I know what null means and I'm clearly instantiating everything"_ -- the framework doesn't through `NullReferenceException` for the fun of it. _Something_ is null. And frankly, most often when someone posts a question asking about NRE, they only _think_ that they've eliminated the possibility of a null value. The whole point of the canonical duplicate is to get them past that mindset and help them debug the code so that they can discover their mistake. – Peter Duniho Apr 27 '21 at 18:56
  • 1
    You'll note from the stack trace you posted that you have a type initializer that is throwing the exception. Type initializers are declared far removed from the code where they are usually invoked, so the code you posted doesn't have to have any null values itself for you to have a null value. You need to debug the code more, using the advice in the canonical Q&A. If you can get to a point where you've identified the null value, and still need help, post a question with a proper [mcve] that explains everything you've done so far, and what _specifically_ you need help with in avoiding the null. – Peter Duniho Apr 27 '21 at 18:59
  • 1
    When your debugger stops on the exception, have a look at the InnerException. There is a good chance that this will reveal the actual problem. – Klaus Gütter Apr 27 '21 at 19:20
  • The code fragment you show runs fine here (after fixing the blue typo). – TaW Apr 27 '21 at 20:04
  • Seems to be a [Unity issue](https://forum.unity.com/threads/system-drawing-image-initfromstream-works-in-editor-not-build.531324/). Is the BMP format important or any restorable raw format will do it? If the latter, you can try my [drawing library](https://github.com/koszeggy/KGySoft.Drawing). Just call `newBmp.GetReadableBitmapData().Save(stream)`. Loading and converting back to GDI+ `Bitmap` is by `BitmapDataFactory.Load(stream).ToBitmap()`. I did not test it in Unity but works in Linux and even in Mono. – György Kőszeg Apr 27 '21 at 20:23
  • Someone was kind enough to ACTUALLY help me rather than close my post with "duplicate of newb question". It turned out that my version of System.Drawing.dll which I pulled into my project a while back was not compatible with the new version of Unity. We solved it by removing the dll and adding a "csc.rsp" file to the Assets folder and added the line "-r:System.Drawing.dll" which, I presume, automatically uses the appropriate verison. Too bad I can't answer my question for others who may have the same problem... – CodeMonkey Apr 27 '21 at 20:37
  • I'm glad you could finally solve it. I voted for reopening by the way. Then just a final note: `Bitmap.SetPixel` is painfully slow, and in Unity it can really matter. The library I linked (disclaimer: written by me) [can help](https://github.com/koszeggy/KGySoft.Drawing#fast-bitmap-manipulation) also in this case. And it supports all possible `PixelFormat`s, too. – György Kőszeg Apr 27 '21 at 20:43
  • Oh, cool. I'll take a look. Thanks for actually trying to help, too :-) – CodeMonkey Apr 27 '21 at 20:48
  • I want to vote to re-open. I can see how this can easily get hit with the null dupe hammer, but its no longer appropriate to do so with the solution pasted into the post. I have edited out the solution and hope to see you post the solution when it is re-opened. – Chris Schaller Apr 28 '21 at 00:22
  • @ChrisSchaller: that's fine, except you voted to reopen the wrong post. This post is a duplicate of https://stackoverflow.com/questions/67276097/null-exception-on-bitmap-save-but-not-null-used-to-work-until-updating-unity (the author violated site rules and reposted the question in order to bypass the closure of the previously posted question) – Peter Duniho Apr 28 '21 at 00:47
  • Thanks @PeterDuniho I was conflicted about that and really not sure what to do. I think this post should win and the other get deleted... In the end I voted for both – Chris Schaller Apr 28 '21 at 06:53
  • 1
    @Chris: voting to reopen both is definitely not the correct thing to do. Whatever you think about the quality and nature of the question, the author violated site rules when they reposted it. Don't further compound the problem by voting to reopen _both_ posts, when there only ever should have been one. Voting to reopen a post that you believe should be deleted doesn't really make any sense. – Peter Duniho Apr 28 '21 at 06:55
  • When it was closed, it specifically told me to write a new question if it shouldn't have been closed and to clarify why. That's what I did. I didn't break rules any more than I asked a newb question. – CodeMonkey Apr 28 '21 at 11:04
  • @ChrisSchaller, btw, thanks for the rewrite. That is definitely a better organization of the facts I laid out to help with those who glance at things. Of course, I thought I was rather explicit as well, but hey... :-p – CodeMonkey Apr 28 '21 at 13:12
  • @CodeMonkey you're supposed to delete the original post if you are rewriting... We should discuss rephrasing that text in meta. I get the frustrations, it takes a bit to remove yourself and see your issue through the eyes of the bots and achievement hunters who will close at the first sniff of a duplicate based on key words without taking the time to understand the issue. You want to appeal to the rest of the community, but you have to make it past the gate keepers first – Chris Schaller Apr 28 '21 at 14:42
  • 1
    @ChrisSchaller Maybe there should also be less incentive to blindly close people's posts. At least give the owner the chance to explain how it's not a duplicate and rephrase it or agree and move on. Rep shouldn't be provided to those who make others absolutely hate using SO. Closing with no guidance or rebuttal ability is extremely infuriating when someone mistakes your post as dupe or off topic yet has all the power with no questions asked. Nothing worse than being demeaned and silenced in such a way. Make it a vote, alert the owner, let them chime in. Make it anonymous if necessary. – CodeMonkey Apr 28 '21 at 14:52
  • Otherwise, I learn nothing and simply hate SO and the people who shouldn't be running it. – CodeMonkey Apr 28 '21 at 14:53

1 Answers1

1

It turned out that my version of System.Drawing.dll which I pulled into my Unity project a while back, was not compatible with the new version of Unity. We solved it by removing the dll and adding a "csc.rsp" file to the Assets folder and added the line -r:System.Drawing.dll which, I presume, automatically uses the appropriate version.

CodeMonkey
  • 1,697
  • 1
  • 13
  • 34