+ Added Async download support to AssetSystem/ImageManager.cs
+ Started converting IA_ImageTool/ImageTool.cs to use the JasperLibrary, but was getting errors TODO: Add an Async download option to the ImageTool download example application git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@448 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using libsecondlife;
|
||||
using libsecondlife.Packets;
|
||||
@@ -34,17 +35,26 @@ using libsecondlife.InventorySystem;
|
||||
|
||||
namespace libsecondlife.AssetSystem
|
||||
{
|
||||
/// <summary>
|
||||
public delegate void ImageRetrievedCallback(LLUUID id, byte[] data); //this delegate is called when an image completed.
|
||||
|
||||
/// <summary>
|
||||
/// Manages the uploading and downloading of Images from SecondLife
|
||||
/// </summary>
|
||||
public class ImageManager
|
||||
{
|
||||
private SecondLife slClient;
|
||||
|
||||
public enum CacheTypes {None, Memory, Disk};
|
||||
private CacheTypes CacheType;
|
||||
private string CacheDirectory = "ImageCache";
|
||||
private Dictionary<LLUUID, Byte[]> CacheTable = new Dictionary<LLUUID, byte[]>();
|
||||
|
||||
private ImagePacketHelpers ImagePacketHelper;
|
||||
|
||||
private Dictionary<LLUUID, TransferRequest> htDownloadRequests = new Dictionary<LLUUID,TransferRequest>();
|
||||
|
||||
public ImageRetrievedCallback OnImageRetrieved;
|
||||
|
||||
private class TransferRequest
|
||||
{
|
||||
public bool Completed;
|
||||
@@ -75,18 +85,122 @@ namespace libsecondlife.AssetSystem
|
||||
/// <param name="client"></param>
|
||||
public ImageManager(SecondLife client)
|
||||
{
|
||||
slClient = client;
|
||||
Init(client, CacheTypes.None, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="ctype">The type of Cache system to use for images.</param>
|
||||
public ImageManager(SecondLife client, CacheTypes ctype)
|
||||
{
|
||||
Init(client, ctype, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="ctype">The type of Cache system to use for images.</param>
|
||||
/// <param name="directory">The directory to use for disk based caching.</param>
|
||||
public ImageManager(SecondLife client, CacheTypes ctype, String directory)
|
||||
{
|
||||
Init(client, ctype, directory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="ctype">The type of Cache system to use for images.</param>
|
||||
/// <param name="directory">The directory to use for disk based caching.</param>
|
||||
private void Init(SecondLife client, CacheTypes ctype, string directory)
|
||||
{
|
||||
slClient = client;
|
||||
|
||||
// Setup Image Caching
|
||||
CacheType = ctype;
|
||||
if (ctype == CacheTypes.Disk)
|
||||
{
|
||||
if (directory != null)
|
||||
{
|
||||
CacheDirectory = directory;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(CacheDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(CacheDirectory);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("ERROR: Disk Cache directory could not be established, defaulting to Memory Cache.");
|
||||
Console.WriteLine(e.Message);
|
||||
|
||||
CacheType = CacheTypes.Memory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Image Packet Helpers
|
||||
ImagePacketHelper = new ImagePacketHelpers(client.Network.AgentID, client.Network.SessionID);
|
||||
|
||||
PacketCallback ImageDataCallback = new PacketCallback(ImageDataCallbackHandler);
|
||||
slClient.Network.RegisterCallback(PacketType.ImageData, ImageDataCallback);
|
||||
// Image Callbacks
|
||||
slClient.Network.RegisterCallback(PacketType.ImageData, new PacketCallback(ImageDataCallbackHandler));
|
||||
slClient.Network.RegisterCallback(PacketType.ImagePacket, new PacketCallback(ImagePacketCallbackHandler));
|
||||
slClient.Network.RegisterCallback(PacketType.ImageNotInDatabase, new PacketCallback(ImageNotInDatabaseCallbackHandler));
|
||||
}
|
||||
|
||||
PacketCallback ImagePacketCallback = new PacketCallback(ImagePacketCallbackHandler);
|
||||
slClient.Network.RegisterCallback(PacketType.ImagePacket, ImagePacketCallback);
|
||||
private void CacheImage(LLUUID ImageID, byte[] ImageData)
|
||||
{
|
||||
switch (CacheType)
|
||||
{
|
||||
case CacheTypes.Memory:
|
||||
CacheTable[ImageID] = ImageData;
|
||||
break;
|
||||
case CacheTypes.Disk:
|
||||
String filepath = Path.Combine(CacheDirectory, ImageID.ToStringHyphenated());
|
||||
File.WriteAllBytes(filepath, ImageData);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PacketCallback ImageNotInDatabaseCallback = new PacketCallback(ImageNotInDatabaseCallbackHandler);
|
||||
slClient.Network.RegisterCallback(PacketType.ImageNotInDatabase, ImageNotInDatabaseCallback);
|
||||
private byte[] CachedImage(LLUUID ImageID)
|
||||
{
|
||||
switch (CacheType)
|
||||
{
|
||||
case CacheTypes.Memory:
|
||||
if (CacheTable.ContainsKey(ImageID))
|
||||
{
|
||||
return CacheTable[ImageID];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
case CacheTypes.Disk:
|
||||
String filepath = Path.Combine(CacheDirectory, ImageID.ToStringHyphenated());
|
||||
if (File.Exists(filepath))
|
||||
{
|
||||
return File.ReadAllBytes(filepath);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool isDownloadingImages()
|
||||
{
|
||||
return htDownloadRequests.Count > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -95,6 +209,12 @@ namespace libsecondlife.AssetSystem
|
||||
/// <param name="ImageID">The Image's AssetID</param>
|
||||
public byte[] RequestImage(LLUUID ImageID)
|
||||
{
|
||||
byte[] imgData = CachedImage(ImageID);
|
||||
if (imgData != null)
|
||||
{
|
||||
return imgData;
|
||||
}
|
||||
|
||||
TransferRequest tr = new TransferRequest();
|
||||
tr.Completed = false;
|
||||
tr.Size = int.MaxValue; // Number of bytes expected
|
||||
@@ -113,15 +233,39 @@ namespace libsecondlife.AssetSystem
|
||||
|
||||
if( tr.Status == true )
|
||||
{
|
||||
CacheImage(ImageID, tr.AssetData);
|
||||
return tr.AssetData;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception( "RequestImage: " + tr.StatusMsg );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requests an image from SecondLife.
|
||||
/// </summary>
|
||||
/// <param name="ImageID">The Image's AssetID</param>
|
||||
public void RequestImageAsync(LLUUID ImageID)
|
||||
{
|
||||
byte[] imgData = CachedImage(ImageID);
|
||||
if (imgData != null)
|
||||
{
|
||||
FireImageRetrieved(ImageID, imgData);
|
||||
}
|
||||
|
||||
TransferRequest tr = new TransferRequest();
|
||||
tr.Completed = false;
|
||||
tr.Size = int.MaxValue; // Number of bytes expected
|
||||
tr.Received = 0; // Number of bytes received
|
||||
tr.LastPacket = Helpers.GetUnixTime(); // last time we recevied a packet for this request
|
||||
|
||||
htDownloadRequests[ImageID] = tr;
|
||||
|
||||
Packet packet = ImagePacketHelper.RequestImage(ImageID);
|
||||
slClient.Network.SendPacket(packet);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles the Image Data packet, which includes the ID, and Size of the image,
|
||||
@@ -140,7 +284,7 @@ namespace libsecondlife.AssetSystem
|
||||
byte[] Data = reply.ImageData.Data;
|
||||
|
||||
// Lookup the request that this packet is for
|
||||
TransferRequest tr = (TransferRequest)htDownloadRequests[ImageID];
|
||||
TransferRequest tr = htDownloadRequests[ImageID];
|
||||
if( tr == null )
|
||||
{
|
||||
// Received a packet for an image we didn't request...
|
||||
@@ -159,8 +303,11 @@ namespace libsecondlife.AssetSystem
|
||||
// If we've gotten all the data, mark it completed.
|
||||
if( tr.Received >= tr.Size )
|
||||
{
|
||||
tr.Completed = true;
|
||||
tr.Status = true;
|
||||
tr.Completed = true;
|
||||
|
||||
// Fire off image downloaded event
|
||||
FireImageRetrieved(ImageID, tr.AssetData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,9 +320,10 @@ namespace libsecondlife.AssetSystem
|
||||
{
|
||||
ImagePacketPacket reply = (ImagePacketPacket)packet;
|
||||
|
||||
LLUUID ImageID = reply.ImageID.ID;
|
||||
|
||||
// Lookup the request for this packet
|
||||
TransferRequest tr = (TransferRequest)htDownloadRequests[reply.ImageID.ID];
|
||||
TransferRequest tr = (TransferRequest)htDownloadRequests[ImageID];
|
||||
if( tr == null )
|
||||
{
|
||||
// Received a packet that doesn't belong to any requests in our queue, strange...
|
||||
@@ -195,8 +343,11 @@ namespace libsecondlife.AssetSystem
|
||||
// If we've gotten all the data, mark it completed.
|
||||
if( tr.Received >= tr.Size )
|
||||
{
|
||||
tr.Completed = true;
|
||||
tr.Status = true;
|
||||
tr.Status = true;
|
||||
tr.Completed = true;
|
||||
|
||||
// Fire off image downloaded event
|
||||
FireImageRetrieved(ImageID, tr.AssetData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +356,33 @@ namespace libsecondlife.AssetSystem
|
||||
/// </summary>
|
||||
public void ImageNotInDatabaseCallbackHandler(Packet packet, Simulator simulator)
|
||||
{
|
||||
Console.WriteLine(packet);
|
||||
ImageNotInDatabasePacket reply = (ImageNotInDatabasePacket)packet;
|
||||
|
||||
LLUUID ImageID = reply.ImageID.ID;
|
||||
|
||||
// Lookup the request for this packet
|
||||
TransferRequest tr = (TransferRequest)htDownloadRequests[ImageID];
|
||||
if( tr == null )
|
||||
{
|
||||
// Received a packet that doesn't belong to any requests in our queue, strange...
|
||||
return;
|
||||
}
|
||||
|
||||
tr.Status = false;
|
||||
tr.StatusMsg = "Image not in database";
|
||||
tr.Completed = true;
|
||||
|
||||
// Fire off image downloaded event
|
||||
FireImageRetrieved(ImageID, null);
|
||||
}
|
||||
|
||||
private void FireImageRetrieved(LLUUID ImageID, byte[] ImageData)
|
||||
{
|
||||
if (OnImageRetrieved != null)
|
||||
{
|
||||
OnImageRetrieved(ImageID, ImageData);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,10 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\libjaspernet\libjaspernet.csproj">
|
||||
<Project>{7D4C4807-7705-48A7-9D82-F6689FBBCC8B}</Project>
|
||||
<Name>libjaspernet</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\IA_SimpleInventory\IA_SimpleInventory.csproj">
|
||||
<Project>{E464B963-46E3-4E1A-A36F-9C640C880E68}</Project>
|
||||
<Name>IA_SimpleInventory</Name>
|
||||
|
||||
@@ -8,6 +8,8 @@ using libsecondlife;
|
||||
using libsecondlife.InventorySystem;
|
||||
using libsecondlife.AssetSystem;
|
||||
|
||||
|
||||
|
||||
namespace IA_ImageTool
|
||||
{
|
||||
/// <summary>
|
||||
@@ -25,8 +27,12 @@ namespace IA_ImageTool
|
||||
[STAThread]
|
||||
static new void Main(string[] args)
|
||||
{
|
||||
if (KakaduWrap.Check4Tools() == false)
|
||||
if (
|
||||
// (File.Exists("libjasper.dll") == false) &&
|
||||
(KakaduWrap.Check4Tools() == false)
|
||||
)
|
||||
{
|
||||
// Console.WriteLine("or you need a copy of libjasper.dll, it can be found in SVN in the main trunk inside libjaspernet");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -65,6 +71,7 @@ namespace IA_ImageTool
|
||||
}
|
||||
|
||||
ImageTool it = new ImageTool(id, filename, put);
|
||||
it.DownloadInventoryOnConnect = false;
|
||||
it.Connect(args[0], args[1], args[2]);
|
||||
it.doStuff();
|
||||
it.Disconnect();
|
||||
@@ -101,16 +108,27 @@ namespace IA_ImageTool
|
||||
|
||||
|
||||
int start = Environment.TickCount;
|
||||
ImageManager im = new ImageManager(base.client);
|
||||
ImageManager im = new ImageManager(base.client, ImageManager.CacheTypes.Disk);
|
||||
byte[] j2cdata = im.RequestImage(_ImageID);
|
||||
int end = Environment.TickCount;
|
||||
Console.WriteLine("Elapsed download time, in TickCounts: " + (end - start));
|
||||
|
||||
Console.WriteLine("Image Data Length :" + j2cdata.Length);
|
||||
|
||||
Console.WriteLine("Writing to: " + _FileName + ".tif");
|
||||
KakaduWrap.WriteJ2CAsTiff(_FileName + ".tif", j2cdata);
|
||||
|
||||
Console.WriteLine("Writing to: " + _FileName + ".bmp");
|
||||
KakaduWrap.WriteJ2CAsBmp(_FileName + ".bmp", j2cdata);
|
||||
|
||||
/*
|
||||
Console.WriteLine("Writing to: " + _FileName + ".tif");
|
||||
File.WriteAllBytes(_FileName + ".tif", JasperWrapper.jasper_decode_j2c_to_tiff(j2cdata));
|
||||
|
||||
Console.WriteLine("Writing to: " + _FileName + ".tga");
|
||||
File.WriteAllBytes(_FileName + ".tga", JasperWrapper.jasper_decode_j2c_to_tga(j2cdata));
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
Console.WriteLine("Done...");
|
||||
|
||||
Reference in New Issue
Block a user