Convert PNG to JPG without writing to disk

 
Post new topic   Reply to topic    Unity Community Index // Scripting
View previous topic :: View next topic  
Author Message
Brad Keys



Joined: 01 May 2006
Posts: 33
Location: Vancouver, Canada

PostPosted: Wed Oct 07, 2009 10:05 pm    Post subject: Convert PNG to JPG without writing to disk Reply with quote
Goal
I'm creating a feature that takes a screen capture of the Unity game and uploads it to my web server using the web player. I've got this working just fine.

Issue
The problem is that the files being uploaded are unnecessarily large (300KB+). I could do some image manipulation in PHP, but I'd like to stay away from having my server doing all that work. .Net has some functionality to convert images to other formats, but as far as I've seen those methods require you to write the newly converted image to disk... which I can't have happen since I'm wanting to do this in the web player.

Solution Needed
I need Unity to convert the PNG image to JPG format without writing to disk.

Any ideas on how I can achieve this?
Back to top
View user's profile Send private message Send e-mail Visit poster's website
SoarionStudios



Joined: 23 Apr 2009
Posts: 49
Location: Dallas, TX

PostPosted: Thu Oct 08, 2009 1:37 am    Post subject: Reply with quote
While technically, this is not really "the answer", I have "an answer" Smile

If you look around on this forum thread: https://mollyrocket.com/forums/viewtopic.php?p=5898 then you can find code for a public domain JPG library as well as pointers to some PNG decompression source code. You could likely cobble those together to do what you need if you can port all that to C#... Or if you have the Advanced version, you could do it in native Obj-C or C++ and do it that way?

Smile

Stephen
Back to top
View user's profile Send private message Visit poster's website
Matthew



Joined: 30 Nov 2006
Posts: 1207
Location: Phoenix, AZ

PostPosted: Thu Oct 08, 2009 2:36 am    Post subject: Reply with quote
This should be fairly easy with .NET, but it looks like Unity's Mono environment is lacking the proper functionality.

This line:

Code:

var codecs:ImageCodecInfo[] = ImageCodecInfo.GetImageEncoders();


Produces:

Code:

DllNotFoundException: gdiplus.dll
System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders ()
System.Drawing.GDIPlus..cctor ()
UnityEditor.EditorGUIUtility:RenderGameViewCameras(Rect, Rect, Boolean, Boolean)
UnityEditor.EditorGUIUtility:RenderGameViewCameras(Rect, Rect, Boolean, Boolean)
UnityEditor.GameView:OnGUI()
System.Reflection.MonoMethod:InternalInvoke(Object, Object[])
System.Reflection.MonoMethod:InternalInvoke(Object, Object[])
System.Reflection.MonoMethod:Invoke(Object, BindingFlags, Binder, Object[], CultureInfo)
System.Reflection.MethodBase:Invoke(Object, Object[])
UnityEditor.HostView:Invoke(String)
UnityEditor.DockArea:OnGUI()


I suppose you could find a totally exposed C# implementation of JPEG compression, but with functionality already present in .NET I doubt there's one out there...

_________________
Matthew Wegner
Founder and CEO, Flashbang Studios / Blurst
Co-Chair, IGF
Editor, Fun-Motion
Back to top
View user's profile Send private message Visit poster's website
Brad Keys



Joined: 01 May 2006
Posts: 33
Location: Vancouver, Canada

PostPosted: Thu Oct 08, 2009 6:50 pm    Post subject: Reply with quote
Matthew wrote:
This should be fairly easy with .NET, but it looks like Unity's Mono environment is lacking the proper functionality.

Ya, its turning out to be really inconvenient. Would it be worth me asking for a feature request? Or is this too obscure of a problem?

Matthew wrote:
I suppose you could find a totally exposed C# implementation of JPEG compression, but with functionality already present in .NET I doubt there's one out there...

I doubt that too. I'll keep looking for a bit, but I'm afraid that for the time being I'll just have to handle the compression with PHP.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Matthew



Joined: 30 Nov 2006
Posts: 1207
Location: Phoenix, AZ

PostPosted: Thu Oct 08, 2009 7:23 pm    Post subject: Reply with quote
Brad Keys wrote:
Matthew wrote:
This should be fairly easy with .NET, but it looks like Unity's Mono environment is lacking the proper functionality.

