Pages: 1 [2]   Go Down
Author Topic: Images over HTTP  (Read 1596 times)
0 Members and 1 Guest are viewing this topic.
Norwich, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 48
Web & Mobile Developer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Peter,
I said that I have an Ethernet shield and want to use an HTTP connection rather than USB. I can't get my PHP code to mimic that Procesing script (see code in first post) but I will try to first test a working image data file that was generated using the Processing sketch. I can upload this to my server and see if the Arduino can print. As you say - this would be a good test to do.

I am still most stuck trying to get the PHP script working - can you help me at all with that please?

Many thanks
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12631
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The (Processing?) code you included in the original post just seems to take an image consisting of a byte array with width/height attributes, and encode that as a line of text for each line of the image, with the line containing a comma separated sequence of hex values. Is that the format you need to output to your printer? If so, you need to convert your JPG image to a bitmap format and then encode it using the bit-map-to-text algorithm in the original post. I haven't done anything like that in PHP but Google suggests that PHP supports ImageMagick which enables you to access image attributes and pixels, so you should have access to get the pixel data used by your conversion algorithm.

I guess the scheme would be that your PHP web app saves the image file in a spool directory as you have already suggested, and a background thread detects the presence of the file, reads it and converts it into your textual format and uses an HTTP post or similar to push that chunk of ascii to the Arduino. The Arduino would send it on to the printer.

If you don't need the ability to spool images and print them in the background, you could simplify this and have the PHP web app encode the image to text within the HTTP request handler and perform the HTTP post or similar to get it printed. In this scheme you'd want to provide some sort of mutex in the PHP web app so that it only processes one image at a time.
« Last Edit: April 21, 2013, 04:57:12 pm by PeterH » Logged

I only provide help via the forum - please do not contact me for private consultancy.

Earth
Offline Offline
Edison Member
*
Karma: 52
Posts: 1782
My browser no longer is binding static IP, Floating is the way to go.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is my 2 cents;-

Plan A: Since OP make Processing+Arduino+Printer  works, here is the route
load Apache Tomcat at server and put Processing into server either head or headless. then write jsp wrapper for Processing code.

== BROWSER ==
Html5 canvas -> canvas.toDataURL -> ajax post base64encoded image to jsp server

== JSP SERVER ==
get post payload -> base64decoded -> Processing ->  log file on server -> sends this to Arduino

== Arduino ==
sends image to the thermal printer -> log print image file.

OP  finished 80%+ job, now just needed write jsp wrapper.
« Last Edit: April 23, 2013, 11:39:32 pm by sonnyyu » Logged

Earth
Offline Offline
Edison Member
*
Karma: 52
Posts: 1782
My browser no longer is binding static IP, Floating is the way to go.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

before we go through Plan B, few thing might need to review;-

1. use HTTP post, say no to HTTP get, the reason is HTTP get has size limit, only few K.
2. move all the cpu intensive task out of Arduino.
3. set up enough log/debug point.
4. no HTTP POST binary, post base64 only.
5. SD Card Shield for Arduino, for log  print image file.

Plan B: Apache php

== BROWSER ==
Html5 canvas -> canvas.toDataURL -> ajax post base64encoded image to php server

== Apache SERVER ==
get post payload -> base64decoded -> get width,height  ->  ImageMagick  convert to bitmap  -> save file on server( debug point) ->  open file on server -> base64encoded  -> cURL post width,height,base64 payload to Arduino

== Arduino web server ==
get post payload -> base64decoded  -> sends image to the thermal printer -> log print image file.


Html5 canvas PHP

Arduino-based Web Server library

Arduino base64 en/decode library
« Last Edit: April 23, 2013, 11:26:22 pm by sonnyyu » Logged

Dubuque, Iowa, USA
Offline Offline
Faraday Member
**
Karma: 46
Posts: 2500
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You can do all of what sonnyyu said smiley-roll or just use a PHP script like this:
Code:
<?php

header
('Content-Type: text/plain');

$url $_GET['url'];

/* Open the URL and create an image; change to "fromjpeg", "frompng", etc. as necessary */
$image imagecreatefromgif($url);

if (
$image) {
  
$height imagesy($image);
  
$width imagesx($image);

  print 
"URL: $url\n";
  print 
"Height: $height\n";
  print 
"Width: $width\n";

  
imagefilter($imageIMG_FILTER_GRAYSCALE);

  for (
$y 0$y <= $height$y++) {
    for (
$x 0$x <= $width$x++) {
      
$rgb imagecolorsforindex($imageimagecolorat($image$x$y));

      if (
$rgb['red'] > 88) {
        print 
"X";
      } else {
        print 
" ";
      }
    }
    print 
"\n";
  }
} else {
  print 
"Crap! Didn't load the image\n";
}

