1

I'm new to C#, and I'm currently working with this piece of code:

//Take a snapshot from left camera and save to current directory as "snapshot.png"
            case Key.Z:
                int left = camLeft.Device.LensCorrection1;
                camLeft.Device.LensCorrection1 = 0;
                Thread.Sleep(150);
                BitmapSource bmpSource = camLeft.Device.BitmapSource as BitmapSource;
                MemoryStream ms = new MemoryStream();
                BitmapEncoder encoder = new PngBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bmpSource));
                encoder.Save(ms);
                ms.Seek(0, SeekOrigin.Begin);

                System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(ms);
                string filepath = Environment.CurrentDirectory;
                string fileName = System.IO.Path.Combine(filepath, @"snapshot.png");
                bitmap.Save(fileName, ImageFormat.Png);
                bitmap.Dispose();
                camLeft.Device.LensCorrection1 = left;
                break;

This is code developed for a camera that, on button press, takes a snapshot and stores it as a png file. This alone works--but what I'm trying to do is have it also take the image data and automatically send it to a PHP webpage that automatically takes in the data and displays the image (bypassing having to store it in a MySQL server). I want this to all work with a single button press--from snapshot being taken, to it all uploading to the webpage to be viewed.

So here's what the above code looks like with the new, problematic/not working code inserted in between the space in the above code:

//Take a snapshot from left camera and save to current directory as "snapshot.png"
            case Key.Z:
                int left = camLeft.Device.LensCorrection1;
                camLeft.Device.LensCorrection1 = 0;
                Thread.Sleep(150);
                BitmapSource bmpSource = camLeft.Device.BitmapSource as BitmapSource;
                MemoryStream ms = new MemoryStream();
                BitmapEncoder encoder = new PngBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bmpSource));
                encoder.Save(ms);
                ms.Seek(0, SeekOrigin.Begin);

                byte[] imageBytes = ms.ToArray();
                string base64 = ImageToBase64(imageBytes);
                string base64Encoded = HttpUtility.UrlEncode(base64);
                WebClient client = new WebClient();
                client.UploadString("www.thisismydesiredurl.com", base64Encoded);                    
                System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(ms);
                string filepath = Environment.CurrentDirectory;
                string fileName = System.IO.Path.Combine(filepath, @"snapshot.png");
                bitmap.Save(fileName, ImageFormat.Png);
                bitmap.Dispose();
                camLeft.Device.LensCorrection1 = left;
                break;

The ImageToBase64 is a method that converts the image to base64, as implied:

public string ImageToBase64(byte[] imageBytes)
    {
            // Convert byte[] to Base64 String
            string base64String = Convert.ToBase64String(imageBytes);
            return base64String;            
    }

The additional code is meant to take the image, convert it into bytes, the convert it into base64, then upload the string via a POST method to a PHP page ready to receive the data. The PHP page then has the following code that's meant to decode and display the image:

<?php
$data = $_POST['base64Encoded'];
$decodedata = urldecode($data);
$rawdata = base64_decode($decodedata);
$source = imagecreatefromstring($rawdata);
?> 

<img src= "<?php echo $source ?>" alt="test"/>

But it's not working--no image is displayed, but I know the page is up. What am I missing?

I'm also open to easier/alternate solutions I may not know about. All I want is to have this image automatically viewable on a definite URL with a single button press--that's all.

Edit: The answer provided below "works", but I always get a broken image on my website--so it seems like the image is being uploaded and sent to the website, it's just not being encoded/decoded correctly. Can't seem to figure out why, either. Thoughts?

user3687873
  • 11
  • 1
  • 5

1 Answers1

5

the way you are doing it, it's never going to work. When you make a HTTP POST, the server side scripting is meant to handle it and give you an output. However, that same output will not be visible when you visit the script outside of the http post request.

What you will need to do is post the data to your image upload script. That script should save the file on server and display it.

for example:

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Drawing;
using System.Collections.Specialized;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            // Load a image
            System.Drawing.Image myImage = GetImage("http://personal.psu.edu/tao5048/JPG.jpg");

            // Convert to base64 encoded string
            string base64Image = ImageToBase64(myImage, System.Drawing.Imaging.ImageFormat.Jpeg);

            // Post image to upload handler
            using (WebClient client = new WebClient())
            {
                byte[] response = client.UploadValues("http://yoursite.com/test.php", new NameValueCollection()
                {
                    { "myImageData", base64Image }
                });

                Console.WriteLine("Server Said: " + System.Text.Encoding.Default.GetString(response));
            }

            Console.ReadKey();
        }

        static System.Drawing.Image GetImage(string filePath)
        {
            WebClient l_WebClient = new WebClient();
            byte[] l_imageBytes = l_WebClient.DownloadData(filePath);
            MemoryStream l_stream = new MemoryStream(l_imageBytes);
            return Image.FromStream(l_stream);
        }

        static string ImageToBase64(System.Drawing.Image image, System.Drawing.Imaging.ImageFormat format)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                // Convert Image to byte[]
                image.Save(ms, format);
                byte[] imageBytes = ms.ToArray();

                // Convert byte[] to Base64 String
                string base64String = Convert.ToBase64String(imageBytes);
                return base64String;
            }
        }
    }
}

PHP test.php

<?php 

// Handle Post
if (count($_POST))
{
    // Save image to file
    $imageData = base64_decode($_POST['myImageData']);

    // Write Image to file
    $h = fopen('test.jpg', 'w');
    fwrite($h, $imageData);
    fclose($h);

    // Success
    exit('Image successfully uploaded.');
}

// Display Image
if (file_exists('test.jpg'))
{
    echo '<img src="test.jpg" />';
}
else
{
    echo "Image not uploaded yet.";
}

?>

Output of C# app is:

enter image description here

After the image was uploaded, if you visit http://yoursite.com/test.php (for example) in browser, this is what you see (i.e. the uploaded image from c#, saved on server, being served back):

enter image description here

Hope this helps.

Latheesan
  • 23,247
  • 32
  • 107
  • 201
  • if the image changes often this solution would introduce browser caching problems. – j_mcnally May 29 '14 at 16:09
  • 1
    if the image changes often, caching can be avoided like this: `echo '';` (i.e. set the image src url with the file modified timestamp on it), which produces HTML like this: `` – Latheesan May 29 '14 at 16:13
  • Thanks very much for the suggestion; I'll try implementing it now, but the first thing is that C# doesn't seem to want to recognize System.Drawing.Image. – user3687873 May 29 '14 at 18:51
  • Okay, I fixed that; now it's uploading properly and the code builds, the next problem is that the image uploaded to the website is a "broken" image--but it's still progress! – user3687873 May 29 '14 at 19:41