I am trying to send the contents of a bitmap as as byte array to a server to be re-constituted as a jpeg. The php file creates a jpg from known good data and it’s also receiving my bad data fine. so the problem seems to be the data format i’m outputting from the roku.
GetByteArray returns pixels (color values), not JPEG data, so if your server is expecting to be passed a JPEG encoded data blob it isn’t going to work.
Also, even if the server accepted an RGBA bitmap, the server is doing a base64 decode so you would need to do a base64 encode on the Roku before sending it. That’s why your data doesn’t look like the sample data.
“RokuMarkn” wrote:
Also, even if the server accepted an RGBA bitmap, the server is doing a base64 decode so you would need to do a base64 encode on the Roku before sending it. That’s why your data doesn’t look like the sample data.
–Mark
OK, so what is this
strx=thispainting.ToBase64String()
doing then? Is it not an encode?
KC - So is this php
$im = imagecreatefromstring($data);
expecting jpeg encoded data? Because you can do either imagejpeg(’ ‘) or imagepng(’ ') after this to make a file.
Either one of you care to make a suggestion on how I might make it work?
Sorry, I didn’t notice the encode. But the $data= line you quoted doesn’t look like it was printed on the Roku. That looks like piece of PHP code. However if the string in quotes is what the Roku is printing, then it’s fine. It’s a valid base64 string representing 25 words of &hABABABFF.
I’ve never used it but according to the PHP doc, imagecreatefromstring accepts JPEG, PNG, GIF, WBMP, and GD2. There may be some tools on your server that would help convert a raw bitmap to one of those file types.
expecting jpeg encoded data? Because you can do either imagejpeg(’ ‘) or imagepng(’ ') after this to make a file.
I can only guess about the PHP code. FWIW your example good $data appears to be PNG file data.
You might look into whether the server can accept raw pixel data, in which case I imagine you would also need to pass the dimensions.
Or BMP format, which is also fairly easy to generate a header for it followed by the pixel data.
Is your intent to send a full screen image, at 1280 x 720? Or just a small part of it?
If you are sending a full screen image, without compression it would be pretty big (3.5 MB?).
It seems what you really want is a Roku 2D API that gives you PNG or JPEG output, but that is not available.
“RokuMarkn” wrote:
Sorry, I didn’t notice the encode. But the $data= line you quoted doesn’t look like it was printed on the Roku. That looks like piece of PHP code.Mark
Well i just copied what the roku printed from the console and enclosed it with data=’ and '; . At this point i’m just pasting the data into the php file its easier then sending it each time until it works.
“RokuKC” wrote:
It seems what you really want is a Roku 2D API that gives you PNG or JPEG output, but that is not available.
You sure hit that nail on the head.
“RokuKC” wrote:
Is your intent to send a full screen image, at 1280 x 720? Or just a small part of it?
If you are sending a full screen image, without compression it would be pretty big (3.5 MB?).
Yea, thats the end game. It wouldn’t happen often. I have a function that makes a decent “painting” out of a photgraph. It would have a lot more promise if i could get the silly image out of the Roku.
Either one of you care to make a suggestion on how I might make it work?
I’m not a PHP developer, but spurred by Mark’s comment looked at PHP docs briefly…
Looks like if you had to, on the server you could do $img = imagecreatetruecolor( $w, $h ) to allocate an image buffer,
then walk over all the pixels and set them from the input pixel data using imagesetpixel.
I imagine there may be more efficient approaches though, browsing PHP docs or internet search may provide options.
“RokuKC” wrote:
Looks like if you had to, on the server you could do $img = imagecreatetruecolor( $w, $h ) to allocate an image buffer,
then walk over all the pixels and set them from the input pixel data using imagesetpixel.
I imagine there may be more efficient approaches though, browsing PHP docs or internet search may provide options.
Well I got this working to some degree. I used KC’s suggestion about imagesetpixel. The size limit seems to about 350 x 350 at this point, not sure if my servers POST data limit is affecting that but i’m checking, also switching to base64 from the hex string I’m using now would save 40% on the number of characters sent.
The server builds the .jpg at that size pretty fast, as fast as i can refresh my ftp app once the Roku says its sent.
I will say it feels pretty ridiculous to be doing it this way, with pony-express era technology, almost as ridiculous as having to record my own Roku sounds when they are already in the box.
Please Roku implement this feature, just because you all can’t see a good reason for some feature, doesn’t mean someone else can’t. Everyone wins if you just make things available.
at this point, 360 x 360 seems to be the limit. KC, Mark - is there a limit to the string size the Roku will output? I say this because it takes several seconds for URL transfer to send the file (roku3) but the server builds 360x360 immediately, and won’t do anything at 370x370. There are no size limits in the PHP file and I’ve upped the server limits for time and memory way beyond what is needed.
Just a thought … instead of using all that encoding and decoding and bases and hexes and stuff, could you just write your roByteArray to a tmp file using ifByteArray.WriteFile, then send the file to your server using ifUrlTransfer.AsyncPostFromFile?
Then your server can read all the bits and bytes from the file without having to decode anything:
“belltown” wrote:
Just a thought … instead of using all that encoding and decoding and bases and hexes and stuff, could you just write your roByteArray to a tmp file using ifByteArray.WriteFile, then send the file to your server using ifUrlTransfer.AsyncPostFromFile?
That seems like a good idea that I can get to later once I can write the whole file - One problem is I actually know very little about PHP ( i just had to look up stream_copy_to_stream, as i did with imagesetpixel when KC mentioned it), although I’ve used it for years on my website, so if i get something working there is usually another big problem to deal with rather then optimizing as I go along, which is certainly the case here. This is the script thats building the jpeg from the POST data which I cobbled together from different examples and some guessing.
One thing about the whole decoding thing, when i started this I first printed the bytearray as an ascii string to the console, and it didnt even look like a recognizeable anything - question marks and space was all I saw, probably doing something wrong, but at least hex values make sense to me and as you see above easily decoded, maybe easier then if i had the separate RGB values to deal with?
I was able to create a 720x480 byte array containing a bitmap of the French flag, send the byte array to my server, which in turn converted it to a jpg file, which I then displayed on my screen.
Sub Main ()
width = 720
height = 480
owner = "sqwiril"
' Make an image of the French flag and convert to an roByteArray
byteArray = MakeByteArray (width, height)
' Send the byte array to the server for conversion to a jpg file
Convert (byteArray, owner, width, height)
' Display the image
Display (owner)
End Sub
Function MakeByteArray (width As Integer, height As Integer) As Object
byteArray = CreateObject ("roByteArray")
byteArray.SetResize (width * height * 4, False)
i = 0
For x = 0 To height - 1
For y = 0 To width - 1
If y < CInt (width / 3)
r = 0 : g = 0 : b = 255 : a = 255
Else If y < CInt (width * 2 / 3)
r = 255 : g = 255 : b = 255 : a = 255
Else
r = 255 : g = 0 : b = 0 : a = 255
EndIf
byteArray [i + 0] = r
byteArray [i + 1] = g
byteArray [i + 2] = b
byteArray [i + 3] = a
i = i + 4
End For
End For
Return byteArray
End Function
Function Convert (byteArray As Object, owner As String, width As Integer, height As Integer) As Void
' Convert the byte array to a file
byteArray.WriteFile ("tmp:/byteArray")
' Send file to server
ut = CreateObject ("roUrlTransfer")
port = CreateObject ("roMessagePort")
ut.SetPort (port)
ut.SetUrl ("http://belltown.tk/bigimage.php?owner=" + owner + "&sizew=" + width.ToStr () + "&sizeh=" + height.ToStr ())
If Not ut.AsyncPostFromFile ("tmp:/byteArray")
Print "AsyncPostFromFile failed"
Stop
EndIf
msg = Wait (0, port)
If msg = Invalid
Print "Image upload timed out"
Stop
Else If Type (msg) <> "roUrlEvent"
Print "Unknown event"
Stop
Else If msg.GetResponseCode () <> 200
Print "Http Failure"; msg.GetResponseCode ()
Stop
Else
Print "File upload successful"
EndIf
End Function
Function Display (owner As String) As Void
url = "http://belltown.tk/" + owner + ".jpg"
ui = CreateObject ("roImageCanvas")
port = CreateObject ("roMessagePort")
ui.SetMessagePort (port)
ui.SetRequireAllImagesToDraw (True)
ui.SetLayer (0, {Url: url})
ui.Show ()
Wait (0, port)
End Function
I also tried it with a 1280x720 image – and did a base64 encode/decode to make the transfer size smaller. That worked as well, although it can take a while to upload a bitmap that large depending on your internet connection speed.
Vive La belltown! (sorry if that should be a le not la, my french is worse than my php) Thanks for all that. I just got it to work - very good lesson here about error handling. Because you are a professional and I only play one on TV, you did the thing pros do which is to put error handling into the URLtransfer thingie which allowed me to see i was getting a 413 error ( which may have been the problem yesterday) and so i was able to contact the server folks and they just yelled at the hamster on my server rack and fixed it, so now i see the ‘tricolour’ on my TV. Also thanks for the ImageMajik code, i do have that installed and will be using it to profile the image when i get to that part. Thanks again for your help.
imagejpeg has an optional third parameter to specify the image quality. Tweaking that value might give similar results to imagemagick, though of course no reason to do that if you’re happy with the current implementation.
“RokuMarkn” wrote:
imagejpeg has an optional third parameter to specify the image quality. Tweaking that value might give similar results to imagemagick, though of course no reason to do that if you’re happy with the current implementation.
–Mark
Yea, plus Imagmajik has two things which are pretty much necessary - color profiling and bluring to de-jaggie the image.
Also I tried using base64 and it was NOT a help, it consistently took maybe 15% longer to send the string on my test image. It would make sense since the hex string always uses 8 characters to describe a pixel, the base64 sometimes uses only 4, but more often than not uses 10.
Either way if Roku would like to add the ability to at least URLtransfer a bitmap thats - you know - already created - i won’t stop them.
“squirreltown” wrote:
Either way if Roku would like to add the ability to at least URLtransfer a bitmap thats - you know - already created - i won’t stop them.
I’d prefer, and have requested multiple times, the ability to create a PNG on the device from an roBitmap. The libraries are already there, so it shouldn’t require a major update, but to date, it doesn’t seem to have gained any traction.