OSDN Git Service

Update copyright year
[radegast/radegast.git] / Radegast / GUI / Consoles / ImageUploadConsole.cs
1 // 
2 // Radegast Metaverse Client
3 // Copyright (c) 2009-2014, Radegast Development Team
4 // All rights reserved.
5 // 
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // 
9 //     * Redistributions of source code must retain the above copyright notice,
10 //       this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above copyright
12 //       notice, this list of conditions and the following disclaimer in the
13 //       documentation and/or other materials provided with the distribution.
14 //     * Neither the name of the application "Radegast", nor the names of its
15 //       contributors may be used to endorse or promote products derived from
16 //       this software without specific prior written permission.
17 // 
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29 // $Id$
30 //
31 using System;
32 using System.Collections.Generic;
33 using System.ComponentModel;
34 using System.Drawing;
35 using System.Drawing.Imaging;
36 using System.Data;
37 using System.Linq;
38 using System.Text;
39 using System.Windows.Forms;
40 using System.IO;
41 using OpenMetaverse;
42 using OpenMetaverse.Assets;
43 using OpenMetaverse.Imaging;
44
45 namespace Radegast
46 {
47     public partial class ImageUploadConsole : RadegastTabControl
48     {
49         public string FileName, TextureName, TextureDescription;
50         public byte[] UploadData;
51         public UUID InventoryID, AssetID, TransactionID;
52         bool ImageLoaded;
53         int OriginalCapsTimeout;
54
55         public ImageUploadConsole()
56         {
57             InitializeComponent();
58         }
59
60         public ImageUploadConsole(RadegastInstance instance)
61             : base(instance)
62         {
63             InitializeComponent();
64
65             Disposed += new EventHandler(ImageUploadConsole_Disposed);
66             instance.Netcom.ClientConnected += new EventHandler<EventArgs>(Netcom_ClientConnected);
67             instance.Netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(Netcom_ClientDisconnected);
68             client.Assets.AssetUploaded += new EventHandler<AssetUploadEventArgs>(Assets_AssetUploaded);
69             UpdateButtons();
70             OriginalCapsTimeout = client.Settings.CAPS_TIMEOUT;
71         }
72
73         void ImageUploadConsole_Disposed(object sender, EventArgs e)
74         {
75             client.Assets.AssetUploaded -= new EventHandler<AssetUploadEventArgs>(Assets_AssetUploaded);
76         }
77
78         void Assets_AssetUploaded(object sender, AssetUploadEventArgs e)
79         {
80             if (e.Upload.ID == TransactionID)
81             {
82                 if (!e.Upload.Success)
83                 {
84                     TempUploadHandler(false, new InventoryTexture(UUID.Zero));
85                 }
86                 else
87                 {
88                     client.Inventory.RequestCreateItem(client.Inventory.FindFolderForType(AssetType.Texture),
89                         TextureName, TextureDescription, AssetType.Texture, TransactionID,
90                         InventoryType.Texture, PermissionMask.All, TempUploadHandler);
91                 }
92             }
93         }
94
95         void Netcom_ClientDisconnected(object sender, DisconnectedEventArgs e)
96         {
97             if (InvokeRequired)
98             {
99                 if (!instance.MonoRuntime || IsHandleCreated)
100                 {
101                     BeginInvoke(new MethodInvoker(() => Netcom_ClientDisconnected(sender, e)));
102                 }
103                 return;
104             }
105
106             UpdateButtons();
107         }
108
109         void Netcom_ClientConnected(object sender, EventArgs e)
110         {
111             if (InvokeRequired)
112             {
113                 if (!instance.MonoRuntime || IsHandleCreated)
114                 {
115                     BeginInvoke(new MethodInvoker(() => Netcom_ClientConnected(sender, e)));
116                 }
117                 return;
118             }
119
120             UpdateButtons();
121         }
122
123         private bool IsPowerOfTwo(uint n)
124         {
125             return (n & (n - 1)) == 0 && n != 0;
126         }
127
128         private int ClosestPowerOwTwo(int n)
129         {
130             int res = 1;
131
132             while (res < n)
133             {
134                 res <<= 1;
135             }
136
137             return res > 1 ? res / 2 : 1;
138         }
139
140         public void LoadImage(string fname)
141         {
142             FileName = fname;
143
144             if (String.IsNullOrEmpty(FileName))
145                 return;
146
147             txtStatus.AppendText("Loading...\n");
148
149             string extension = System.IO.Path.GetExtension(FileName).ToLower();
150             Bitmap bitmap = null;
151
152             try
153             {
154                 if (extension == ".jp2" || extension == ".j2c")
155                 {
156                     Image image;
157                     ManagedImage managedImage;
158
159                     // Upload JPEG2000 images untouched
160                     UploadData = System.IO.File.ReadAllBytes(FileName);
161
162                     OpenJPEG.DecodeToImage(UploadData, out managedImage, out image);
163                     bitmap = (Bitmap)image;
164
165                     txtStatus.AppendText("Loaded raw JPEG2000 data " + FileName + "\n");
166                 }
167                 else
168                 {
169                     if (extension == ".tga")
170                     {
171                         bitmap = LoadTGAClass.LoadTGA(FileName);
172                     }
173                     else
174                     {
175                         bitmap = (Bitmap)System.Drawing.Image.FromFile(FileName);
176                     }
177                 }
178
179                 txtStatus.AppendText("Loaded image " + FileName + "\n");
180
181                 int width = bitmap.Width;
182                 int height = bitmap.Height;
183
184                 // Handle resizing to prevent excessively large images and irregular dimensions
185                 if (!IsPowerOfTwo((uint)width) || !IsPowerOfTwo((uint)height) || width > 1024 || height > 1024)
186                 {
187                     txtStatus.AppendText("Image has irregular dimensions " + width + "x" + height + "\n");
188
189                     width = ClosestPowerOwTwo(width);
190                     height = ClosestPowerOwTwo(height);
191
192                     width = width > 1024 ? 1024 : width;
193                     height = height > 1024 ? 1024 : height;
194
195                     txtStatus.AppendText("Resizing to " + width + "x" + height + "\n");
196
197                     Bitmap resized = new Bitmap(width, height, bitmap.PixelFormat);
198                     Graphics graphics = Graphics.FromImage(resized);
199
200                     graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
201                     graphics.InterpolationMode =
202                        System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
203                     graphics.DrawImage(bitmap, 0, 0, width, height);
204
205                     bitmap.Dispose();
206                     bitmap = resized;
207                 }
208
209                 txtStatus.AppendText("Encoding image...\n");
210
211                 UploadData = OpenJPEG.EncodeFromImage(bitmap, chkLossless.Checked);
212
213                 txtStatus.AppendText("Finished encoding.\n");
214                 ImageLoaded = true;
215                 UpdateButtons();
216                 txtAssetID.Text = UUID.Zero.ToString();
217
218                 pbPreview.Image = bitmap;
219                 lblSize.Text = string.Format("{0}x{1} {2} KB", bitmap.Width, bitmap.Height, Math.Round((double)UploadData.Length / 1024.0d, 2));
220             }
221             catch (Exception ex)
222             {
223                 UploadData = null;
224                 btnSave.Enabled = false;
225                 btnUpload.Enabled = false;
226                 txtStatus.AppendText(string.Format("Failed to load the image:\n{0}\n", ex.Message));
227                 return;
228             }
229         }
230
231         void UpdateButtons()
232         {
233             btnLoad.Enabled = true;
234
235             if (ImageLoaded)
236             {
237                 btnSave.Enabled = true;
238             }
239             else
240             {
241                 btnSave.Enabled = false;
242             }
243
244             if (ImageLoaded && client.Network.Connected)
245             {
246                 btnUpload.Enabled = true;
247             }
248             else
249             {
250                 btnUpload.Enabled = false;
251             }
252         }
253
254
255         private void btnLoad_Click(object sender, EventArgs e)
256         {
257             OpenFileDialog dialog = new OpenFileDialog();
258             dialog.Filter =
259                 "Image Files (*.jp2,*.j2c,*.jpg,*.jpeg,*.gif,*.png,*.bmp,*.tga,*.tif,*.tiff,*.ico,*.wmf,*.emf)|" +
260                 "*.jp2;*.j2c;*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.tga;*.tif;*.tiff;*.ico;*.wmf;*.emf|" +
261                 "All files (*.*)|*.*";
262
263             if (dialog.ShowDialog() == DialogResult.OK)
264             {
265                 LoadImage(dialog.FileName);
266             }
267         }
268
269         private void btnSave_Click(object sender, EventArgs e)
270         {
271
272             SaveFileDialog dlg = new SaveFileDialog();
273             dlg.AddExtension = true;
274             dlg.RestoreDirectory = true;
275             dlg.Title = "Save image as...";
276             dlg.Filter = "PNG (*.png)|*.png|Targa (*.tga)|*.tga|Jpeg2000 (*.j2c)|*.j2c|Jpeg (*.jpg)|*.jpg|Bitmap (*.bmp)|*.bmp";
277
278
279
280             if (dlg.ShowDialog() == DialogResult.OK)
281             {
282                 int type = dlg.FilterIndex;
283                 if (type == 3)
284                 { // jpeg2000
285                     File.WriteAllBytes(dlg.FileName, UploadData);
286                 }
287                 else if (type == 2)
288                 { // targa
289                     ManagedImage imgManaged;
290                     OpenJPEG.DecodeToImage(UploadData, out imgManaged);
291                     File.WriteAllBytes(dlg.FileName, imgManaged.ExportTGA());
292                 }
293                 else if (type == 1)
294                 { // png
295                     pbPreview.Image.Save(dlg.FileName, ImageFormat.Png);
296                 }
297                 else if (type == 4)
298                 { // jpg
299                     pbPreview.Image.Save(dlg.FileName, ImageFormat.Jpeg);
300                 }
301                 else
302                 { // BMP
303                     pbPreview.Image.Save(dlg.FileName, ImageFormat.Bmp);
304                 }
305             }
306
307             dlg.Dispose();
308         }
309
310         private void TempUploadHandler(bool success, InventoryItem item)
311         {
312             if (InvokeRequired)
313             {
314                 if (IsHandleCreated)
315                 {
316                     BeginInvoke(new MethodInvoker(() => TempUploadHandler(success, item)));
317                 }
318                 return;
319             }
320
321             InventoryID = item.UUID;
322
323             UpdateButtons();
324             txtAssetID.Text = AssetID.ToString();
325
326             if (!success)
327             {
328                 txtStatus.AppendText("Upload failed.\n");
329                 return;
330             }
331
332             txtStatus.AppendText("Upload success.\n");
333             txtStatus.AppendText("New image ID: " + AssetID.ToString() + "\n");
334         }
335
336         private void UploadHandler(bool success, string status, UUID itemID, UUID assetID)
337         {
338             if (InvokeRequired)
339             {
340                 if (IsHandleCreated)
341                 {
342                     BeginInvoke(new MethodInvoker(() => UploadHandler(success, status, itemID, assetID)));
343                 }
344                 return;
345             }
346
347             client.Settings.CAPS_TIMEOUT = OriginalCapsTimeout;
348
349             AssetID = assetID;
350             InventoryID = itemID;
351
352             UpdateButtons();
353             txtAssetID.Text = AssetID.ToString();
354
355             if (!success)
356             {
357                 txtStatus.AppendText("Upload failed: " + status + "\n");
358                 return;
359             }
360
361             txtStatus.AppendText("Upload success.\n");
362             txtStatus.AppendText("New image ID: " + AssetID.ToString() + "\n");
363         }
364
365         private void btnUpload_Click(object sender, EventArgs e)
366         {
367             bool tmp = chkTemp.Checked;
368             txtStatus.AppendText("Uploading...");
369             btnLoad.Enabled = false;
370             btnUpload.Enabled = false;
371             AssetID = InventoryID = UUID.Zero;
372
373             TextureName = Path.GetFileNameWithoutExtension(FileName);
374             if (tmp) TextureName += " (temp)";
375             TextureDescription = string.Format("Uploaded with Radegast on {0}", DateTime.Now.ToLongDateString());
376
377             Permissions perms = new Permissions();
378             perms.EveryoneMask = PermissionMask.All;
379             perms.NextOwnerMask = PermissionMask.All;
380
381             if (!tmp)
382             {
383                 client.Settings.CAPS_TIMEOUT = 180 * 1000;
384                 client.Inventory.RequestCreateItemFromAsset(UploadData, TextureName, TextureDescription, AssetType.Texture, InventoryType.Texture,
385                     client.Inventory.FindFolderForType(AssetType.Texture), perms, UploadHandler);
386             }
387             else
388             {
389                 TransactionID = UUID.Random();
390                 client.Assets.RequestUpload(out AssetID, AssetType.Texture, UploadData, true, TransactionID);
391             }
392         }
393     }
394 }