Ya, its turning out to be really inconvenient. Would it be worth me asking for a feature request? Or is this too obscure of a problem?


It's worth requesting, at least. It might be something simple for Unity to add, although my guess is it's a deliberate feature reduction in order to save file size on the web player...

_________________
Matthew Wegner
Founder and CEO, Flashbang Studios / Blurst
Co-Chair, IGF
Editor, Fun-Motion
Back to top
View user's profile Send private message Visit poster's website
Matthew



Joined: 30 Nov 2006
Posts: 1207
Location: Phoenix, AZ

PostPosted: Sun Nov 29, 2009 12:58 am    Post subject: Reply with quote
I ported some AS3 JPEG encoding code to Unity JavaScript--you can now do this natively: http://blur.st/jpeg
_________________
Matthew Wegner
Founder and CEO, Flashbang Studios / Blurst
Co-Chair, IGF
Editor, Fun-Motion
Back to top
View user's profile Send private message Visit poster's website
Brad Keys



Joined: 01 May 2006
Posts: 33
Location: Vancouver, Canada

PostPosted: Sun Nov 29, 2009 1:47 am    Post subject: Reply with quote
Thanks, this will be extremely useful.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Brad Keys



Joined: 01 May 2006
Posts: 33
Location: Vancouver, Canada

PostPosted: Tue Dec 01, 2009 8:21 pm    Post subject: Reply with quote
I tried it out but I'm having some troubles. I'm trying to upload the image to my website, but the file type that's getting uploaded is returning as: application/octet-stream rather than image/jpeg. Here is my modified version of your example project.

Code:

function ScreenshotEncode()
{
   // wait for graphics to render
   yield WaitForEndOfFrame();
   
   // create a texture to pass to encoding
   var texture:Texture2D = new Texture2D (Screen.width, Screen.height, TextureFormat.RGB24, false);
   
   // put buffer into texture
   texture.ReadPixels(Rect(0.0, 0.0, Screen.width, Screen.height), 0.0, 0.0);
   texture.Apply();

   // split the process up--ReadPixels() and the GetPixels() call inside of the encoder are both pretty heavy
   yield;
   
   // create our encoder for this texture
   var encoder:JPGEncoder = new JPGEncoder(texture, 75.0);
   
   // encoder is threaded; wait for it to finish
   while(!encoder.isDone)
      yield;
      
   // Create a Web Form
    var form = new WWWForm();
    form.AddBinaryData("avatar", encoder.GetBytes());

    // Upload to PHP script   
    var w = WWW(screenShotURL, form);
    yield w;
   
    if (w.error != null) {
        print(w.error);   
    }
    else {
        print(w.data);   
    }
}
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Matthew



Joined: 30 Nov 2006
Posts: 1207
Location: Phoenix, AZ

PostPosted: Tue Dec 01, 2009 9:22 pm    Post subject: Reply with quote
This looks like a Unity thing:

Code:

If mimeType is not given and first 8 bytes of the data match PNG format header, then the data is sent with "image/png" mimetype. Otherwise it is sent with "application/octet-stream" mimetype.


The MIME type shouldn't matter too much, depending on what your server-side code looks like. Are you just saving to disk?

_________________
Matthew Wegner
Founder and CEO, Flashbang Studios / Blurst
Co-Chair, IGF
Editor, Fun-Motion
Back to top
View user's profile Send private message Visit poster's website
Matthew



Joined: 30 Nov 2006
Posts: 1207
Location: Phoenix, AZ

PostPosted: Tue Dec 01, 2009 9:31 pm    Post subject: Reply with quote
Actually, based on the docs, just try:
Code:

form.AddBinaryData("avatar", encoder.GetBytes(), "screenshot.jpg", "image/jpeg");

_________________
Matthew Wegner
Founder and CEO, Flashbang Studios / Blurst
Co-Chair, IGF
Editor, Fun-Motion
Back to top
View user's profile Send private message Visit poster's website
Brad Keys



Joined: 01 May 2006
Posts: 33
Location: Vancouver, Canada

PostPosted: Tue Dec 01, 2009 9:42 pm    Post subject: Reply with quote
Ah, yes that did the trick. Works beautifully.

Thanks a lot.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Post new topic   Reply to topic    Unity Community Index // Scripting All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum