Download Only A Part of a JPG with HTTP request - http

With the HTTP header Range clients can request only a certain range of bytes from a server.
GET myfile.jpg HTTP/1.1
"http://myhost"
Range=bytes=1000-1200
If the server supports this response feature and maybe even shows that by a Accept-Range header, the above request will return only the 200 bytes from byte 1000 onwards.
Is it possible to get usable parts from an JPG image with this method? Say the actual JPG measures 800x1197 pixels. What would have to be done in order to request only a sub image between the pixels 200x200 and 400x400?
To me it looks like it's only possible receive horizontally cut slices of the image. But this would already be better than getting the full image file. So in the example above I'd say one could try to download: the slice from 200 (y-axis) to 400 (y-axis) and then crop the result on the client side accordingly.
Assume we already know the content-length of the file as well as its actual image size, which may have been determined by a preceding HTTP request:
content length in bytes: 88073
jpg size: 800x1197
Which byte range would I have to request for this image? I assume that JPG has some meta data, which has to be taken in account as well. Or does the compression of jpg render this attempt impossible? It would be ok if the final cut out does not contain any metadata from the original.
But still it might be necessary to have an initial request, which takes some bytes from the beginning hoping to fetch the metadata. and based on this the actual byte range might be determined.
Would be very nice if someone could give me a hint how to approach this.

JPEG encodes compressed data in one or more scans. The scans do not indicate their length. You have to actually decode to get to the end of the scan. The scans span the entire image.
If the JPEG stream is progressively encoded you can read the stream blocks at at a time, decode the scans, update the output image, and get successively refined views of the image.

Related

How do you choose a boundary for multipart/x-mixed-replace when serving MJPEG over HTTP?

When sending M-JPEG over HTTP, you first send a header with Content-Type: multipart/x-mixed-replace;boundary=<your boundary>, then each time the sequence \r\n--<your boundary>\r\n occurs, the browser treats it as the end of one part and the start of the next part.
The problem is that a JPEG can contain that sequence, either in a comment or just because that byte sequence happens to occur in the payload.
I get that if you know all your jpeg images when you send the initial HTTP response header, you can construct a boundary which doesn't occur in any of your jpegs. But most of the time when you use M-JPEG, the jpegs are generated on the fly. How can I choose a boundary which is guaranteed to not occur in the jpegs? Are there byte sequences which never occur in a valid jpeg? Or is the best strategy just to choose a long enough random boundary that the probability of collision is small and hope for the best..?

What size does the server have to give to each response chunk?

If I wanted to configure my personal server so that the response for a certain request is set according to the chunk rules: what size should each of the server response chunk have?
For example, let's say that the chunked response is a long HTML page or a file.
How would you behave in these two cases?
From the RFC:
This allows dynamically produced content to be transferred...
In other words: Transfer-Encoding: chunked is needed when the length of content is unknown.
The length of your content may be as big as 10Tb... but also it can be as small as 10 bytes. It doesn't matter. The chucks' sizes depend solely on the algorithms you are using to generate them and to read then.
Let's say you generate a stream of messages of different lengths, one character per second. In this case you can decide to send one byte chucks to the client. This way the client will be able to use the data as soon as it arrives. But if your client have no use for partial messages, then you probably should save the bandwidth and send a chunk at the moment you've finished generating the next message. And again it doesn't matter how big or small the message is. It can be 2 characters or it can be 1000.
On second thought, there are some use cases for Transfer-Encoding: chunked with the data of known size. But then your question becomes to broad to answer. It depends on your client code, server code, network conditions, data properties, desired user experience, etc.
And if by any chance you are asking about optimal size from the network perspective, then just send the whole file - that the best bet. And support Content-Range on your server instead of Transfer-Encoding: chunked.

WKInterfaceDevice caching optimization

