I need your help.
I was creating an application in c# that converts the data from the IP camera to an image (JPEG).
I was able to convert the image using the below code:
hex = "FFD8FFDB008400130D0F1.........";/// supply this with the attached hex dump.
byte[] image = HexString2Bytes(hex);
File.WriteAllBytes("visio.png", image);
Process.Start("visio.png");
private static byte[] HexString2Bytes(string hexString)
{
int bytesCount = (hexString.Length) / 2;
byte[] bytes = new byte[bytesCount];
for (int x = 0; x < bytesCount; ++x)
{
bytes[x] = Convert.ToByte(hexString.Substring(x * 2, 2), 16);
}
return bytes;
}
Sometimes I get a better image as expected:https://ibb.co/pxrwn6p
but sometimes I get a distorted image after converting https://ibb.co/9twx5ZT.
I was wondering if there is a problem with the conversion or the way I save the image.
because as per the supplier what I need to do is to directly save the image from the stream.
but since I receive it as a byte and I still need to convert it maybe there is something wrong with my codes.
the image also starts with ÿØÿÛ FF D8 and ends with ÿ Ùÿÿÿÿ (FF D9 FF FF FF FF)
here's the hex dump from their sample app:
https://drive.google.com/file/d/1CMlQ0xaVjM0jfU5A4MB-_HwK54dUMTOr/view?usp=sharing
using their test application the image can be captured and converted the image perfectly.
captured image using their application:https://ibb.co/2KgyLTc
using the hex from the sniff and convert it using my code:
converted image using my code:https://ibb.co/G0WMjht
sample source code:
please bare with my codes because currently this is only my test app before integrating this feature to another app.
https://drive.google.com/file/d/1Ux7zsR39IVNyd1wrBxQPQKA6yM4YnwJN/view?usp=sharing
Thank You in advance.
Looking at the hex-dump it looks like some kind of XML file with embedded image data. Trying to convert this directly to an image will most likely not work, you would need to parse the XML-data to extract the actual image file. But it looks like you have a valid Jpeg header, so I would guess you have found the start of the image at least. But you probably also need to check the length property from the XML-data to find the length of the image-data block.
However, the datablock looks like it contains large sections of zeros, this should not be present in a jpeg file, so it might indicate some data corruption. Possibly from the way the network data is captured.
I would expect cameras to use some higher level protocol than raw TCP. Like Real Time Streaming Protocol, GigE vision, or mjpeg over http. I have not seen any camera that require you to process a raw TCP streams. But since you do not show how the data is fetched it is difficult to tell if there is any mistakes in that code.
Related
I am creating a photo editing app for my c# project. I need to support different image formats, but to begin with, I chose a very simple format - PNM. At the moment, I can open PNM images and change the color scheme, but strange things happen when saving. When saving the image on macOS, everything works fine, but after trying a similar action on Windows, I got a strange effect, the colors were read with a shift of 1 byte with each new opening after saving.
Here is an example of an image:
example image
That’s what is happening after loading and re-opening it on Windows:
damaged image
It is logical to assume that the problem is in the methods of saving the image. I first write the entire file header to the stream, and then write the color bytes one by one.
I can't figure out what exactly the problem is, because when debugging, the array of bytes being written contained nothing extra. Opening the image in the notepad before and after saving, I did not find any visible changes.
Here is my implementation of saving in a file:
public void SaveTo(Stream stream)
{
_filter.WriteHeader(stream, _image);
foreach (var (x, y) in _enumerationStrategy.Enumerate(Width, Height))
{
var triplet = _image[x, y];
_filter.Write(stream, triplet, _converterProvider.Converter);
}
}
public void WriteHeader(Stream stream, IBitmapImage image)
{
var builder = new StringBuilder();
builder.AppendLine("P6");
builder.AppendLine($"{image.Width} {image.Height}");
builder.AppendLine("255");
var header = builder.ToString();
var headerBytes = Encoding.UTF8.GetBytes(header);
stream.Write(headerBytes, 0, headerBytes.Length);
}
I tried to create a header of image without a string builder, and I tried to write the header to the stream in different ways. Trying different encodings to convert bytes didn't work out too. The effect is the same...
I guess your issue is caused by inconsistent line endings between operating systems. When you use AppendLine it adds a \n character after your string which is translated to binary differently, depending on the OS you running.
I suggest you to write a line ending directly like so:
builder.Append((char)10);
I want to get a screenshot into c# using adb without saving files to the filesystem all the time.
I'm using the SharpAdbClient to talk with the device.
I'm on a windows platform.
This is what i got so far:
AdbServer server = new AdbServer();
StartServerResult result = server.StartServer(#"path\to\adb.exe", restartServerIfNewer: false);
DeviceData device = AdbClient.Instance.GetDevices().First();
ConsoleOutputReceiver receiver = new ConsoleOutputReceiver();
AdbClient.Instance.ExecuteRemoteCommand("screencap -p", device, receiver);
string str_image = receiver.ToString().Replace("\r\r", "");
byte[] bytes = Encoding.ASCII.GetBytes(str_image);
Image image = Image.FromStream(new MemoryStream(bytes));
I can successfully load both str_image, and create the byte array but it keeps saying System.ArgumentException when trying to load it into an Image.
I also tried saving the data to a file, but the file is corrupt.
I tried both replacing "\r\r" and "\r\n", both same result.
Anyone has some insight in how to load this file?
It's actually preferred if it could be loaded into a Emgu image since i'm gonna do some CV on it later.
One possible cause is the nonprintable ASCII characters in the string.
Look at the code below
string str_image = File.ReadAllText("test.png");
byte[] bytes = Encoding.ASCII.GetBytes(str_image);
byte[] actualBytes = File.ReadAllBytes("test.png");
str_image is shown in the below screencap, note that there are some non-printable chars (displayed as question mark).
The first eight bytes of a PNG file are always
137 80 78 71 13 10 26 10
While you read the console output as a string, then use ASCII to encode the string, the first byte becomes 63 (0x3F), which is the ASCII code for a question mark.
Also note that the size of the two byte arrays vary hugely (7828/7378).
And other thing is you are replace "\r\r", while actually a new line character in Windows is "\r\n".
So my conclusion is some image data is lost or modified in the output redirection by the ConsoleOutputReceiver, and you cannot recover the original data from the output string.
I have a device which is sending RGB32 encoded color image frames as byte arrays at 30 FPS.
I'd like to send these frames to the browser in the most performant manner possible via a websocket connection.
I'm assuming that the best way to get the image data through the websocket is as a base64 string that I interpret as a URI in the browser, but base64 encoding raw RGB32 data obviously doesn't work, as it's not interpretable by the browser.
Therefore, I need to encode the RGB32 data as jpg before encoding into base64 and sending down the pipe, but all of the solutions I have been able to find for encoding byte arrays involve saving to the disk, which is obviously a performance killer.
Can anyone explain to me a performant manner to convert these RGB32 byte arrays to jpgs on the fly so I can push them down the pipe?
Alternately, if anyone has any ideas on an alternate high performance manner to get these RGBA frames down a websocket to a browser, I'd love to hear.
Thanks!
Code looks something like this:
private void ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame frame = e.OpenColorImageFrame())
{
if (frame != null)
{
byte[] pixelData = new byte[frame.PixelDataLength];
frame.CopyPixelDataTo(pixelData);
//display in wpf
this._ColorImageBitmap.WritePixels(this._ColorImageBitmapRect, pixelData, this._ColorImageStride, 0);
//send via websocket to chrome
//how do we create a base64 encoded jpg here and pass it off to chrome?
MainWindow.Broadcast(DataForChromeGoesHere);
}
}
}
I have a flash app which sends raw data for a jpg image to a particular url Send.aspx . In Send.aspx I am using request.binaryread() to get the total request length and then read in the data to a byte array.
Then I am writing the data as jpg file to the server. The code is given below:
FileStream f = File.Create(Server.MapPath("~") + "/plugins/handwrite/uploads/" + filename);
byte[] data = Request.BinaryRead(Request.TotalBytes);
f.Write(data, 0, data.Length);
f.Close();
The file is getting created but there is no image in it. It always shows up as empty in any graphic viewer. What part am I missing. Am I supposed to use jpg encoding first before writing it to file? Thanks in advance
Well, you should use a using statement for your file stream, but other than that it looks okay to me.
A few suggestions for how to proceed...
Is it possible that the client isn't providing the data properly? Perhaps it's providing it as base64-encoded data?
Have you already read some data from the request body? (That could mess things up.)
I suggest you look closely at what you end up saving vs the original file:
Are they the same length? If not, which is longer?
If they're the same length, do their MD5 sums match?
If you look at both within a binary file editor, do they match at all? Any obvious differences?
I want to build a Screen Sharing program in C#.(with TCP)
I sniffed around the web and found out that the most efficient way to do it is by sending alot of screenshots from the client to the server.
The point is - how can I compress a Bitmap to Jpeg - receive it on the server and decompress again to Bitmap (so I can show it in a form) ?
I've tried using the JpegBitmapEncoder with no luck, here's my code:
Bitmap screen = TakeScreenshot();
MemoryStream ms = new MemoryStream();
byte[] Bytes = BmpToBytes_Unsafe(screen);
ms.Write(Bytes, 0, Bytes.Length);
Jpeg = new JpegBitmapEncoder();
Jpeg.Frames.Add(BitmapFrame.Create(ms));
Jpeg.QualityLevel = 40;
Jpeg.Save(ms);
BinaryReader br = new BinaryReader(ms);
SendMessage(br.ReadBytes((int)ms.Length));
It throws an NotSupportedException at Jpeg.Frames.Add(BitmapFrame.Create(ms));
No imaging component suitable to complete this operation was found.
So I need a way to convert a Bitmap to Jpeg, then to byte[], then send it over TCP.
And on the other end, do the exact opposite. Any suggestions ?
Thank you.
JPEG was designed for photographs, not for screen captures. Also, most of the screen doesn't change so better to just send the changed portions and only a full screen when much of the screen has changed.
Unless you're just doing this for fun, you are going about this all wrong. VNC has been doing this for years and the source code is free so you could look to see how that's done.