?>

Be warned that I'm a novice PHP programmer. Also, this requires the GD library but that should be default with any PHP install.

Try with a URL like:
http://www.mysite.com/myscriptname.php?url=http://arduino.cc/forum/Themes/arduinoWide/images/home_icon.gif

For output like:
Code:
URL: http://arduino.cc/forum/Themes/arduinoWide/images/home_icon.gif
Height: 11
Width: 9
XXXX XXXX
XXX   XXX
XX     XX
X       X
         
X XX    X
X XX    X
X       X
X       X
XXXXXXXXX

You'll want to adjust the output so it's more practical for reading it by the Arduino, but hopefully you get the idea how to manipulate the image pixel by pixel. Adjusting from a color image to black and white for the thermal printer is kinda tricky; you'll probably want to play with that part as well.
         
Logged

Norwich, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 48
Web & Mobile Developer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

sonnyyu, thank you for your thorough replies. I think your Plan B is best for me because I am sure I can do the first 2 steps easily (HTML Canvas / PHP Server). The main issue I have is getting the image data to print.

For the sake of testing (and because I am happy enough to code the HTML5 and PHP image handling) I can upload an image to my server and pretend this is the one generated from the canvas.

The section I am most stuck with is how to convert my image into a byte array. From what I can see, the processing script scans each row of pixels, and groups them into 8 bits. It then checks to see if these are black (or below a certain threshhold) and then sets the bit. This 8 pixel chunk is then output as a hexadecimal byte.

How can I duplicate this with PHP? I understand how to scan rows and columns - but I don't get the 8 pixel chunk going to the byte array (c++ byte array according to the code comments)

Once I can at least get PHP to dump out the correct byte array to the screen (and manually copy this into my sketch to print out) then I can focus on sending this data to the Arduino via HTTP POST

Thanks for everyone's help this far. I know I am so close to getting this working, but I lack a total understanding of bit / byta array coding
Logged

Earth
Offline Offline
Edison Member
*
Karma: 52
Posts: 1782
My browser no longer is binding static IP, Floating is the way to go.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

first before go through Plan B, We need Plan C - backup Plan. processing use Java image class to processing Image. we could easily wrote web service via tomcat, and tomcat will be very happily co-exist with apache server. Both have same father. Now your php code call tomcat web service. The job is done. If testing purpose you could even run it through command line. Your php code make system call, It is arguably but works. Plan C will be bought me some time as well.  smiley-wink

Let me think through correct method for Plan B. I need time!
Logged

Earth
Offline Offline
Edison Member
*
Karma: 52
Posts: 1782
My browser no longer is binding static IP, Floating is the way to go.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Now I know where you are stuck. the format of processing file.

Quote
...This 8 pixel chunk is then output as a hexadecimal byte.

if you see hexadecimal byte image file, then it is base-64 encoded, first you should decode it back to binary image file. Once you have binary image file you could test it with Adobe Photoshop or even download Imagemagick binary releases to identify file format. or upload it to Abode forum or java image forum to ask help.

Download Binary Releases http://www.imagemagick.org/script/binary-releases.php#windows

Command to identify "identify logo.gif"

known well about php image library - GD, ImageMagick, Gmagick. Since they support variant image file format.

after you go through all of above, but fail you still have Plan D and Plan E.

Plan D is using C++ to take care image byte array and write it as PHP extension.

Plan E is use php-java bridge.

if we are in same page, Arduino printing is single thread application, no con-current support is needed. the work around of Plan C is perfect here. Write java command line application is very easy, since you have logic complete. Might need few lines of java code.
then php make system call to command line.
« Last Edit: May 22, 2013, 11:36:49 am by sonnyyu » Logged

Norwich, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 48
Web & Mobile Developer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is all sounding really complex. I see2 main steps to test.

1. Converting an image into a byte array using PHP

2. Geting the Arduino to download this data and print it.

So firstly, I want to focus on step 1, and manually test the byte array. I am trying to print the data to the screen using PHP. The image (which would be created with the HTML5 canvas) is already uploaded.

Here are my example files

The image I want to convert: https://dl.dropboxusercontent.com/u/8396442/online/arduino/arduino.png
The correct byte array data: https://dl.dropboxusercontent.com/u/8396442/online/arduino/arduino.h
The original processing script: https://dl.dropboxusercontent.com/u/8396442/online/arduino/bitmapImageConvert.pde
The PHP script I have written so far: https://dl.dropboxusercontent.com/u/8396442/online/arduino/php.txt

