From 1fa9399ab86afc126deefafe7277419aaea6f5e1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 8 Dec 2010 00:41:33 +0000 Subject: change doc. trivial commit to get panda to rebuild --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 9ade100..6d72154 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4246,7 +4246,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// + /// Perform the given action for each object /// /// // public void ForEachObject(Action action) -- cgit v1.1 From 7cfb3d7e96a1340d59a5a6984f46ba4fd9e21a0f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 7 Dec 2010 17:17:06 -0800 Subject: Removed extraneous left-/ on /object/ subpath. Bug introduced during region URLs clean up. --- OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 585a30e..3b907c1 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -489,7 +489,7 @@ namespace OpenSim.Services.Connectors.Simulation protected virtual string ObjectPath() { - return "/object/"; + return "object/"; } public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall) -- cgit v1.1 From 796216e44ff78b1088f9a977b810f16d98855f37 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 7 Dec 2010 20:05:53 -0800 Subject: Added an exception handler on CreateObject handler, just in case there's an exception being thrown that is silently being ignored by the http server. (Trying to catch Melanie's problem with attachments on TPs) --- .../Server/Handlers/Simulation/ObjectHandlers.cs | 51 +++++++++++++--------- 1 file changed, 31 insertions(+), 20 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs b/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs index 04ff83f..984b843 100644 --- a/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs @@ -84,32 +84,43 @@ namespace OpenSim.Server.Handlers.Simulation return responsedata; } - // Next, let's parse the verb - string method = (string)request["http-method"]; - if (method.Equals("POST")) - { - DoObjectPost(request, responsedata, regionID); - return responsedata; - } - else if (method.Equals("PUT")) + try { - DoObjectPut(request, responsedata, regionID); - return responsedata; + // Next, let's parse the verb + string method = (string)request["http-method"]; + if (method.Equals("POST")) + { + DoObjectPost(request, responsedata, regionID); + return responsedata; + } + else if (method.Equals("PUT")) + { + DoObjectPut(request, responsedata, regionID); + return responsedata; + } + //else if (method.Equals("DELETE")) + //{ + // DoObjectDelete(request, responsedata, agentID, action, regionHandle); + // return responsedata; + //} + else + { + m_log.InfoFormat("[OBJECT HANDLER]: method {0} not supported in object message", method); + responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed; + responsedata["str_response_string"] = "Method not allowed"; + + return responsedata; + } } - //else if (method.Equals("DELETE")) - //{ - // DoObjectDelete(request, responsedata, agentID, action, regionHandle); - // return responsedata; - //} - else + catch (Exception e) { - m_log.InfoFormat("[OBJECT HANDLER]: method {0} not supported in object message", method); - responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed; - responsedata["str_response_string"] = "Mthod not allowed"; + m_log.WarnFormat("[OBJECT HANDLER]: Caught exception {0}", e.StackTrace); + responsedata["int_response_code"] = HttpStatusCode.InternalServerError; + responsedata["str_response_string"] = "Internal server error"; return responsedata; - } + } } protected void DoObjectPost(Hashtable request, Hashtable responsedata, UUID regionID) -- cgit v1.1 From 4df1d25d23d76ee3ae8c7da155462b57735f6418 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 9 Dec 2010 01:55:32 +0000 Subject: Plumb a code path for the entity transfer module to ask a destination scene whether or not an agent is allowed there as a root agent. --- .../Simulation/LocalSimulationConnector.cs | 17 +++++++ .../Simulation/RemoteSimulationConnector.cs | 17 +++++++ OpenSim/Region/Framework/Scenes/Scene.cs | 11 ++++ .../Server/Handlers/Simulation/AgentHandlers.cs | 26 ++++++++++ .../Simulation/SimulationServiceConnector.cs | 59 ++++++++++++++++++++++ OpenSim/Services/Interfaces/ISimulationService.cs | 2 + 6 files changed, 132 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index e32dbb3..37b403e 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -257,6 +257,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return false; } + public bool QueryAccess(GridRegion destination, UUID id) + { + if (destination == null) + return false; + + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == destination.RegionHandle) + { + //m_log.Debug("[LOCAL COMMS]: Found region to send QueryAccess"); + return s.QueryAccess(id); + } + } + //m_log.Debug("[LOCAL COMMS]: region not found for QueryAccess"); + return false; + } + public bool ReleaseAgent(UUID origin, UUID id, string uri) { foreach (Scene s in m_sceneList) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs index 3f577f2..387a9b8 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs @@ -239,6 +239,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation } + public bool QueryAccess(GridRegion destination, UUID id) + { + if (destination == null) + return false; + + // Try local first + if (m_localBackend.QueryAccess(destination, id)) + return true; + + // else do the remote thing + if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) + return m_remoteConnector.QueryAccess(destination, id); + + return false; + + } + public bool ReleaseAgent(UUID origin, UUID id, string uri) { // Try local first diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 6d72154..de75375 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4953,5 +4953,16 @@ namespace OpenSim.Region.Framework.Scenes DeleteSceneObject(grp, true); } } + + // This method is called across the simulation connector to + // determine if a given agent is allowed in this region + // AS A ROOT AGENT. Returning false here will prevent them + // from logging into the region, teleporting into the region + // or corssing the broder walking, but will NOT prevent + // child agent creation, thereby emulating the SL behavior. + public bool QueryAccess(UUID agentID) + { + return true; + } } } diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs index 1f7e502..24ae81f 100644 --- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs @@ -110,6 +110,11 @@ namespace OpenSim.Server.Handlers.Simulation DoAgentDelete(request, responsedata, agentID, action, regionID); return responsedata; } + else if (method.Equals("QUERYACCESSS")) + { + DoQueryAccess(request, responsedata, agentID, regionID); + return responsedata; + } else { m_log.InfoFormat("[AGENT HANDLER]: method {0} not supported in agent message", method); @@ -300,6 +305,27 @@ namespace OpenSim.Server.Handlers.Simulation return m_SimulationService.UpdateAgent(destination, agent); } + protected virtual void DoQueryAccess(Hashtable request, Hashtable responsedata, UUID id, UUID regionID) + { + if (m_SimulationService == null) + { + m_log.Debug("[AGENT HANDLER]: Agent QUERY called. Harmless but useless."); + responsedata["content_type"] = "application/json"; + responsedata["int_response_code"] = HttpStatusCode.NotImplemented; + responsedata["str_response_string"] = string.Empty; + + return; + } + + GridRegion destination = new GridRegion(); + destination.RegionID = regionID; + + bool result = m_SimulationService.QueryAccess(destination, id); + + responsedata["int_response_code"] = HttpStatusCode.OK; + responsedata["str_response_string"] = result.ToString(); + } + protected virtual void DoAgentGet(Hashtable request, Hashtable responsedata, UUID id, UUID regionID) { if (m_SimulationService == null) diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 3b907c1..e2032d9 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -409,6 +409,65 @@ namespace OpenSim.Services.Connectors.Simulation return false; } + public bool QueryAccess(GridRegion destination, UUID id) + { + IPEndPoint ext = destination.ExternalEndPoint; + if (ext == null) return false; + // Eventually, we want to use a caps url instead of the agentID + string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); + request.Method = "QUERYACCESS"; + request.Timeout = 10000; + //request.Headers.Add("authorization", ""); // coming soon + + HttpWebResponse webResponse = null; + string reply = string.Empty; + StreamReader sr = null; + try + { + webResponse = (HttpWebResponse)request.GetResponse(); + if (webResponse == null) + { + m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Null reply on agent query "); + } + + sr = new StreamReader(webResponse.GetResponseStream()); + reply = sr.ReadToEnd().Trim(); + + + } + catch (WebException ex) + { + m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR]: exception on reply of agent query {0}", ex.Message); + // ignore, really + return false; + } + finally + { + if (sr != null) + sr.Close(); + } + + if (webResponse.StatusCode == HttpStatusCode.OK) + { + try + { + bool result; + + result = bool.Parse(reply); + + return result; + } + catch + { + return false; + } + } + + return false; + } + public bool ReleaseAgent(UUID origin, UUID id, string uri) { WebRequest request = WebRequest.Create(uri); diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs index 67d7cbe..12e8982 100644 --- a/OpenSim/Services/Interfaces/ISimulationService.cs +++ b/OpenSim/Services/Interfaces/ISimulationService.cs @@ -60,6 +60,8 @@ namespace OpenSim.Services.Interfaces bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent); + bool QueryAccess(GridRegion destination, UUID id); + /// /// Message from receiving region to departing region, telling it got contacted by the client. /// When sent over REST, it invokes the opaque uri. -- cgit v1.1 From 1070cffcf905f77d694e140d0c9e978f5d0052c0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 8 Dec 2010 18:53:15 -0800 Subject: Added ability for GetTexture to serve multiple formats. The format may come as an extra query parameter in the URL format= (this was tested and working) or it may come in the Accept header (code added, but not tested). The result of the conversion is placed in the asset cache, under the name -. --- OpenSim/Framework/WebUtil.cs | 81 +++++++ .../CoreModules/Avatar/Assets/GetTextureModule.cs | 244 +++++++++++++++++---- 2 files changed, 283 insertions(+), 42 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index d16f9bf..1c856af 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -26,6 +26,7 @@ */ using System; +using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; @@ -363,5 +364,85 @@ namespace OpenSim.Framework } #endregion Stream + + public class QBasedComparer : IComparer + { + public int Compare(Object x, Object y) + { + float qx = GetQ(x); + float qy = GetQ(y); + if (qx < qy) + return -1; + if (qx == qy) + return 0; + return 1; + } + + private float GetQ(Object o) + { + // Example: image/png;q=0.9 + + if (o is String) + { + string mime = (string)o; + string[] parts = mime.Split(new char[] { ';' }); + if (parts.Length > 1) + { + string[] kvp = parts[1].Split(new char[] { '=' }); + if (kvp.Length == 2 && kvp[0] == "q") + { + float qvalue = 1F; + float.TryParse(kvp[1], out qvalue); + return qvalue; + } + } + } + + return 1F; + } + } + + /// + /// Takes the value of an Accept header and returns the preferred types + /// ordered by q value (if it exists). + /// Example input: image/jpg;q=0.7, image/png;q=0.8, image/jp2 + /// Exmaple output: ["jp2", "png", "jpg"] + /// NOTE: This doesn't handle the semantics of *'s... + /// + /// + /// + public static string[] GetPreferredImageTypes(string accept) + { + + if (accept == null || accept == string.Empty) + return new string[0]; + + string[] types = accept.Split(new char[] { ',' }); + if (types.Length > 0) + { + List list = new List(types); + list.RemoveAll(delegate(string s) { return !s.ToLower().StartsWith("image"); }); + ArrayList tlist = new ArrayList(list); + tlist.Sort(new QBasedComparer()); + + string[] result = new string[tlist.Count]; + for (int i = 0; i < tlist.Count; i++) + { + string mime = (string)tlist[i]; + string[] parts = mime.Split(new char[] { ';' }); + string[] pair = parts[0].Split(new char[] { '/' }); + if (pair.Length == 2) + result[i] = pair[1].ToLower(); + else // oops, we don't know what this is... + result[i] = pair[0]; + } + + return result; + } + + return new string[0]; + } + + } } diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs index 97581e5..ac2ad7a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs @@ -28,6 +28,8 @@ using System; using System.Collections; using System.Collections.Specialized; +using System.Drawing; +using System.Drawing.Imaging; using System.Reflection; using System.IO; using System.Web; @@ -35,6 +37,7 @@ using log4net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.StructuredData; +using OpenMetaverse.Imaging; using OpenSim.Framework; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; @@ -74,6 +77,12 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps private Scene m_scene; private IAssetService m_assetService; + public const string DefaultFormat = "x-j2c"; + + // TODO: Change this to a config option + const string REDIRECT_URL = null; + + #region IRegionModule Members public void Initialise(Scene pScene, IConfigSource pSource) @@ -96,7 +105,7 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps { UUID capID = UUID.Random(); - m_log.Info("[GETTEXTURE]: /CAPS/" + capID); + m_log.InfoFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); } @@ -104,12 +113,12 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps private byte[] ProcessGetTexture(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { - // TODO: Change this to a config option - const string REDIRECT_URL = null; + //m_log.DebugFormat("[GETTEXTURE]: called in {0}", m_scene.RegionInfo.RegionName); // Try to parse the texture ID from the request URL NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); string textureStr = query.GetOne("texture_id"); + string format = query.GetOne("format"); if (m_assetService == null) { @@ -121,33 +130,85 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps UUID textureID; if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID)) { - //m_log.DebugFormat("[GETTEXTURE]: {0}", textureID); - AssetBase texture; + string[] formats; + if (format != null && format != string.Empty) + { + formats = new string[1] { format.ToLower() }; + } + else + { + formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get("Accept")); + if (formats.Length == 0) + formats = new string[1] { DefaultFormat }; // default - if (!String.IsNullOrEmpty(REDIRECT_URL)) + } + // OK, we have an array with preferred formats, possibly with only one entry + + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + foreach (string f in formats) { - // Only try to fetch locally cached textures. Misses are redirected - texture = m_assetService.GetCached(textureID.ToString()); + if (FetchTexture(httpRequest, httpResponse, textureID, f)) + break; + } - if (texture != null) - { - if (texture.Type != (sbyte)AssetType.Texture) - { - httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; - httpResponse.Send(); - return null; - } - SendTexture(httpRequest, httpResponse, texture); - } - else + } + else + { + m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); + } + + httpResponse.Send(); + return null; + } + + /// + /// + /// + /// + /// + /// + /// + /// False for "caller try another codec"; true otherwise + private bool FetchTexture(OSHttpRequest httpRequest, OSHttpResponse httpResponse, UUID textureID, string format) + { + m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format); + AssetBase texture; + + string fullID = textureID.ToString(); + if (format != DefaultFormat) + fullID = fullID + "-" + format; + + if (!String.IsNullOrEmpty(REDIRECT_URL)) + { + // Only try to fetch locally cached textures. Misses are redirected + texture = m_assetService.GetCached(fullID); + + if (texture != null) + { + if (texture.Type != (sbyte)AssetType.Texture) { - string textureUrl = REDIRECT_URL + textureID.ToString(); - m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl); - httpResponse.RedirectLocation = textureUrl; + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + return true; } + WriteTextureData(httpRequest, httpResponse, texture, format); } else { + string textureUrl = REDIRECT_URL + textureID.ToString(); + m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl); + httpResponse.RedirectLocation = textureUrl; + return true; + } + } + else // no redirect + { + // try the cache + texture = m_assetService.GetCached(fullID); + + if (texture == null) + { + //m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache"); + // Fetch locally or remotely. Misses return a 404 texture = m_assetService.Get(textureID.ToString()); @@ -156,32 +217,49 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps if (texture.Type != (sbyte)AssetType.Texture) { httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; - httpResponse.Send(); - return null; + return true; + } + if (format == DefaultFormat) + { + WriteTextureData(httpRequest, httpResponse, texture, format); + return true; + } + else + { + AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.CreatorID); + newTexture.Data = ConvertTextureData(texture, format); + if (newTexture.Data.Length == 0) + return false; // !!! Caller try another codec, please! + + newTexture.Flags = AssetFlags.Collectable; + newTexture.Temporary = true; + m_assetService.Store(newTexture); + WriteTextureData(httpRequest, httpResponse, newTexture, format); + return true; } - SendTexture(httpRequest, httpResponse, texture); - } - else - { - m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); - httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; } - } - } - else - { - m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); + } + else // it was on the cache + { + //m_log.DebugFormat("[GETTEXTURE]: texture was in the cache"); + WriteTextureData(httpRequest, httpResponse, texture, format); + return true; + } + } - httpResponse.Send(); - return null; + // not found + m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + return true; + } - private void SendTexture(OSHttpRequest request, OSHttpResponse response, AssetBase texture) + private void WriteTextureData(OSHttpRequest request, OSHttpResponse response, AssetBase texture, string format) { string range = request.Headers.GetOne("Range"); //m_log.DebugFormat("[GETTEXTURE]: Range {0}", range); - if (!String.IsNullOrEmpty(range)) + if (!String.IsNullOrEmpty(range)) // JP2's only { // Range request int start, end; @@ -212,15 +290,19 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps } else { - m_log.Warn("Malformed Range header: " + range); + m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range); response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; } } - else + else // JP2's or other formats { // Full content request + response.StatusCode = (int)System.Net.HttpStatusCode.OK; response.ContentLength = texture.Data.Length; - response.ContentType = texture.Metadata.ContentType; + if (format == DefaultFormat) + response.ContentType = texture.Metadata.ContentType; + else + response.ContentType = "image/" + format; response.Body.Write(texture.Data, 0, texture.Data.Length); } } @@ -240,5 +322,83 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps start = end = 0; return false; } + + + private byte[] ConvertTextureData(AssetBase texture, string format) + { + m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format); + byte[] data = new byte[0]; + + MemoryStream imgstream = new MemoryStream(); + Bitmap mTexture = new Bitmap(1, 1); + ManagedImage managedImage; + Image image = (Image)mTexture; + + try + { + // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data + + imgstream = new MemoryStream(); + + // Decode image to System.Drawing.Image + if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image)) + { + // Save to bitmap + mTexture = new Bitmap(image); + + EncoderParameters myEncoderParameters = new EncoderParameters(); + myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L); + + // Save bitmap to stream + ImageCodecInfo codec = GetEncoderInfo("image/" + format); + if (codec != null) + { + mTexture.Save(imgstream, codec, myEncoderParameters); + // Write the stream to a byte array for output + data = imgstream.ToArray(); + } + else + m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format); + + } + } + catch (Exception e) + { + m_log.WarnFormat("[GETTEXTURE]: Unable to convert texture {0} to {1}: {2}", texture.ID, format, e.Message); + } + finally + { + // Reclaim memory, these are unmanaged resources + // If we encountered an exception, one or more of these will be null + if (mTexture != null) + mTexture.Dispose(); + + if (image != null) + image.Dispose(); + + if (imgstream != null) + { + imgstream.Close(); + imgstream.Dispose(); + } + } + + return data; + } + + // From msdn + private static ImageCodecInfo GetEncoderInfo(String mimeType) + { + ImageCodecInfo[] encoders; + encoders = ImageCodecInfo.GetImageEncoders(); + for (int j = 0; j < encoders.Length; ++j) + { + if (encoders[j].MimeType == mimeType) + return encoders[j]; + } + return null; + } + + } } -- cgit v1.1