I am trying to cache rendered animations to the apple watch (these are generated at run time). I have saved the frames of each animation as JPEG #1x with compression of 0.1. The sum of all the frames is less then 1.2 MB. I clear the cache before I start caching. However only about half the animations are cached. The documentation says that the cache is 5MB. What am I doing wrong?
If you want to send image data to the Watch programmatically (i.e. not at compile time), WKInterfaceDevice provides two methods:
addCachedImage:name: accepts a UIImage, encodes it as PNG image data, and transmits it to the cache. So, if you create a UIImage from JPEG data, you are actually decoding the JPEG data into an image, then re-encoding it as PNG before it's sent to the cache (thereby negating the effects of JPEG-encoding in the first place).
addCachedImageWithData:name: accepts NSData and transmits the unaltered data directly to the cache. So, if you encode your image to NSData using UIImageJpegRepresentation and pass it to this method, you'll transmit and store less in the cache. I use this technique for all of my images, unless I need the benefits of a PNG image; in that case, I actually encode my own NSData using UIImagePngRepresentation and send it using this method.
For debugging purposes, it's helpful to use the [[WKInterfaceDevice currentDevice] cachedImages] dictionary to find the size of the cached image data. The dictionary returns a NSNumber with the size (in bytes) of the cache entry.
I just discovered that if you use this line of code:
[self.image setImageNamed:#"number"]
Your images should be named:
number1.png
number2.png
number3.png
number4.png
I was running into a similar error when I had my images named:
number001.png
number002.png
number003.png
number004.png

How can I get the size of a resource without actually downloading it?

So I'm on very constrained bandwidth where I am right now and I clicked a link to a pdf tutorial for something and Chrome began to download it and I was watching the size spiral upward from 20Kb past 5Mb and decided to stop it. How do I know it's not a 4Gb pdf?? Ridiculous, I know.
But I started thinking, surely there must be a way I can simply request the size of the resource to check before downloading. Perhaps some sort of cURL request?
Does anyone know a way?
You could try using the HTTP HEAD method. This should get you the headers of the document without the body. This might have the content length in it.
Or you could send an HTTP Range request header with a GET request. See section 14.35.2 in this document. Range headers look like:
Range: 1-20000
which would request the first 20,000 bytes (octets) of a document. If the document is less than 20,000 bytes, you would get the whole document.
The only problem is that the server might not support the Range header, in which case it will send a 200 status instead of 206. In that case you can just reset the connection if you don't want to risk burning bandwidth on a 5Gb document.

Content-Range for resuming a file of unknown length

I create a ZIP archive on-the-fly of unknown length from existing material (using Node), which is already compressed. In the ZIP archive, files just get stored; the ZIP is only used to have a single container. That's why caching the created ZIP files makes no sense -there's no real computation involved.
So far, OK. Now I want to permit resuming downloads, and I'm reading about Accept-Range, Range and Content-Range HTTP headers. A client with a broken download would ask for an open-ended range, say: Range: bytes=8000000-.
How do I answer that? My answer must include a Content-Range header, and there, according to RFC 2616 ยง 14.16 :
Unlike byte-ranges-specifier values (see section 14.35.1), a byte- range-resp-spec MUST only specify one range, and MUST contain absolute byte positions for both the first and last byte of the range.
So I cannot just send "everything starting from position X", I must specify the last byte sent, too - either by sending only a part of known size, or by calculating the length in advance. Both ideas are not convenient to my situation. Is there any other possibility?
Answering myself: Looks like I have to choose between (1) chunked-encoding of a file of yet unknown length, or (2) knowing its Content-Length (or at least the size of the current part), allowing for resuming downloads (as well as for progress bars).
I can live with that - for each of my ZIP files, the length will be the same, so I can store it somewhere and re-use it for subsequent downloads. I'm just surprised the HTTP protocol does not allow for resuming downloads of unknown length.
Response with "multipart/byteranges" Content-Type including Content-Range fields for each part.
Reasoning:
When replying to requests with "Range" header, successful partial responses should report 206 HTTP status code (14.35.1 Byte Ranges section)
206 response suggests either "Content-Range" header or "multipart/byteranges" Content-Type (10.2.7 206 Partial Content)
"Content-Range" header cannot be added to the response as it does not allow omitting end position, so the only left way is to use "multipart/byteranges" Content-Type

Resources