I basically want to get to a point where the PHP script is able to output the data that you can see in the arduino.h file

I am sure that my PHP script is scanning the image in the same way as the Processing script - but I can't quite understand the bitwise operations, specifically how to convert this into PHP:

Code:
if((img.pixels[i++] & 1) == 0) sum |= b; // If black pixel, set bit

The img.pixels part returns a "Color" datatype: http://processing.org/reference/color_datatype.html

I know in PHP I can use imagecolorat($img,$x,$y); and this returns an array for RGBA

I am certain that once I can get this one line running as PHP then the first (and hardest part) of my project will be complete!

So basically, my question this far is how to convert that line of code into PHP?

Thanks for sticking with me on this one smiley-grin
Logged

Norwich, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 48
Web & Mobile Developer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

My best work happens after midnight smiley-wink

I realised that I needed to have a counter in my loop because I wasn't checking each pixel properly. This is the working PHP code. The image is fixed, but I can easily adapt this to read from a file input or from the HTML5 canvas. But anyway, I copied the output from the PHP script (from the browser screen) and copied the byte data into my Arduino sketch and it prints the image perfectly. I'm quite relieved to have worked it out. Have learnt a lot about bitwise operations!

Here's the working code:

Code:
<?php

$i 
0;
$n 0;

$imgPath "arduino.png";

$im imagecreatefrompng($imgPath);
imagefilter($imIMG_FILTER_GRAYSCALE);
imagefilter($imIMG_FILTER_CONTRAST, -100);

$height imagesy($im);
$width imagesx($im);


$rowBytes   floor(($width 7)/8);
$totalBytes $rowBytes $height;

// Image info
echo '<p>Image: '.$width.'x'.$height.'<br />';
echo 
$rowBytes.' rowBytes ('.$totalBytes.' total)';
echo 
'</p>';

echo 
'<pre>';

for(
$y=0;$y<$height;$y++) {
echo "<br />";
for($x=0$x<$rowBytes$x++) {
$lastBit = ($x $rowBytes 1) ? : (<< ($rowBytes $width));

$sum 0// Clear accumulated 8 bits
for($b=128$b>=$lastBit$b >>= 1) { // Each pixel within block...
$row floor($i/$width);
$col $i%$width;
$i++;

$rgb imagecolorat($im,$col,$row);
$rVal = ($rgb >> 16) & 0xFF;
$gVal = ($rgb >> 8) & 0xFF;
$bVal $rgb 0xFF;

if($rVal==0) {
$sum |= $b;
}
}
echo "0x".sprintf("%02X",$sum);

if(++$n $totalBytes) {
echo ",";
}
}
}

echo 
'</pre>';
?>

So step 2, is how to get that code onto the Arduino and into a variable that I can pass to the printer function? I actually need to pass 3 values in the HTTP POST. The image width, the height and also the image data.

This should be the easy bit !
Logged

Norwich, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 48
Web & Mobile Developer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've finished an HTML canvas drawing tool and this now saves the byte array to my server (into a text document for now).

My Arduino Ethernet shield doesn't have the SD card header - a friend of mine said I could have to stream the data to the printer if the images were too large.

To get the basics working - I need to work out how to download this data to the Arduino memory and them print it. Can anyone offer any tips or advise? Most of the examples I have found tend to save to the SD card first (which I don't have).

Perhaps it's too simple, but can I simply read the bytes into a char* and then pass this to the Thermal.printBitmap()?
Logged

Norwich, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 48
Web & Mobile Developer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just bumping this thread. I can retrieve the byte array into my serial monitor (using Ethernet librar and client.read()), but not sure of 2 things:

1. How to ignore the HTML header and other crud and store the image into a variable

2. How to pass the byte array as a stream into printBitmap (for larger images)

Any pointers to help get me started would be most helpful.

Thank you
Logged

Norwich, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 48
Web & Mobile Developer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

My image conversion works correctly - I have tested this by manually copying the output from my server into the Arduino sketch and it prints correctly (see PHP code in my earlier post). My current sketch is able to dump the output from the server (the image data) into the serial monitor. I don't know how to read this data into a string/array and then pass that to the printBitmap() function:

https://github.com/adafruit/Adafruit-Thermal-Printer-Library/blob/master/Adafruit_Thermal.cpp
« Last Edit: May 28, 2013, 06:36:41 pm by Alex Holsgrove » Logged

Pages: 1 [2]   Go Up
Jump to: