Share Your Pride With Twilio MMS and Pridefy.com

July 02, 2015
Written by

PrideFy

Last week, the Supreme Court gave us a fantastic reason to celebrate, legalizing gay marriage in the U.S. At Twilio HQ, we celebrated alongside our friends and co-workers, in spirit with hundreds of thousands of men and women across the country and abroad.

Twitter put out a super easy way to add the signature rainbow heart to your tweet with the hashtag #LoveWins. Facebook offered an easy to add a rainbow photo filter on your profile picture. Now, Abe Diaz created another way you can show your pride.

Using Twilio MMS, you can text in any photo to 415 360 2438 and Abe’s service PrideFy will send you that photo back with a rainbow filter added.

PrideFyPhoto

We’re happy (and humbled) to syndicate Abe’s post below. Check out the original post on Abe’s blog here.

Sharing Your Pride via Twilio MMS with PrideFy

Inspired by the decision of the Supreme Court of the United States to declare same sex marriage a constitutional right and the celebratepride tool that Facebook launched on that same day, I decided to create an MMS ( Twilio powered) version of the same for those who (and I’m not sure why) do not have a Facebook account yet. Here are the steps I followed to make this happen; if you want to see the demo go to Pridefy.com

Step 1: Change Opacity
First I needed to find a way to change the opacity of the rainbow flag; a 50% seemed like the right choice here but I made this option part of the input for the method, just in case you want to play with this in the future. Check this article for some more details into this.

public static Bitmap ChangeOpacity(Image img, float opacityvalue)
        {
            Bitmap bmp = new Bitmap(img.Width, img.Height);
            Graphics graphics = Graphics.FromImage(bmp);
            ColorMatrix colormatrix = new ColorMatrix();
            colormatrix.Matrix33 = opacityvalue;
            ImageAttributes imgAttribute = new ImageAttributes();
            imgAttribute.SetColorMatrix(colormatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
            graphics.DrawImage(img, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, imgAttribute);
            graphics.Dispose();  
            return bmp;
        }

I tried this method and got some results, but not quite what I wanted. See what I mean here:

output1

Background Image with Overlay at 50%
 

Step 2: Scale Image

I wanted like the rainbow flag to cover the whole image, So I tried making both images the same size and this is what I got:

output2

Stretched with Uniform Ratios

This didn’t turn out like I wanted it. I needed to scale the image using ratios horizontally but needed to retain the same vertical height.

public static Image ScaleImage(Image image, int maxWidth, int maxHeight)
{
var ratioX = (double)maxWidth / image.Width;
var ratioY = (double)maxHeight / image.Height;
var ratio = Math.Min(ratioX, ratioY);
 
var newWidth = (int)(image.Width * ratio);
var newImage = new Bitmap(newWidth, maxHeight);//
Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, maxHeight);//
return newImage;
}

Check the results now:

output3

Step 3 – Putting it all together for Image Manipulation

When I receive an MMS message what I get is not the actual file (binary) but a link to the media file in Twilio’s servers. Therefore I needed to do a webrequest to get the media file (this is the MediaUrl0 parameter). I grabbed the flag image from a public Flickr url.

private static Image CreateBlendedImage(string backgroundimageurl)
{
Image imageBackground;
Image imageOverlay;
var request = WebRequest.Create(backgroundimageurl);
using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
{
imageBackground = Bitmap.FromStream(stream);
}
var request2 = WebRequest.Create("http://c1.staticflickr.com/1/286/19041020628_2657a057cc_k.jpg"); //Rainbow Flag
using (var response2 = request2.GetResponse())
using (var stream2 = response2.GetResponseStream())
{
imageOverlay = Bitmap.FromStream(stream2);
}
 
imageOverlay = ChangeOpacity(imageOverlay, 0.5F);
imageOverlay = ScaleImage(imageOverlay, imageBackground.Width, imageBackground.Height);
imageOverlay = imageOverlay.GetThumbnailImage(imageBackground.Width, imageBackground.Height, null, IntPtr.Zero);
 
Image img = new Bitmap(imageBackground.Width, imageBackground.Height);
using (Graphics gr = Graphics.FromImage(img))
{
gr.DrawImage(imageBackground, new Point(0, 0));
gr.DrawImage(imageOverlay, new Point(0, 0));
}
return img;
}

I then do the scaling, overlay and return the (in memory) image to the main controller.

Step 4 – The MMS Controller

I created an MVC controller to handle the incoming images and return back TwiML markup (Note: This controller must inherit from TwilioController in order to be able to send that TwiML markup back). You can do the same with a WebAPI controller, Node, etc. I just went for simple here

The same way that Twilio sends images via MMS, I needed to send them back; this means I had to save the image somewhere and then send the URL to that media file back. To do this I used Azure Blob Storage; again nothing fancy here, check this tutorial for a quick how to. I created a container for my images,created a blob and uploaded the image to that blob.

//Reminder this class needs to inherit from TwilioController --> public class MMSController : TwilioController
public ActionResult Index(string from, string mediaurl0)
{
Image blended = CreateBlendedImage(mediaurl0);
//We are using Azure Storage, and loading our credentials from our config file
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["<CONNECTIONKEY>"].ToString());
// Create the blob client
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference("<CONTAINERNAME>");
//Allow public access to the blob (but not to the container)
container.SetPermissions(new BlobContainerPermissions {PublicAccess = BlobContainerPublicAccessType.Blob });
// Create the container if it doesn't already exist.
container.CreateIfNotExists();
// Retrieve reference to a blob names using the from phone number.
//We add the png file extension so its easier for us when looking at a list of blobs
CloudBlockBlob blockBlob = container.GetBlockBlobReference(from + ".png");
// Create or overwrite the phone mumber blob with contents from a local file.
//We re using temp file space for file creation
var filepath = System.IO.Path.GetTempFileName();
blended.Save(filepath, ImageFormat.Png);
//remmeber to set the Content Type, else Azure will return appliction/octet and Twilio won't be able to read the image
blockBlob.Properties.ContentType = "image/png";
//Upload the file to Azure storage
blockBlob.UploadFromFile(filepath, FileMode.Open);
//Create th Twilio TwiML markup response
var response = new TwilioResponse();
string[] mediaurls = new string[1];
//For some reason only http worked for me
mediaurls[0] = blockBlob.Uri.AbsoluteUri.Replace("https://","http
//Add the Blended Image URL from Azure to the response
response.Message(mediaurls);
//Note how we return a TwiML respone and not a View
return TwiML(response);
}

Warning: don’t forget to set the Content-Type for the blob, failure to do this will serve the blob as “application/octet” which Twilio won’t be able to handle.

Hopefully you enjoyed this little project, I surely did. Feel free to reach out if you have any questions with this demo.