5 ms·
Show HN: Imgix.js, a JavaScript library for responsive imaging
- fimdomeio 12y agoI wonder why are there so many services that work with this kind of business model. while I would be willing to pay for code I can own, I would never invest in something in something where I can't predict it's future.
- latch 12y agoI can't speak specifically about this responsive image feature, but as for imgix's core business, I have mixed feelings. It's pretty trivial to write on-the-fly image processing using an existing graphics library. And given that the image can be cached and served from disk and a CDN, it can scale incredibly well. Having said that, the features that they support is impressive, the API is intuitive, the speed is great, and you can stick your own CDN infront of it (or use theirs, which is actually Fastly, I believe). The founder, Chris, is wicked smart...this is really more than just a wrapper around GM.
- egonschiele 12y agoI just had to write an image server for work and found it incredibly hard. What's your on-the-fly image processing setup look like?
- latch 12y agoI'd break it down into two parts. The first is the image transformation. For this we use graphics magic, and based on the params in the querystring, we'd crop, resize, alter the quality, anchor the image to a focus point and so on. Not copy and pastable, but [1] should give you a rough idea. Also [2] is code we use to get the file type and size of the image (gm identify can be painfully slow). The second part was a bit more "fancy". There were two really slow parts to this (a) fetching the origin (from S3) and (b) applying lossless compression (for a large image, it can take 10+ seconds). Fetching from origin is easily solved by caching the origin to disk. So if you ask for goku.png?w=90001&h=9001 and then goku.png?w=2393&h=43433 it's only going to be 1 origin fetch. For the lossless compression, we just used the filesystem as a queue. We'll serve up the umcompressed image with a short cache header (maybe 10 minutes) and store it in /storage/uncompressed. The filesystem is monitored and when a file is added, we compress it and them move it to /storage/compressed. So, when you serve an image, the flow is: - check for the file in /storage/compressed/ and serve that with a long cache header (this is a fully transformed image (hash the querystring parameters)) - check for the file in /storage/uncompressed/ and serve that with a short cache header (this is a fully transformed image (hash the querystring parameters)) - Check if we at least have the original in /storage/original - if not, fetch the original, put it in /storage/original - Transform the image, store it at /storage/uncompressed and serve it up - In the background, compress images and move them from /storage/uncompressed to /storage/compressed It might seem like overkill when you consider that, despite serving thousands of images per second, the CDN handles almost every request. The problem is with the lossless compression. We found it impossible to do it on-the-fly for too many of our images, so you absolutely need that available and ready to go for the 5% CDN miss. [1] https://gist.github.com/anonymous/8f328359f07f6c5d142e https://gist.github.com/anonymous/8f328359f07f6c5d142e [2] http://openmymind.net/Getting-An-Images-Type-And-Size/ http://openmymind.net/Getting-An-Images-Type-And-Size/
- richbradshaw 12y agoAre you using S3 with multiple EC2 instances/multiple servers? Do you keep your /storage/ on S3? I'm considering pulling from S3, then resizing on whatever server it is, then storing back on S3 - any issues with that? Do you handle the malicious case of someone supplying various widths and heights potentially DoSing the server?
- latch 12y agoNon EC2 servers, one in Europe and one in the US. /storage are local SSDs to the machines (so it's 2 copies of the data (3 for the originals since they're also on S3)). Whether storing it back on S3 is "good enough" depends on whether you feel the latency to fetch from S3 is acceptable. I don't have any hard numbers (I might have at some point). I imagine you'll see a percentage in the 1-4s range, which is pretty bad considering you still have to serve it to the CDN and then the CDN to the user. If you have users on mobile or in developer countries, you do what you can to make your side as fast as possible. Never had malicious users, but we worried about it. We took a reactive approach: monitoring disk space usage. It never proved necessary to do more. You're definitely open to a DOS attack. Hard to mitigate too...can't rate limit since the request comes from the CDN. You could whitelist certain dimensions, but we also allowed our content owners to specify the focal point of the image, which we'd center our crop on, which means any value of x and y is reasonable. You could possibly store that data on the image servers, instead of passing it in the querystring, but then you're introducing state and, with multiple servers, synchronisation. shudder. You can see it in action at: http://0.viki.io/viki.jpg?s=263x220&q=h http://0.viki.io/viki.jpg?s=263x220&q=h with documentation at: http://dev.viki.com/v4/images/ http://dev.viki.com/v4/images/ (the [q]uality argument isn't documented, weird....unless you specify a quality (I only remember [h]igh) we pick a jpg compression based on the filesize)
- porker 12y ago> It never proved necessary to do more. You're definitely open to a DOS attack. Hard to mitigate too... An approach I've used before is to have a hash in the URL, and discard any requests where the width/height don't match the hash value. Not good if users are meant to be able to link at whatever size they want, but in our case we gave a shortcode to users which then generated the actual URL.
- Ronsenshi 12y agoHad to write image server myself and it wasn't really hard. Nginx to handle existing files. Python + Pillow + cherrypy (or could be any other microframework) to handle image processing on the fly and then caching processed image to the disk. All in all around 350 lines of code in python. And something like 100 lines in nginx (because of a heavy filename processing and inner url rewriting). Result - facebook-like image processing: Simple resize: http://media.example.com/w400x200/id_token_string.jpg http://media.example.com/w400x200/id_token_string.jpg Crop (based on coords): http://media.example.com/20.20.380.300/id_token_string.jpg http://media.example.com/20.20.380.300/id_token_string.jpg Or crop resize from center: http://media.example.com/c200x200/id_token_string.jpg http://media.example.com/c200x200/id_token_string.jpg and so on... Fun project.
- nc 12y agoIt's about total cost of ownership A: Imgix = cost of imgix subscription + integration time * hourly rate (it's dead simple) B: Rolling your own = dev time * hourly rate + maintenance/ops time * hourly rate For most orgs B > A. For most individual programmers since hourly rate is not a factor A < B.
- nulltype 12y agoIf you have to pay for hardware to run it on, that would be part of B.
- Ronsenshi 12y agoThat's certainly true. I'm not saying that this service doesn't have any value. Just wanted to share my experience with writing similar solution. It's good to be dev and have spare time for stuff like that. You learn stuff while making such projects, you save money and it just works. About money, judging by the pricing on imgix page (and if I understand pricing correctly, I'm saving around $300 per month ($50 for cheapest plan + $250 for traffic).
- egonschiele 12y agoWhat was the max throughput your server could handle? We ended up using Go because we serve 400 - 600 reqs/sec and Python/Ruby solutions didn't have high throughput.
- michaelmior 12y agoThere are at least couple open source projects that handle dynamic image generation on the backend quite nicely. It seems photon is dead, but I found it works quite well and is easy to extend. Thumbor seems quite active although I've never used it myself. https://github.com/thumbor/thumbor https://github.com/thumbor/thumbor https://github.com/1000Memories/photon-core https://github.com/1000Memories/photon-core
- aidanfeldman 12y agoOne that I wrote, written in Ruby: http://magickly.afeld.me/ http://magickly.afeld.me/ Powers http://mustachify.me http://mustachify.me :3)
- justinph 12y agoThis is nice, but it does not put a valid img tag in the document source without javascript execution. That might be fine for things that don't face the public internet, but if you do any type of public publishing, you should care about having markup that describes your content independent of scripts or css. This is why standard markup-based responsive images (picture and srcset) are such a big deal.
- miggi 12y agoThere is nothing stopping you from setting the src tag. But you are just adding another request. Our base service works perfectly with src set and picturefill. This library is for cases where a different result is desired.
- sleepyhead 12y agoWhy isn't there an img-tag in the default example? Why are you promoting bad practice by not having images in img-tags? You solved one problem but created a much bigger problem. Bots, screen readers and non-javascript client should see an image, not a div with some attributes.
- sim0n 12y agoThey're welcome to target whichever type of users they want to - it's 2014, most average internet users have javascript enabled. Besides, you can add a title/aria-* attribute for bots and screenreaders (perhaps not semantically correct but gets the job done).
- sleepyhead 12y agoYes it is 2014 and we should be able to follow simple standards that has been around for quite some time.
- tantalor 12y agoTitle is "for responsive images", not "imaging". Imaging is completely different!
- miggi 12y agoWhat is your definition of imaging? Our use of imaging is in reference to imaging in technology. "The production of graphic images from digitally generated data." Our service processes images on our servers and produces new image data with each request when necessary (if not cached already.) The Javascript library is just a way to interface with our infrastructure and generate these requests.
- kingzain 12y agoWhat would the advantage of this be versus using the picture tag with your own image sources hosted on a CDN? (Let's assume picture tag is widely supported for now)
- miggi 12y agoIt is possible to easily target thr picture element using imgix's URL API directly. However, with picture you are limited to a set of image sizes and predefined dprs. This library allows the containing element to recieve an image at any size necessary with any DPR multiplier (up to 5, I believe) with the added bonus of conditional image manipulation overrides. In the example, we are baking in textual image information. Other edits like image quality and sharpening or midtone adjustments could be conditionally set as the image crops larger or smaller.
- crapiola 12y agowhere did they get the yeti image in the demo?
- miggi 12y agoI'm not sure what "yeti" image you are referring to. All images were purchased royalty free images from iStockPhoto.