Archive

Archive for October, 2014

A Hello World example for Foundation Reveal

Foundation is a Javascript / CSS framework similar to Bootstrap, and I was looking at the Reveal plugin to create modal dialogs, but dismayed when there was no really simple “hello world” example.

First, download Foundation “complete”, and then create a HTML file with this content

<html>
<head>
<link href=”css/foundation.css” rel=”stylesheet” />
<script src=”js/vendor/modernizr.js”></script>
<script src=”js/vendor/jquery.js”></script>
<script src=”js/foundation/foundation.js”></script>
<script src=”js/foundation/foundation.reveal.js”></script>
</head>
<body>

<a href=”#” id=”btnJoin” >Join</a>

<div id=”dialogPage” class=”reveal-modal” data-reveal>
<h2>Alert</h2>
<p id=”pMessage”></p>
<a class=”close-reveal-modal”>×</a>
</div>

<script>
$(init);
function init()
{
$(document).foundation();
$(“#btnJoin”).bind(“click”, btnJoin_click);
}

function btnJoin_click()
{
jqmAlert(“Hey, I’m an alert”);
}

function jqmAlert(message)
{
console.log(“jqmAlert(” + message + “)”);
$(“#pMessage”).html(message);
$(‘#dialogPage’).foundation(‘reveal’, ‘open’);
}
</script>
</body>
</html>

Categories: Uncategorized

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…

Categories: Uncategorized

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&#8221;, “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.

Categories: Uncategorized

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?&#8221;;
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!

Categories: Uncategorized

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/&#8221;)]
[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&#8221;,
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.

Categories: Uncategorized

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:

  • Download new apps or updates. The HP App Catalog will be unavailable after the shutdown
  • Backup or restore devices from the cloud
  • Setup new devices
  • Recover lost passwords

What this means to developers

  • As of the date of this announcement, no new apps can be submitted to the HP App Catalog
  • You can submit updates to the HP App Catalog until November 10, 2014
  • Sales will be allowed until November 1st, 2014 in order to give users ample time to access apps prior to the shutdown. Note that the front page of the HP App Catalog will have an announcement about the impending shutdown
  • Developers will need to access the Developer Portal before it is shut down on January 15, 2015, to access and download final sales reports, etc.
  • Final developer payouts are expected to be made by February 15, 2015
Categories: Uncategorized

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.

EU Country VAT rate
before
1/1/2015
VAT rate
after
1/1/2015
EU Country VAT rate
before
1/1/2015
VAT rate
after
1/1/2015
Austria 15% 20% Italy 15% 22%
Belgium 15% 21% Latvia 15% 21%
Bulgaria 15% 20% Lithuania 15% 21%
Croatia 15% 25% Luxembourg 15% 15%
Cyprus 15% 19% Malta 15% 18%
Czech Republic 15% 21% Netherlands 15% 21%
Denmark 15% 25% Poland 15% 23%
Estonia 15% 20% Portugal 15% 23%
Finland 15% 24% Romania 15% 24%
France 15% 20% Spain 15% 21%
Germany 15% 19% Slovakia 15% 20%
Greece 15% 23% Slovenia 15% 22%
Hungary 15% 27% Sweden 15% 25%
Ireland 15% 23% UK 15% 20%

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.

Categories: Uncategorized