Create thumbnail from remote image in c#
Most of the thumbnail scripts I came across show how to create a thumbnail from a local image, but if the image is on another server, then here’s a script in asp.net / c# for that:
protected void Page_Load(object sender, EventArgs e)
{
string Image = Request.QueryString[“Image”];
if (Image == null)
{
throw new Exception(“Image is required”);
}
string sSize = Request[“Size”];
int Size = 120;
if (sSize != null) Size = Int32.Parse(sSize);
Bitmap bmp = CreateThumbnail(Image, Size, Size);
// Put user code to initialize the page here
Response.ContentType = “image/jpeg”;
bmp.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Jpeg);
bmp.Dispose();
}
Then we add the code for CreateThumbnail;
public static Bitmap CreateThumbnail(string strUrl,int lnWidth, int lnHeight)
{System.Drawing.Bitmap bmpOut = null;
System.Net.WebRequest request = System.Net.WebRequest.Create(strUrl);
System.Net.WebResponse response = request.GetResponse();
System.IO.Stream responseStream = response.GetResponseStream();
Bitmap loBMP = new Bitmap(responseStream);
ImageFormat loFormat = loBMP.RawFormat;
decimal lnRatio;
int lnNewWidth = 0;
int lnNewHeight = 0;
//*** If the image is smaller than a thumbnail just return it
if (loBMP.Width < lnWidth && loBMP.Height < lnHeight)
return loBMP;
if (loBMP.Width > loBMP.Height)
{
lnRatio = (decimal) lnWidth / loBMP.Width;
lnNewWidth = lnWidth;
decimal lnTemp = loBMP.Height * lnRatio;
lnNewHeight = (int)lnTemp;
}
else
{
lnRatio = (decimal) lnHeight / loBMP.Height;
lnNewHeight = lnHeight;
decimal lnTemp = loBMP.Width * lnRatio;
lnNewWidth = (int) lnTemp;
}
// System.Drawing.Image imgOut =
// loBMP.GetThumbnailImage(lnNewWidth,lnNewHeight,
// null,IntPtr.Zero);// *** This code creates cleaner (though bigger) thumbnails and properly
// *** and handles GIF files better by generating a white background for
// *** transparent images (as opposed to black)
bmpOut = new Bitmap(lnNewWidth, lnNewHeight);
Graphics g = Graphics.FromImage(bmpOut);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle( Brushes.White,0,0,lnNewWidth,lnNewHeight);
g.DrawImage(loBMP,0,0,lnNewWidth,lnNewHeight);
loBMP.Dispose();
return bmpOut;
}
I’ll probably be developing this further to implement a local cache of thumbnails, but let’s see how this goes…
Handle custom Url schemes in Chrome / Firefox
If you want to be the go-to site to handle common url schemes (protocols), such as a Gmail wants to handle mailto: links, and so forth, then you can prompt the user to accept your website as the default handler for common uri schemes, using this simple code:
try
{
navigator.registerProtocolHandler(“protocol”, “http://www.yourdomain.com/?to=%s”, “Your site”);
} catch (ex) { }
The Try / Catch is just there for older browsers, or Internet explorer. The script has to be executed from the same domain as mentioned in the protocol handler. Otherwise it’ll be just flatly ignored.
Convert Quicktime (MOV) to Mpeg4 (MP4) in C#
I came across CloudConvert today, and I think this is the coolest thing since sliced bread. If at one point sliced bread was cool.
With a couple of lines of code you can convert a MOV (Quicktime) video to the more ubiquitous Mpeg 4 (Mp4) format, and then drop the file back to Amazon S3 for playback.
WebClient wc = new WebClient();
string strUrl = “https://api.cloudconvert.org/convert?”;
strUrl += “apikey=[YOUR KEY HERE]”;
strUrl += “&input=download”;
strUrl += “&output[s3][accesskeyid]=[YOUR KEY HERE]”;
strUrl += “&output[s3][secretaccesskey]=[YOUR KEY HERE]”;
strUrl += “&output[s3][bucket]=video”;
strUrl += “&output[s3][region]=eu-west-1”;
strUrl += “&output[s3][acl]=private”;
strUrl += “&download=inline”;
strUrl += “&inputformat=mov”;
strUrl += “&outputformat=mp4”;
strUrl += “&file=http%3A%2F%2Fiyourserver.com%2Fvideoupload%2Fsomevideo.mov” ;
wc.DownloadString(strUrl);
Once the call returns, then the video will have been placed in your S3 Bucket ready to be played back.
No more Apple-only videos!
Upload video from Phonegap to ASP.NET
If you’re uploading an image from Phonegap to a server, then it’s perhaps ok to just Base64 encode the image data and post it to the server, but when you you are dealing with Video, then you need something a little more efficient, which is where I started to take a look at the FileTransfer feature of Phonegap.
The best lesson I learned from this process, is to start with uploading an image from the photo gallery first, rather than diving headlong into the Video upload process. This is because you can run through the process in the simulator, giving you access to the debug console, so you can see any error details coming back from the server, otherwise, you can’t really see what’s going on.
So, let’s start with the server side, here’s my ASMX webservice:
<%@ WebService Language=”C#” Class=”WebService” %>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.IO;
[WebService(Namespace = “http://tempuri.org/”)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService {
public WebService () {}
[WebMethod]
public string UploadFile() {
string lreturn = “success”;
try
{
HttpPostedFile file = HttpContext.Current.Request.Files[“file”];
string saveFile = file.FileName;
string realPhysicalPath = Path.Combine(Server.MapPath(“videoUpload”), saveFile);
file.SaveAs(realPhysicalPath);
}
catch (Exception ex)
{
lreturn = “fail. ” + ex.Message;
}
return lreturn ;
}
}
The web.config configuration for this service is quite important, as follows:
<system.web>
<compilation debug=”true”/>
<customErrors mode=”Off”/>
<webServices>
<protocols>
<add name=”HttpGet”/>
<add name=”HttpPost”/>
</protocols>
</webServices>
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name=”Access-Control-Allow-Origin” value=”*” />
</customHeaders>
</httpProtocol>
</system.webServer>
This allows the webservice to be called with GET and POST, and the CORS support helps cross-domain access.
Then, the fun part of writing the app to upload video as follows (Slightly adapted from official docs)
<!DOCTYPE html>
<html>
<head>
<title>Capture Video</title><script type=”text/javascript” charset=”utf-8″ src=”cordova.js”></script>
<!–<script type=”text/javascript” charset=”utf-8″ src=”json2.js”></script>–>
<script type=”text/javascript” charset=”utf-8″>// Called when capture operation is finished
//
function captureSuccess(mediaFiles) {
var i, len;
for (i = 0, len = mediaFiles.length; i < len; i += 1) {
uploadFile(mediaFiles[i]);
}
}// Called if something bad happens.
//
function captureError(error) {
var msg = ‘An error occurred during capture: ‘ + error.code;
alert(msg, null, ‘Uh oh!’);
}// A button will call this function
//
function captureVideo() {
// Launch device video recording application,
// allowing user to capture up to 2 video clips
navigator.device.capture.captureVideo(captureSuccess, captureError, {limit: 2});
}// Upload files to server
function uploadFile(mediaFile) {var ft = new FileTransfer(),
path = mediaFile.fullPath,
name = mediaFile.name;
alert(“Attempting to upload:” + path);var op;
op = new FileUploadOptions();
op.fileName = name;
op.fileKey = “file”;ft.upload(path,
“http://yourserver.com/videoUpload.asmx/UploadFile”,
function(result) {
alert(‘Upload success: ‘ + result.responseCode);
alert(result.bytesSent + ‘ bytes sent’);},
function(error) {
alert(‘Error uploading file ‘ + path + ‘: ‘ + error.code);
},
op);
}</script>
</head>
<body>
<button onclick=”captureVideo();”>Capture Video</button> <br></body>
</html>
Now, the fun part, is that I just see that iOS uploads in Quicktime (MOV) format, which is not supported in-browser by Android.
webOS App Store closing November 1st, 2014
![]() |
| webOS Cloud Services to end January 15, 2015 |
| Cloud services support for webOS devices will end on January 15, 2015. We appreciate the effort that our developer community has contributed to the webOS platform. However, it has been more than three (3) years since the last device was sold. Since only a small fraction of the devices are still connecting to our cloud, the time has come to close the services.
The remaining webOS devices will continue to run after the cloud services are terminated. However, they will no longer be able to:
What this means to developers
|
Microsoft no longer routing it’s sales through Luxembourg
NOTICE – European Union VAT Changes Coming 1/1/2015
Tax laws in the European Union (EU), which govern the Value Added Tax (VAT) rate applied to business-to-consumer digital goods, are changing on 1/1/2015. This affects the VAT rate on content offered in the Windows and Windows Phone Stores. You may want to start thinking about how this change could impact your EU pricing decisions.
Beginning on 1/1/2015, the applicable VAT rate for paid business-to-consumer transactions for digital goods will change from 15% to the country-specific VAT rate.
All EU countries are Microsoft tax remit, which means the price you select in Dev Center for your app and/or in-app purchase is the final sale price to the customer and already includes applicable taxes. Microsoft then subtracts the taxes from the price prior to payout, and remits them on your behalf.
The table below shows the new VAT rates that will go in to effect on 1/1/2015.
|
Note: Tax rates are subject to change at any time. Microsoft cannot guarantee the accuracy of these rates. For definitive information, consult official EU sources.
Issue: Assembly outside lib folder. (NuGet)
NuGet seems to be a great way to get windows developers to use your code, it makes it easy to package up an assembly to be used in another project. Seconds after uploading, I started to get developers downloading my code.
Here was a problem that I hit when I tried to package my assembly, there may be a better solution, but this worked for me.
I created a boiler-plate NuSpec file from my DLL by running
nuget spec MyAssembly.dll
I had to open the nuspec file in notepad, and edited the fairly obvious fields, like URL description, etc. Then, I went to pack the nuspec and dll together with this command:
NuGet Pack YourPackage.nuspec
However, I then got a warning:
WARNING: 1 issue(s) found with package ‘xxxx.dll’.
Issue: Assembly outside lib folder.
Description: The assembly ‘xxx.dll’ is not inside the ‘lib’ folder
and hence it won’t be added as reference when the package is installed into a project.
Solution: Move it into the ‘lib’ folder if it should be referenced.
The nupkg file was created, and I uploaded it to nuget.org, however, when I tried to download this again, using
PM> Install-Package xxxxx.dll
Installing ‘xxxxx.dll 1.0.0’.
Successfully installed ‘xxxx.dll 1.0.0’.
There was no reference added to my project, so, I couldn’t access the assembly.
So, after reading a bit, I edited my nuspec file, and added this node in the metadata
<references>
<reference file=”xxxx.dll” />
</references>
created a lib folder, and copied the dll into it. – and changed the version number
I repacked, and re-uploaded the nupkg, and when I downloaded it again, I got a reference automatically added to my test project.
And it’s all live on https://www.nuget.org/packages/OfflineAdvertsLib.dll
Could not load type ‘System.Action’ from assembly ‘mscorlib, Version=3.7.0.0, Culture=neutral, PublicKeyToken=969DB8053D3322AC’.
When porting some code from Silverlight 4 to Windows Phone 7.1, I got an unusual error “Could not load type ‘System.Action’ from assembly ‘mscorlib, Version=3.7.0.0, Culture=neutral, PublicKeyToken=969DB8053D3322AC’.” – At this bit of code:
Deployment.Current.Dispatcher.BeginInvoke(someMethod);
The code is designed to run “someMethod” on the main UI Thread, so you don’t an illegal cross thread exception.
Invoking Dispatcher.BeginInvoke with a function name like this, is interpreted as an Action, rather than a delegate, so the solution is to use a delegate as follows:
private delegate void someMethodDelegate();
private static void SomeMethodCalledByBackgroundThread()
{
someMethodDelegate action = someMethod;
Deployment.Current.Dispatcher.BeginInvoke(action);
}
Although a little less easy to read, and it appears to have an extra level of indirection, this code works in both SL4 and WP7
Display Data URI Image in Silverlight (Windows Phone)
The data uri is a string based representation of an image, which is base-64 encoded, so it’s easy to store in Javascript, and pass it in Post data. It bloats the image size, so it isn’t an efficient format, but it’s certainly easy to handle.
Here is an example of how to render a image from a data URI in Silverlight – which should also be suitable for Windows Phone 7, 8, and 8.1 (Silverlight).
Here’s my XAML:
<Grid x:Name=”LayoutRoot” Background=”White” Loaded=”LayoutRoot_Loaded”>
<Image x:Name=”imgDisplay”></Image>
</Grid>
And this is the underlying C# code:
public static BitmapSource BitmapSourceForDataUri(Uri dataUri)
{
var dataString = dataUri.OriginalString;
var b64Start = dataString.IndexOf(“,”, StringComparison.Ordinal);
if (b64Start == -1) return null;
var base64 = dataString.Substring(b64Start + 1);
Stream stream = new MemoryStream(Convert.FromBase64String(base64));
var image = new BitmapImage();
image.SetSource(stream);
return image;
}private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
const string strDataUri =
“data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==”;
var bmp = BitmapSourceForDataUri(new Uri(strDataUri));
imgDisplay.Source = bmp;
imgDisplay.Width = bmp.PixelWidth;
imgDisplay.Height = bmp.PixelHeight;
}
Using Google Analytics in Phonegap apps.
If you use Phonegap, and want to know how many people use your app regularly, and where they come from, then Google Analytics, with a small modification, is great for this purpose. – But you need a slight modifiction to the normal tracking code.
Firstly, download the ga.js file from http://www.google-analytics.com/ga.js – open it in a text editor and look for the word file:, and replace it with _file then stick it into your www folder. make a reference to it from every page you want to track, then use the script:
<script type="text/javascript" src="ga.js"></script>
<script>
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-YOUR_ID_HERE']);
_gaq.push(['_setDomainName', 'none']);
_gaq.push(['_trackPageview', 'NAME_OF_PAGE']);
</script>
To get your UA-ID then you have to go to Google Analytics, create a new property – selecting “WEBSITE” not “APP”, and pick it out of the code.
To test it, then you run the app, and look at Google Analytics “Real time”, if you see activity appearing, then it’s working!
