I've often wondered how hard it is to output a PNG file directly, without using a library or a standard tool like pnmtopng
. (I'm not sure when you'd actually want to do this; maybe for a tiny embedded system with a web interface.)
I found that constructing a simple, uncompressed PNG does not require a whole lot of code, but there are some odd details I got wrong on the first try. Here's a crash course in writing a minimal PNG encoder. We'll use only a small subset of the PNG specification, but I'll link to the full spec so you can read more.
The example code is not too fast; it's written in Python and has tons of string copying everywhere. My goal was to express the idea clearly, and let you worry about coding it up in C for your embedded system or whatever. If you're careful, you can avoid ever copying the image data.
We will assume the raw image data is a Python byte string (non-Unicode), consisting of one byte each for red, green, and blue, for each pixel in English reading order. For reference, here is how we'd "encode" this data in the much simpler PPM format.
def to_ppm(width, height, data):
return 'P6\n%d %d\n255\n%s' % (width, height, data)
I lied when I said we'd use no libraries at all. I will import Python's standard struct
module. I figured an exercise in converting integers to 4-byte big endian format would be excessively boring. Here's how we do it with struct
.
import struct
def be32(n):
return struct.pack('>I', n)
A PNG file contains a sequence of data chunks, each with an associated length, type, and CRC checksum. The type is a 4-byte quantity which can be interpreted as four ASCII letters. We'll implement crc
later.
def png_chunk(ty, data):
return be32(len(data)) + ty + data + be32(crc(ty + data))
The IHDR
chunk, always the first chunk in a file, contains basic header information such as width and height. We will hardcode a color depth of 8 bits, color type 2 (RGB truecolor), and standard 0 values for the other fields.
def png_header(width, height):
return png_chunk('IHDR',
struct.pack('>IIBBBBB', width, height, 8, 2, 0, 0, 0))
The actual image data is stored in DEFLATE format, the same compression used by gzip and friends. Fortunately for our minimalist project, DEFLATE allows uncompressed blocks. Each one has a 5-byte header: the byte 0
(or 1
for the last block), followed by a 16-bit data length, and then the same length value with all of the bits flipped. Note that these are little-endian numbers, unlike the rest of PNG. Never assume a format is internally consistent!
MAX_DEFLATE = 0xffff
def deflate_block(data, last=False):
n = len(data)
assert n <= MAX_DEFLATE
return struct.pack('<BHH', bool(last), n, 0xffff ^ n) + data
Since a DEFLATE block can only hold 64 kB, we'll need to split our image data into multiple blocks. We will actually want a more general function to split a sequence into chunks of size n
(allowing the last chunk to be smaller than n
).
def pieces(seq, n):
return [seq[i:i+n] for i in xrange(0, len(seq), n)]
PNG wants the DEFLATE blocks to be encapsulated as a zlib data stream. For our purposes, this means we prefix a header of 78 01
hex, and suffix an Adler-32 checksum of the "decompressed" data. That's right, a self-contained PNG encoder needs to implement two different checksum algorithms.
def zlib_stream(data):
segments = pieces(data, MAX_DEFLATE)
blocks = ''.join(deflate_block(p) for p in segments[:-1])
blocks += deflate_block(segments[-1], last=True)
return '\x78\x01' + blocks + be32(adler32(data))
We're almost done, but there's one more wrinkle. PNG has a pre-compression filter step, which transforms a scanline of data at a time. A filter doesn't change the size of the image data, but is supposed to expose redundancies, leading to better compression. We aren't compressing anyway, so we choose the no-op filter. This means we prefix a zero byte to each scanline.
At last we can build the PNG file. It consists of the magic PNG signature, a header chunk, our zlib stream inside an IDAT
chunk, and an empty IEND
chunk to mark the end of the file.
def to_png(width, height, data):
lines = ''.join('\0'+p for p in pieces(data, 3*width))
return ('\x89PNG\r\n\x1a\n'
+ png_header(width, height)
+ png_chunk('IDAT', zlib_stream(lines))
+ png_chunk('IEND', ''))
Actually, a PNG file may contain any number of IDAT
chunks. The zlib stream is given by the concatenation of their contents. It might be convenient to emit one IDAT
chunk per DEFLATE block. But the IDAT
boundaries really can occur anywhere, even halfway through the zlib checksum. This flexibility is convenient for encoders, and a hassle for decoders. For example, one of many historical PNG bugs in Internet Explorer is triggered by empty IDAT
chunks.
Here are those checksum algorithms we need. My CRC function follows the approach of code fragment 5 from Wikipedia. For better performance you would want to precompute a lookup table, as suggested by the PNG spec.
def crc(data):
c = 0xffffffff
for x in data:
c ^= ord(x)
for k in xrange(8):
v = 0xedb88320 if c & 1 else 0
c = v ^ (c >> 1)
return c ^ 0xffffffff
def adler32(data):
s1, s2 = 1, 0
for x in data:
s1 = (s1 + ord(x)) % 65521
s2 = (s2 + s1) % 65521
return (s2 << 16) + s1
Now we can test this code. We'll generate a grid of red-green-yellow gradients, and write it in both PPM and PNG formats.
w, h = 500, 300
img = ''
for y in xrange(h):
for x in xrange(w):
img += chr(x % 256) + chr(y % 256) + '\0'
open('out.ppm', 'wb').write(to_ppm(w, h, img))
open('out.png', 'wb').write(to_png(w, h, img))
Then we can verify that the two files contain identical image data.
$ pngtopnm out.png | sha1sum - out.ppm
e19c1229221c608b2a45a4488f9959403b8630a0 -
e19c1229221c608b2a45a4488f9959403b8630a0 out.ppm
That's it! As usual, the code is on GitHub. You can also read what others have written on similar subjects here, here, here, or here.
Out of curiosity, why do you set the block size to 3*width? On the line:
ReplyDeletelines = ''.join('\0'+p for p in pieces(data, 3*width))
Ah, 3 bytes per pixel, and width pixels per line.
ReplyDeleteIs it a requirement that each DEFLATE block contain a horizontal line of pixels? Or could you stuff all the pixels (% 64000) into a single DEFLATE block?
ReplyDeleteThank you for sharing in this article
I can learn a lot and could also be a reference
I am happy to find your website and can join to comment
Share and Klick Info Blokwalking. Hammer Of Thor
=> Jual Hammer Of Thor Di Bogor
=> Jual Hammer Of Thor Di Medan
=> Jual Hammer Of Thor Di Semarang
=> Jual Hammer Of Thor Di Bandung
=> Jual Hammer Of Thor Di Bandar Lampung
Obat Good Man | Obat pembesar penis | Vimax Asli | Vimax Extender
شركة مكافة حشرات
ReplyDeleteشركة مكافحة الصراصير بالرياض
شركة مكافحة النمل الابيض بالطائف
شركة مكافحة فئران بالرياض
شركة عزل شينكو
ReplyDeleteTiap jalma bisa mibanda(học toán cho trẻ mẫu giáo) alesan béda pikeun(toán cho trẻ 5-6 tuổi) hirup kahirupan maranéhanana sorangan.(toán cho bé 5 tuổi) Anjeun teu bisa conflate kabeh alesan ieu sami.
ReplyDeleteدينا نقل عفش جدة دينا نقل عفش جدة
ReplyDeleteافضل شركة نقل عفش من جدة الى الرياض شركة نقل عفش من جدة الى الرياض
شركة نقل عفش من جدة الى دبي شركة شحن عفش من جدة الى الامارات
ارخص معلم دهانات بالرياض
شركة تركيب واجهات حجر بالرياض
ارخص شركة نقل عفش بمكة
شركة نقل عفش من جدة الى الاردن شركة شحن عفش من جدة الى الاردن
The content is tasteful, your authored subject matter stylish. Thank you for sharing! www.caramembuatwebsiteku.com
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis is a topic that's close to my heart... Best wishes! Exactly where are your contact details though?
ReplyDeletedonald trump net worth
michael phelps net worth
warren buffett net worth
obama net worth
افضل شركات الشحن البرى والبحرى ونقل العفش داخل جميع مدن المملكة
ReplyDeleteنقل عفش من جدة الى الاردن
شركة نقل عفش من جدة الى الاردن
شركات نقل العفش من جدة للاردن
اجراءات نقل العفش للاردن
شحن من جدة الى عمان
شركات النقل البرى من جدة الى الاردن
شحن اثاث من السعودية الى الاردن
اجراءات نقل الاثاث من السعودية الى الاردن
شحن من جده للاردن
اسعار شحن الاثاث من السعودية الى الاردن
نقل عفش من السعودية الى الاردن
شركة شحن من السعودية الى الاردن
نقل عفش من جدة الى الامارات
شركة نقل عفش من جدة الى الامارات
شركات نقل العفش من جدة للامارات
اجراءات نقل العفش للامارات
شحن من جدة الى دبى
شركات النقل البرى من جدة الى الامارات
شحن اثاث من السعودية الى الامارات
شحن من جده للامارات
اسعار شحن الاثاث من السعودية الى الامارات
نقل عفش من السعودية الى الامارات
شركة شحن من السعودية الى الامارات
نقل عفش من الرياض الى الامارات
شركة نقل عفش من الرياض الى الامارات
شركات نقل العفش من الرياض للامارات
اجراءات نقل العفش للامارات
شحن من الرياض الى دبى
ReplyDeleteيسعدنا تقديم كافة خدمات نقل العفش والشحن الدولى الى من السعودية الى الاردن من السعودية الى الامارات شحن من جدة للاردن تنظيف منازل وخزانات ورش مبيدات ومكافحة حشرات شحن دولى من الرياض للامارات
اضغط على الخدمة لتصل الى موقعنا
نقل عفش من جدة الى الاردن
شركة نقل عفش من جدة الى الاردن
شحن الاثاث من جدة الى الاردن
شركات نقل العفش من جدة للاردن
اجراءات نقل العفش للاردن
شحن من جدة الى عمان
شركات النقل البرى من جدة الى الاردن
شحن اثاث من السعودية الى الاردن
اجراءات نقل الاثاث من السعودية الى الاردن
شحن من جده للاردن
اسعار شحن الاثاث من السعودية الى الاردن
رش مبيدات ومكافحة حشرات بجدة
شركة تنظيف خزانات بجدة
شركة تنظيف منازل بجدة
==========================
نقل عفش من الرياض الى الامارات
شركة نقل عفش من الرياض الى الامارات
شحن الاثاث من الرياض الى الامارات
شركات نقل العفش من الرياض للامارات
شركة شحن عفش من الرياض الي الامارات
شحن من الرياض الى دبى
شركة نقل عفش من الرياض الى دبي
شحن اثاث من السعودية الى الامارات
شركة شحن عفش من الرياض الى الامارات
شركة شحن من الرياض الى الامارات
شحن من الرياض للامارات
افضل شركات نقل الاثاث الى الامارات
نقل عفش من السعودية الى الامارات
شركة شحن من السعودية الى الامارات
ReplyDeleteاذا كنت تود الانتقال بصورة كاملة من السعودية للامارات فمن البديهى انك قد تحتاج الى شركة نقل عفش من جدة الى الامارات وهنا من داخل موقع مؤسسة الاحمدى الذى صممناه خصيصا لتقديم كافة خدمات الشحن الدولية
نقل عفش من جدة الى الامارات - شركة نقل عفش من جدة الى الامارات - شحن الاثاث من جدة الى الامارات - شركات نقل العفش من جدة للامارات - شركات شحن من جدة للامارات - شحن من جدة الى دبى - شركات النقل البرى من جدة الى الامارات - شحن اثاث من السعودية الى الامارات - شحن من جده للامارات - اسعار شحن الاثاث من السعودية الى الامارات - افضل شركات نقل الاثاث الى الامارات - نقل عفش من السعودية الى الامارات - شركة شحن من السعودية الى الامارات - شركة شحن من جدة الى دبى - نقل عفش من الرياض الى الامارات - شركة نقل عفش من الرياض الى الامارات - شحن الاثاث من الرياض الى الامارات - شركات نقل العفش من الرياض للامارات - شركات شحن العفش من الرياض للامارات - شحن من الرياض الى دبى - شركات النقل البرى من الرياض الى الامارات - شحن اثاث من السعودية الى الامارات - افضل شركة تنظيف بالباحه - شركة تنظيف خزانات بالباحه
nox-app app
ReplyDeleteOpen bin files
ReplyDeleteFollow football news And the cool thing here. ติดตาม ข่าวสารฟุตบอล และที่เด็ดได้ที่นี้
ReplyDeleteSuggest good information in this message, click here.
ReplyDeletetwinklerscandles.com
1idee-cadeau.com
Suggest good information in this message, click here.
ReplyDeleteแทงบอล ออนไลน์
พนันบอลออนไลน์ UFABET
اهم الخدمات التى تقدمها شركة انوار الحرمين فى مجالات نقل العفش والشحن الدولى بجدة مكة الطائف الرياض
ReplyDeleteشركه نقل عفش بجده
نقل عفش الرياض
شركات نقل العفش من جدة للامارات
شركة نقل عفش من الرياض الى الاردن
شركات نقل العفش من الرياض للامارات
شركة شحن من السعودية الى الامارات
نقل عفش مكة
شركة نقل عفش من جدة الى الاردن
نقل عفش جدة
Suggest good information in this message, click here.
ReplyDeleteufabetring
เกมยิงปลา ios
เกมยิงปลา
เกมยิงปลา joker
เกมยิงปลา 918
เกมยิงปลา
เกมยิงปลาออนไลน์
เกมส์ยิงปลา
เกมยิงปลา fish hunter
เกมส์ยิงปลาเล่นมัน
Unique Information. I appreciate your efforts and your ideas. Keep sharing again.
ReplyDeleteAOL Desktop Gold has a wide range of features with advanced technology inside. But sometimes, you may face AOL Desktop Gold Update Error. This is caused by an outdated web browser on your computer. To fix this error, you can contact our Quick Aid support team, we guarantee that our Quick Aid support team will be ready to assist you in whatever way possible.
Your style is very unique in comparison to other folks I have read stuff from. I appreciate you for posting when you have the opportunity, Guess I will just bookmark this page. Feel free to visit my website; 카지노사이트
ReplyDeletePretty great post. I just stumbled upon your weblog and wished to say that I have really enjoyed browsing your weblog posts. In any case I’ll be subscribing to your rss feed and I am hoping you write again very soon! Feel free to visit my website; 배트맨토토
ReplyDeleteThanks for your post! Through your pen I found the problem up interesting! I believe there are many other people who are interested in them just like me! How long does it take to complete this article? I have read through other blogs, but they are cumbersome and confusing.
ReplyDeletehappy wheels 스포츠중계
Completely awesome posting! Bunches of helpful data and motivation, both of which we all need!Relay welcome your work 스포츠토토
ReplyDeleteThanks for your post! Through your pen I found the problem up interesting! I believe there are many other people who are interested in them just like me! How long does it take to complete this article? I have read through other blogs, 바카라사이트
ReplyDeletebut they are cumbersome and confusing.
happy wheels
GREAT JOB! This blog presents a very valuable information. Keep up the good work! Visit our website too. 바카라사이트 Thanks!
ReplyDeleteHi there! This is my first visit to your blog! We are a group of volunteers and starting a new project in a community in the same niche. 토토
ReplyDeleteYour blog provided us useful information to work on. You have done a extraordinary job!
I really happy found this website eventually. Really informative and inoperative, Thanks for the post and effort! Please keep sharing more such blog. 한국야동닷컴
ReplyDeletePlease visit once. I leave my blog address below
국산야동
한국야동닷컴
Really nice and interesting post. I was looking for this kind of information and enjoyed reading this one. 국산야동
ReplyDeletePlease visit once. I leave my blog address below
야설
국산야동
Thanks for taking the time to discuss this, I feel strongly about it and love learning more on this topic. If possible, as you gain expertise, would you mind updating your blog with extra information? It is extremely helpful for me. 중국야동넷
ReplyDeletePlease visit once. I leave my blog address below
야설
중국야동넷
I was able to find good info from your blog articles. 사설토토
ReplyDeleteI have been browsing online greater than three hours today, but I by no means discovered any interesting article like yours. 파워볼게임
ReplyDeleteAs expected, I can only see articles that can grow. I ll let you know around me. 메이저사이트
ReplyDeleteThank you for the information provided! Maintain the good performance of your site. You can also check my article 토토
ReplyDeleteGreat content, thanks for sharing.
ReplyDeleteการลงทุนระยาว ใช้เงินเก็บกับการลงทุนที่คุ้มค่า เชิญทางนี้ supremosystems เว็บไซต์ที่ได้รวบรวม สาระน่ารู้เกี่ยวกับการเงิน การบริหารการเงิน จัดการวางแผนการเงิน ธุรกิจอสังหาริมทรัพย์ และการลงทุนต่าง ๆ เเนะนำการออมเงินอย่างถูกวิธี เเละทริคในการเก็บเงินต่างๆที่จะช่วยสร้างการเงินของคุณให้เเข็งเเรง.
ReplyDeleteI think it's a website with a lot of good contents. I think I accumulate a lot of knowledge.
ReplyDeletePlease come to my website and give me a lot of advice.
It's my website.
피망머니상
Your blogs are truly awesome. Keep it up. 바카라사이트인포
ReplyDeleteGreat delivery. Outstanding arguments. Keep up the good work. 바둑이사이트넷
ReplyDeleteผ่านพ้นวิกฤติเศรษฐกิจที่ย้ำเเย่ได้ง่ายๆ ไปกับ supremosystems เว็บไซต์ของเราได้รวบรวมเอา สาระน่ารู้เกี่ยวกับการเงิน การบริหารการเงิน จัดการวางแผนการเงิน ธุรกิจอสังหาริมทรัพย์ และการลงทุนต่าง ๆ คลิกตรงนี้ ซึ่งจะช่วยให้การเงิน การลงทุนของคุณมีความมั่นคง เเละมีประสิทธิภาพสูง รับรองมีเงินเก็บ เเละใช้ตลอดอย่างเเน่นอน.
ReplyDeleteThanks for sharing this amazing article, it is very informative post good work keep it up.
ReplyDelete토토
Great post, beautiful weblog with great informational content. This is a really interesting and informative content. 스포츠토토
ReplyDeleteoncainven
ReplyDeleteThanks for sharing with us this important Content. I feel strongly about it and really enjoyed learning more about this topic. 바카라사이트
ReplyDeleteI enjoy it. I come back again. This blog is a really useful blog. 먹튀폴리스
ReplyDeleteHi, you look like you' I want to join you. I hope we can do it together next time.
ReplyDeleteYour story touched me a lot. Looking forward to more updates. 해외사이트
ReplyDeleteThis blog is very useful to me. I can see new problems in your article. 토토사이트
ReplyDeletebinance hesap açma
ReplyDeleteelf bar
sms onay
VDE
binance hesap açma
ReplyDeleteelf bar
sms onay
64QH7D
betmatik
ReplyDeletekralbet
betpark
tipobet
slot siteleri
kibris bahis siteleri
poker siteleri
bonus veren siteler
mobil ödeme bahis
O3İGX
This is a smart blog. I mean it.
ReplyDeleteYou also know how to make people rally behind it, obviously from the responses.
ReplyDeleteI’d have to check with you here. Which is not something I usually do!
ReplyDeleteAlso, thanks for allowing me to comment!
ReplyDeleteYour style is very unique. Appreciate you for posting Valuable tips
ReplyDeletefantastic it is
DeleteWow, happy to see this awesome post. Thanks for sharing a great information
ReplyDeletewonderful blog
DeleteGreat post! We will be linking to this great post on our website. Keep up the great writing.
ReplyDeleteAwesome
DeleteNice post. I learn something totally new and challenging on blogs, Its great.
ReplyDeleteWonderful
DeleteI must say that this is a great post.
ReplyDeleteReally I am impressed from this post.
ReplyDeleteI am happy to find this post very useful for me, as it contains lot of information.
ReplyDelete
ReplyDeleteI am thankful for the article post. Looking forward to visit more.
Thank for information, I am extremely impressed you write style.
ReplyDelete
ReplyDeleteI want to to thank you for this good read!! I definitely enjoyed every little bit of it.
Thanks for sharing this piece of information. I really enjoyed it. keep up the good work.
ReplyDelete"I would like to thanks' for the efforts you have put in writing this blog.
ReplyDeletethis is the best way to share the great article with everyone one, so that everyone can able to utilize this information
ReplyDeleteI was impressed by your writing. Your writing is impressive. I want to write like you
ReplyDeleteBig thumbs up for making such wonderful blog page!
ReplyDeleteI have learned lot of things from it regarding blogging. thanks.
ReplyDeleteI’m really glad I have found this information.
ReplyDeleteThanks for keeping this web site, I’ll be visiting it.
ReplyDeleteI enjoyed reading the entire post. This article post is fantastic. Thank you so much for the article. Cool.
ReplyDeleteI enjoyed this just as much as what you did right here. Thanks a lot, Really Cool.
ReplyDeleteWOW, this is just what I needed. I arrived here after looking for cheap quest bars.
ReplyDeleteYou must use these strategies on your own site if you want to get the most out of this article.
ReplyDelete
ReplyDeleteAhaa, its nice discussion about this paragraph at this place at this blog, I have read all that, so now me also commenting here.
ReplyDeleteA big thank you for your blog.Really looking forward to read more. Want more
ReplyDeleteGreat Blog
ReplyDeleteGreat Blog
ReplyDeleteYour blog got me to learn a lot, thanks for sharing, nice article
ReplyDeletePerfect just what I was looking for!
ReplyDeleteKeep it on sharing
ReplyDeleteyou are really a good webmaster
"Thanks for share amazing content. Very interesting keep posting.
ReplyDelete"Much thanks to you for setting aside an ideal opportunity to distribute this data extremely valuable!
ReplyDelete"
ReplyDeleteThis is so much hilarious blog, Anyways thanks for posting ideas.
ReplyDeleteI truly like your way of blogging. I bookmarked it to my bookmark website list.
ReplyDeleteplease share i understand this is off subject but I just had to ask.
ReplyDeleteEverything is quite open and very clear reason of troubles
ReplyDeleteWe are really grateful for your blog post for giving a lot of information
ReplyDeletebest article
Hi my friend! I wish to say that this article is awesome, great written and come with almost all important infos. I would like to peer extra posts like this .
ReplyDeleteI love the efforts you have put in this, thanks for all the great blog posts. You should take part in a contest for probably the greatest blogs on the web. I will suggest this web site!
ReplyDeletegreat job, dude You've written a fantastic piece that will be very helpful to readers. Please keep doing more for people in need.
ReplyDeleteYour contribution to our knowledge is invaluable, and I appreciate you sharing it with us.
ReplyDeletesomething that is remarkable and should be learned. Thank you for providing this great information
ReplyDeleteI must say you have written a great article.
ReplyDeleteIts an amazing website, I really enjoy reading your articles.
ReplyDeleteSuch an amazing and helpful post. I really really love it.
ReplyDeleteExtremely decent blog and articles.
ReplyDeleteMuch obliged to you and sitting tight for your new post
ReplyDeleteIt’s really a great and helpful piece of information.
ReplyDeleteHi there, I enjoy reading all of your article.
ReplyDeleteThis article is very helpful and interesting too. Keep doing this in future.
ReplyDeleteNow not one thing I’d typically learn, but I favored your emotions none the less.
ReplyDeleteexcellent publish, very informative. thank you..
ReplyDeleteYou should proceed your writing. I am confident, you’ve a great readers’ base already!
ReplyDeleteOne of the most serious issues is a lack of good communication
ReplyDeletethis is very appealing, however , it is very important that will mouse click on the connection:
ReplyDeleteGreat article, This post helps me a lot Thank you. Anyways I have this site recommendation for you, Just follow the given link here:
ReplyDeleteReading this info So i am glad to convey that I have a very just right uncanny feeling I found out exactly what I needed. See more about sportstoto:
ReplyDeleteThank you a lot for sharing this with all folks you really recognize what you are talking approximately! I will Bookmark this for sure.
ReplyDeleteDaebak!! this was an extremely good post. Taking the time and actual effort to produce a top notch article… But what can I say… Just check my website and see more:
ReplyDeleteI hope you will continue to have similar posts to share with everyone.
ReplyDeleteis extremely decent and exceptionally useful article.
ReplyDeleteThe website loading velocity is amazing.
ReplyDeleteVery helpful information specifically the final phase.
ReplyDeleteI simply wish to give you a huge thumbs up for your excellent info
ReplyDeleteYou made some good points. Great blog you made here. Keep it up
ReplyDeleteI was captured with the piece of resources have got here. Big thumbs up
ReplyDeleteI’m truly enjoying the design and layout of this website. I also love the blog Thanks
ReplyDeleteGood job! That’s great idea to build this topic. It’s very helpful information you provide
ReplyDelete