<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6260754590317264118</id><updated>2012-02-21T10:06:53.921-08:00</updated><title type='text'>libvips and nip2</title><subtitle type='html'>Development and use of the &lt;a href="http://www.vips.ecs.soton.ac.uk"&gt;VIPS image processing system&lt;/a&gt;</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-5302450435257413665</id><published>2012-02-21T03:31:00.001-08:00</published><updated>2012-02-21T10:06:53.947-08:00</updated><title type='text'>Sequential mode read</title><content type='html'>Development libvips has just gained an interesting new feature: sequential mode read. This will be in the upcoming 7.28, due in another month or so.&lt;br /&gt;&lt;br /&gt;Many image formats only really support sequential reading. For example, libpng provides &lt;a href="http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Desktop-generic/LSB-Desktop-generic/libpng12.png.read.row.1.html"&gt;png_read_row()&lt;/a&gt;, a function which reads the next line of pixels from a file. You call it once for each line in the image to get every pixel.&lt;br /&gt;&lt;br /&gt;However, many operations require random access to pixels. For example, a 90-degree rotate will need to read a column of pixels for every output line it writes. If it just used &lt;a href="http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Desktop-generic/LSB-Desktop-generic/libpng12.png.read.row.1.html"&gt;png_read_row()&lt;/a&gt; it would need to decompress the input image many, many times in order to create the output.&lt;br /&gt;&lt;br /&gt;To prevent this, libvips will first decompress the entire image to a large temporary area and then process from that. This temporary area is in memory for small files or on disc for large files.&lt;br /&gt;&lt;br /&gt;Not all operations need random access to their source pixels. For example, thumbnailing, the process of shrinking images for display, can work strictly top-to-bottom. To help speed up operations of this type, libvips has a new hint that you can give to read operations to indicate that you only need sequential access.&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time vips --vips-leak copy wtc.jpg[sequential] wtc.tif&lt;br /&gt;real&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m4.903s&lt;br /&gt;user&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m1.384s&lt;br /&gt;sys&amp;nbsp; &amp;nbsp;&amp;nbsp; 0m0.512s&lt;br /&gt;memory: high-water mark 70.73 MB&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;(where wtc.jpg is a 10,000 by 10,000 pixel RGB image and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;--vips-leak&lt;/span&gt; makes libvips print peak memory use)&lt;br /&gt;&lt;br /&gt;Here the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[sequential]&lt;/span&gt; hint means that we will only need top-to-bottom access to the pixels in &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;wtc.jpg&lt;/span&gt;. When libvips opens this image it will not decompress to a temporary buffer but, instead, stream pixels from the jpeg decompressor directly through the operation. This saves first writing and then reading the 300 MB temporary area.&lt;br /&gt;&lt;br /&gt;The sequential mode reader keeps a few hundred lines behind the current read point in a cache so it can handle some small amount of non-sequential access. If you try something that's very non-sequential after giving the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[sequential]&lt;/span&gt; hint, you get an error.&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time vips flip wtc.png[sequential] wtc.tif vertical&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VipsSequential: non-sequential read --- at position 0 in file, but position 9344 requested&lt;/span&gt; &lt;/blockquote&gt;&lt;br /&gt;Without the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[sequential]&lt;/span&gt; hint you get the current libvips behaviour, which is noticeably slower and of course makes much more disc traffic:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time vips copy wtc.jpg wtc.tif&lt;br /&gt;real&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m6.004s&lt;br /&gt;user&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m1.588s&lt;br /&gt;sys&amp;nbsp; &amp;nbsp;&amp;nbsp; 0m1.208s&lt;br /&gt;memory: high-water mark 77.46 MB&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;Both are faster than ImageMagick:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time convert wtc.jpg wtc.tif&lt;br /&gt;real&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m9.357s&lt;br /&gt;user&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m11.393s&lt;br /&gt;sys&amp;nbsp;&amp;nbsp; &amp;nbsp; 0m0.620s&lt;br /&gt;peak memuse 673 MB&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;The jpeg, stripped tiff and png readers now support sequential mode read. We may add sequential mode support to other readers before release, but these are the main ones.&lt;br /&gt;&lt;br /&gt;The libvips thumbnailing utility, &lt;a href="http://www.manpagez.com/man/1/vipsthumbnail/"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;vipsthumbnail&lt;/span&gt;&lt;/a&gt;, now turns on sequential mode for you, so you get this nice behaviour automatically.&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time vipsthumbnail --vips-leak wtc.tif&lt;br /&gt;real&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m1.612s&lt;br /&gt;user&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m1.160s&lt;br /&gt;sys &amp;nbsp; &amp;nbsp; 0m0.784s&lt;br /&gt;memory: high-water mark 72.57 MB&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;Again, faster than ImageMagick: &lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time convert wtc.tif -resize 128x128 tn_wtc.jpg&lt;br /&gt;real&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m10.039s&lt;br /&gt;user&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m9.409s&lt;br /&gt;sys&amp;nbsp; &amp;nbsp;&amp;nbsp; 0m0.820s&lt;br /&gt;peak memuse 678 MB&lt;/div&gt;&lt;/blockquote&gt;You won't see much of a speedup with jpg images since both systems use libjpeg's handy downsample-on-load feature:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time vipsthumbnail wtc.jpg&lt;br /&gt;real&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m0.527s&lt;br /&gt;user&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m0.492s&lt;br /&gt;sys&amp;nbsp; &amp;nbsp;&amp;nbsp; 0m0.024s&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time convert -define jpeg:size=256x256 wtc.jpg -thumbnail 128x128 -unsharp 0x.5 tn_wtc.jpg&lt;br /&gt;real&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m0.463s&lt;br /&gt;user&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m0.436s&lt;br /&gt;sys&amp;nbsp; &amp;nbsp;&amp;nbsp; 0m0.040s&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Update&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Rob Hines pointed out that this will help tiff pyramid build as well. You see a modest speedup with a tif source:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time vips --vips-leak copy wtc.tif wtc-pyr.tif[compression=jpeg,tile,pyramid]&lt;br /&gt;memory: high-water mark 72.50 MB&lt;br /&gt;real    0m6.604s&lt;br /&gt;user    0m4.820s&lt;br /&gt;sys    0m1.076s&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time vips --vips-leak copy wtc.tif[sequential] wtc-pyr.tif[compression=jpeg,tile,pyramid]&lt;br /&gt;memory: high-water mark 62.30 MB&lt;br /&gt;real    0m5.379s&lt;br /&gt;user    0m4.648s&lt;br /&gt;sys    0m0.560s&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;And a very nice speedup with a massive jpg source:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time vips --vips-leak copy world.topo.bathy.200405.3x21600x21600.A1.jpg A1-pyr.tif[compression=jpeg,tile,pyramid]&lt;br /&gt;memory: high-water mark 162.58 MB&lt;br /&gt;real    1m12.996s&lt;br /&gt;user    0m22.845s&lt;br /&gt;sys    0m4.552s&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time vips --vips-leak copy world.topo.bathy.200405.3x21600x21600.A1.jpg[sequential] A1-pyr.tif[compression=jpeg,tile,pyramid]&lt;br /&gt;memory: high-water mark 138.95 MB&lt;br /&gt;real    0m24.218s&lt;br /&gt;user    0m22.277s&lt;br /&gt;sys    0m1.172s&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;In this case you save writing then reading back a 1.3 GB file.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-5302450435257413665?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/5302450435257413665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2012/02/sequential-mode-read.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/5302450435257413665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/5302450435257413665'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2012/02/sequential-mode-read.html' title='Sequential mode read'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-2661701616002971330</id><published>2012-01-30T09:12:00.000-08:00</published><updated>2012-01-30T09:12:12.071-08:00</updated><title type='text'>How libvips handles colour</title><content type='html'>I was asked to write some notes on how libvips handles colourspaces. I thought it might be handy to have as a blog post for reference. &lt;br /&gt;&lt;br /&gt;libvips started out as a library for very high-resolution colorimetricimaging of old master paintings. So it emphasises efficiency, largefile sizes and high accuracy, it does not think much of being easy touse. It's a low-level, rather manual library.&lt;br /&gt;&lt;br /&gt;libvips images are 3D arrays with the dimensions width / height / bands (usually called channels in other packages I think), where each value can be 8, 16 or 32-bit int,signed or unsigned, float, double, complex or double complex. Allvalues in an image must have the same type. All operations (almost)can work on images of any size or type. libvips uses templates soyou (usually) only write one inner loop and the compiler will expandit to the 10 cases for you.&lt;br /&gt;&lt;br /&gt;Colour transforms are implemented as a set of functions ontop of this. libvips has D65 XYZ, represented as a 3-band float image,as its core colourspace:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-5KyOT4txqTc/Tya1anIk_oI/AAAAAAAAAKQ/MStTfpPDiV8/s1600/interconvert.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-5KyOT4txqTc/Tya1anIk_oI/AAAAAAAAAKQ/MStTfpPDiV8/s1600/interconvert.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;There's no such thing as a LAB image (for example). Instead,operations like im_XYZ2Lab() assume you know what you are doing andthat the array of values you pass in does indeed represent a D65 XYZimage. Operations set a hint field on their output (called"interpretation" -- it'd be set to LAB by im_XYZ2Lab(), for example) thathigher-level libraries can use to help display an image to the usersensibly.&lt;br /&gt;&lt;br /&gt;The colour-related operations libvips provides are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;conversion between XYZ, Lab, LCh, Yxy and CMC&lt;/li&gt;&lt;li&gt; a few colour difference metrics: CIELAB 76, CIELAB 2000, CMC&lt;/li&gt;&lt;li&gt;D65 / D50 conversion, based on Bradford&lt;/li&gt;&lt;li&gt;conversion to and from device space and D65 XYZ with lcms and an ICC profile&lt;/li&gt;&lt;li&gt;a fast path to sRGB from XYZ for GUIs&lt;/li&gt;&lt;/ul&gt;And that's about it.&lt;br /&gt;&lt;br /&gt;The file load/save operations (like tiffload, jpegsave etc.) don't doanything with colour. On load they attach any ICC profiles they seeto the vips image as metadata and on save they write any attachedprofile to the file. They aim to give you something very close towhat's actually stored in the file and leave colour processing for youto arrange.&lt;br /&gt;&lt;br /&gt;What's good about the way libvips handles colour? It's simple, fast andpredictable. There's no magic and it won't do strange things behindyour back. Because there's no colour knowledge embedded in imagesit's also very easy to extend.&lt;br /&gt;&lt;br /&gt;The downsides are: it takes some level of knowledge to drive it,there's not much support for other colour temperatures (better D50support would be useful for printing), and like all of libvips there'sno support for alpha. &lt;br /&gt;&lt;br /&gt;nip2 tries to provide a slightly higher-level way of working with colour. It has simple menus which flip between colour spaces and temperatures, buttons for calculating distance maps, and fairly automatic import and export features.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-2661701616002971330?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/2661701616002971330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2012/01/how-libvips-handles-colour.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/2661701616002971330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/2661701616002971330'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2012/01/how-libvips-handles-colour.html' title='How libvips handles colour'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-5KyOT4txqTc/Tya1anIk_oI/AAAAAAAAAKQ/MStTfpPDiV8/s72-c/interconvert.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-3213598375202425119</id><published>2011-12-31T07:51:00.000-08:00</published><updated>2012-01-28T21:56:39.756-08:00</updated><title type='text'>Task of the day: resize an image with the "align centers" and "align corners" image size conventions</title><content type='html'>There are two main image size conventions. Both are based on imagining pixels of the "original" image to be squares of unit area. Each leads to different results when resizing.&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Note:&amp;nbsp;&lt;/b&gt;In this post, I won't address the issue of preserving the aspect ratio exactly.&lt;br /&gt;&lt;br /&gt;Suppose that&lt;br /&gt;&lt;i&gt;input.img&lt;/i&gt; is the image to be resized. &lt;i&gt;input.img&lt;/i&gt; has &lt;i&gt;m&lt;/i&gt; rows and&lt;i&gt; n &lt;/i&gt;columns.&lt;br /&gt;&lt;i&gt;output.img&lt;/i&gt; is the resized image. &lt;i&gt;output.img&lt;/i&gt; has &lt;i&gt;M&lt;/i&gt; rows and &lt;i&gt;N&lt;/i&gt; columns.&lt;br /&gt;&lt;br /&gt;In VIPS, the center of the top left corner of any image is understood to be at position (0,0) by default, and pixels are indexed starting at 0 (the C convention). So, the top left pixel has index (0,0) and is centered at (0,0). The bottom right pixel of &lt;i&gt;input.img&lt;/i&gt;&amp;nbsp;has index (n-1,m-1) and is centered at (n-1,m-1).&lt;br /&gt;In other words, positions match C-style indexing.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Align corners (generaly better for reducing size): &lt;/b&gt;This is the image size convention which is ideal for reducing the number of pixels in each direction by an exact fraction (with box filtering, for example). With this convention, there is no extrapolation near the boundary when downsampling. &amp;nbsp;It is used by ImageMagick by default&amp;nbsp;&lt;strike&gt;(recent versions of ImageMagick can be compiled to use the other convention instead)&lt;/strike&gt;.&lt;br /&gt;&lt;br /&gt;The corners of input.img are located at (-.5,-.5), (-.5,&lt;i&gt;m&lt;/i&gt;-.5), (&lt;i&gt;n&lt;/i&gt;-.5,-.5) and (&lt;i&gt;n&lt;/i&gt;-.5,&lt;i&gt;m&lt;/i&gt;-.5).&lt;br /&gt;The corners of output.img are located at&amp;nbsp;(-.5,-.5), (-.5,&lt;i&gt;M&lt;/i&gt;-.5), (&lt;i&gt;N&lt;/i&gt;-.5,-.5) and (&lt;i&gt;N&lt;/i&gt;-.5,&lt;i&gt;M&lt;/i&gt;-.5).&lt;br /&gt;&lt;br /&gt;The affine transformation that sends each input corner to the corresponding output corner is&lt;br /&gt;X = (&lt;i&gt;N&lt;/i&gt;/&lt;i&gt;n&lt;/i&gt;) x + (&lt;i&gt;N&lt;/i&gt;/&lt;i&gt;n&lt;/i&gt;-1)/2&lt;br /&gt;Y = (&lt;i&gt;M&lt;/i&gt;/&lt;i&gt;m&lt;/i&gt;) y + (&lt;i&gt;M&lt;/i&gt;/&lt;i&gt;m&lt;/i&gt;-1)/2&lt;br /&gt;&lt;br /&gt;Consequently, you can resize with the command:&lt;br /&gt;&lt;br /&gt;vips im_affinei &lt;i&gt;input.img&lt;/i&gt; &lt;i&gt;output.img&amp;nbsp;&lt;/i&gt;&lt;i&gt;interpolator&amp;nbsp;&lt;/i&gt;&lt;i&gt;a b c d dx dy ox oy ow oh&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;where&lt;br /&gt;&lt;i&gt;interpolator&lt;/i&gt; is your choice of method used to interpolate. The current options are bilinear, bicubic, lbb, nearest, nohalo or vsqbs.&lt;br /&gt;&lt;i&gt;a &lt;/i&gt;= &lt;i&gt;N&lt;/i&gt;/&lt;i&gt;n&lt;/i&gt;&lt;br /&gt;&lt;i&gt;b &lt;/i&gt;= 0&lt;br /&gt;&lt;i&gt;c &lt;/i&gt;=&lt;i&gt; 0&lt;/i&gt;&lt;br /&gt;&lt;i&gt;d &lt;/i&gt;=&lt;i&gt; M&lt;/i&gt;/&lt;i&gt;m&lt;/i&gt;&lt;br /&gt;&lt;i&gt;dx &lt;/i&gt;= (&lt;i&gt;N/n-1)/2&lt;/i&gt;&lt;br /&gt;&lt;i&gt;dy &lt;/i&gt;= (&lt;i&gt;M&lt;/i&gt;/&lt;i&gt;m-1)/2&lt;/i&gt;&lt;br /&gt;&lt;i&gt;ox &lt;/i&gt;= 0&lt;br /&gt;&lt;i&gt;oy&lt;/i&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;= 0&lt;br /&gt;&lt;i&gt;ow&lt;/i&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;=&lt;i&gt;&amp;nbsp;N&lt;/i&gt;&lt;br /&gt;&lt;i&gt;oh&lt;/i&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;=&lt;i&gt;&amp;nbsp;M&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Warning:&amp;nbsp;&lt;/b&gt;Compute everything in floating point arithmetic unless the divisions have no remainder.&lt;br /&gt;&lt;div&gt;&lt;b&gt;Warning: &lt;/b&gt;With the current crop of interpolators, this approach will not give high quality reductions of images. Use vips_thumbnail for that.&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Align centers (generally better for enlarging): &lt;/b&gt;With this image size convention, there is no extrapolation near the boundary when enlarging. Instead of aligning the outer corners, we align the centers of the corner pixels.&lt;br /&gt;&lt;br /&gt;The affine transformation that does this is&lt;br /&gt;X = ((&lt;i&gt;N&lt;/i&gt;-1&lt;i&gt;)&lt;/i&gt;/(&lt;i&gt;n&lt;/i&gt;-1)) x&lt;br /&gt;Y = ((&lt;i&gt;M&lt;/i&gt;-1)/(&lt;i&gt;m&lt;/i&gt;-1)) y&lt;br /&gt;&lt;br /&gt;Consequently, you can resize with the command:&lt;br /&gt;&lt;br /&gt;vips im_affinei&lt;i&gt;&amp;nbsp;input.img&lt;/i&gt;&amp;nbsp;&lt;i&gt;output.img&lt;/i&gt;&amp;nbsp;&lt;i&gt;interpolator&lt;/i&gt;&lt;i&gt;&amp;nbsp;a b c d dx dy ox oy ow oh&lt;/i&gt;&lt;br /&gt;where&lt;br /&gt;&lt;i&gt;interpolator&lt;/i&gt;&amp;nbsp;is as above&lt;br /&gt;&lt;i&gt;a&amp;nbsp;&lt;/i&gt;=&amp;nbsp;(&lt;i&gt;N&lt;/i&gt;-1&lt;i&gt;)&lt;/i&gt;/(&lt;i&gt;n&lt;/i&gt;-1)&lt;br /&gt;&lt;i&gt;b&amp;nbsp;&lt;/i&gt;= 0&lt;br /&gt;&lt;i&gt;c&amp;nbsp;&lt;/i&gt;=&lt;i&gt;&amp;nbsp;0&lt;/i&gt;&lt;br /&gt;&lt;i&gt;d&amp;nbsp;&lt;/i&gt;=&lt;i&gt;&amp;nbsp;&lt;/i&gt;(&lt;i&gt;M&lt;/i&gt;-1)/(&lt;i&gt;m&lt;/i&gt;-1)&lt;br /&gt;&lt;i&gt;dx&amp;nbsp;&lt;/i&gt;= 0&lt;br /&gt;&lt;i&gt;dy&amp;nbsp;&lt;/i&gt;=&lt;i&gt;&amp;nbsp;&lt;/i&gt;0&lt;br /&gt;&lt;i&gt;ox&amp;nbsp;&lt;/i&gt;= 0&lt;br /&gt;&lt;i&gt;oy&lt;/i&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;= 0&lt;br /&gt;&lt;i&gt;ow&lt;/i&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;=&lt;i&gt;&amp;nbsp;N&lt;/i&gt;&lt;br /&gt;&lt;i&gt;oh&lt;/i&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;=&lt;i&gt;&amp;nbsp;M&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-3213598375202425119?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/3213598375202425119/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/12/task-of-day-resize-image-with-align.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/3213598375202425119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/3213598375202425119'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/12/task-of-day-resize-image-with-align.html' title='Task of the day: resize an image with the &quot;align centers&quot; and &quot;align corners&quot; image size conventions'/><author><name>Nicolas Robidoux</name><uri>http://www.blogger.com/profile/01482580733771854842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/--ZNJwtHX4Ss/TgNa2x_EuoI/AAAAAAAAAB4/16-vMNoRd2k/s220/eye.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-9133002709908921468</id><published>2011-12-30T17:42:00.000-08:00</published><updated>2011-12-30T18:24:10.908-08:00</updated><title type='text'>Task of the day: convert a jpg image to 8-bit png</title><content type='html'>vips im_copy input.jpg output.png&lt;br /&gt;&lt;br /&gt;If you want to set the png compression type (to 9, say, instead of the default 6):&lt;br /&gt;&lt;br /&gt;vips im_copy input.jpg output.png:9&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-9133002709908921468?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/9133002709908921468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/12/task-of-day-convert-jpg-image-to-png.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/9133002709908921468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/9133002709908921468'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/12/task-of-day-convert-jpg-image-to-png.html' title='Task of the day: convert a jpg image to 8-bit png'/><author><name>Nicolas Robidoux</name><uri>http://www.blogger.com/profile/01482580733771854842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/--ZNJwtHX4Ss/TgNa2x_EuoI/AAAAAAAAAB4/16-vMNoRd2k/s220/eye.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-3930862740580390025</id><published>2011-12-23T04:45:00.000-08:00</published><updated>2011-12-23T04:45:26.904-08:00</updated><title type='text'>new file format system</title><content type='html'>vips8 slowly creeps closer. A new system for loading and saving images has just arrived.&lt;br /&gt;&lt;br /&gt;You used to specify file formats and give them options like this:&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;$ vips im_vips2tiff myfile.v newfile.tiff:jpeg&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;meaning load the file myfile.v, then write it to newfile.tiff in TIFF format with jpeg compression.&lt;br /&gt;&lt;br /&gt;The vips8 equivalent is called tiffsave. If you run it with no arguments you get a nice help display:&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;$ vips tiffsave&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;usage:&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; tiffsave in filename&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;where:&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; in&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Image to save, input VipsImage&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; filename&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Filename to save to, input gchararray&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;optional arguments:&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; compression&amp;nbsp; - Compression for this file, input VipsTiffCompression&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; Q&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Q factor, input gint&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; predictor&amp;nbsp;&amp;nbsp;&amp;nbsp; - Compression prediction, input VipsTiffPredictor&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; profile&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - ICC profile to embed, input gchararray&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; tile&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Write a tiled tiff, input gboolean&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; tile-width&amp;nbsp;&amp;nbsp; - Tile width in pixels, input gint&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; tile-height&amp;nbsp; - Tile height in pixels, input gint&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; pyramid&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Write a pyramidal tiff, input gboolean&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; squash&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Squash images down to 1 bit, input gboolean&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; resunit&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Resolution unit, input VipsTiffResunit&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp; bigtiff&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Write a bigtiff image, input gboolean&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&amp;nbsp;and you can do the equivalent of the old vips7 command above like this:&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;$ vips tiffsave myfile.v newfile.tiff --compression jpeg&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;You can also embed options in the filename using the standard vips8 syntax. For example: &lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;$ vips invert fred.jpg jim.tif{compression=jpeg}&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;Which will load fred.jpg, invert it, then save as a jpeg-compressed tiff.&lt;br /&gt;&lt;br /&gt;The old vips7 system is still there and working, though it's now just a thin skin over the new system, so it's fully backwards-compatible. &lt;br /&gt;&lt;br /&gt;There's a very similar C API and it's also easy expressed in Python and C++. It's also easy to add support for new formats. We have &lt;a href="http://www.vips.ecs.soton.ac.uk/development/7.27/doc/libvips/VipsForeignSave.html"&gt;preliminary documentation &lt;/a&gt;and &lt;a href="https://github.com/jcupitt/libvips/tree/master/libvips/foreign"&gt;source code&lt;/a&gt; available.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-3930862740580390025?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/3930862740580390025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/12/new-file-format-system.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/3930862740580390025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/3930862740580390025'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/12/new-file-format-system.html' title='new file format system'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-2070337208825856617</id><published>2011-12-14T20:40:00.000-08:00</published><updated>2011-12-29T10:48:57.524-08:00</updated><title type='text'>Task of the day: autodetect CMYK and convert to sRGB JPEG</title><content type='html'>Adam Turcotte, John Cupitt and I have written a&amp;nbsp;C driver for libvips that produces an sRGB JPEG version of an image detected to be CMYK (and does nothing otherwise). The program is called &lt;b&gt;cmyk2srgbjpeg.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;USAGE: &lt;b&gt;cmyk2srgbjpeg&lt;/b&gt; &lt;i&gt;input_image output_image_name_before_extention&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, &lt;b&gt;cmyk2srgbjpeg&lt;/b&gt; checks whether&lt;i&gt;&amp;nbsp;input_image&lt;/i&gt; is CMYK. If not, it exits without further ado. Otherwise, &lt;b&gt;cmyk2srgbjpeg&lt;/b&gt; imports the input image using the embedded ICC profile (with&amp;nbsp;&lt;b&gt;im_icc_import_embedded)&lt;/b&gt; and converts the result to sRGB (with&amp;nbsp;&lt;b&gt;im_icc_export)&lt;/b&gt;. If there is no embedded ICC profile, or importing with the embedded profile fails (because the ICC is not compatible with CMYK, for example),&amp;nbsp;&lt;b&gt;cmyk2srgbjpeg&lt;/b&gt; substitutes a default and uses &lt;b&gt;im_icc_transform&lt;/b&gt;, which combines the above two operations. The result is saved in &lt;i&gt;output_image_name_before_extension&lt;/i&gt;.jpg.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;You need to compile this program. See the source code for pointers.&lt;br /&gt;&lt;br /&gt;Several options can be set through #defines:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The path to the backstop ICC colour profile (current default:&amp;nbsp;/usr/local/share/nip2/data/HP5000_UVDuraImageGlossMaxQ.icc);&lt;/li&gt;&lt;li&gt;The path to an sRGB colour profile (current default:&amp;nbsp;/usr/local/share/nip2/data/sRGB.icm);&lt;/li&gt;&lt;li&gt;The return codes (current default: &lt;b&gt;0&lt;/b&gt; if nothing was done (not CMYK), &lt;b&gt;1&lt;/b&gt; if the program failed, &lt;b&gt;2&lt;/b&gt; if conversion was performed with the backstop ICC because the embedded one "didn't work", &lt;b&gt;3&lt;/b&gt; if this was done because there was no embedded ICC, and &lt;b&gt;4&lt;/b&gt; if conversion was performed with the embedded ICC);&lt;/li&gt;&lt;li&gt;The JPEG quality setting (current default: 99);&lt;/li&gt;&lt;li&gt;The JPEG extension to be used for the output_image (current default: jpg); and&lt;/li&gt;&lt;li&gt;The color conversion "intent" (current default: relative colorimetric).&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;I could have had these set with command line options instead, but the program was written for a high volume server environment for which speed of execution (and a small executable) matter more than on the fly configurability.&lt;br /&gt;&lt;br /&gt;Code comments hopefully make everything clear.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It should be easy to modify this driver to perform similar tasks.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The code can be downloaded from &lt;a href="http://web.cs.laurentian.ca/nrobidoux/misc/cmyk2srgbjpeg.c"&gt;http://web.cs.laurentian.ca/nrobidoux/misc/cmyk2srgbjpeg.c&lt;/a&gt;. It is distributed under the Simplified BSD License. Improvements/bug reports/criticisms are welcome.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;P.S.&lt;/b&gt;&amp;nbsp;&lt;strike&gt;Crashes&lt;/strike&gt;&amp;nbsp;Now runs correctly on the apparently broken CMYK JPEG found at&amp;nbsp;&lt;a href="http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&amp;amp;t=19903&amp;amp;p=78647&amp;amp;hilit=cmyk#p78647"&gt;http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&amp;amp;t=19903&amp;amp;p=78647&amp;amp;hilit=cmyk#p78647&lt;/a&gt;. The ICC profile embedded in this image does not match its content: 3 band profile VS 4 band image.&amp;nbsp;&lt;b&gt;cmyk2srbgjpeg&lt;/b&gt; returns 2 and the result looks fine.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;P.S. II&lt;/b&gt;&amp;nbsp;You can poke around an image by loading it into &lt;b&gt;nip2&lt;/b&gt;, left clicking on the bar on the left of its thumbnail, menuing Toolkits -&amp;gt; Colour -&amp;gt; ICC -&amp;gt; Import, and tinkering with the options after having double clicked on the thumbnail of the result to see it full size. Even if using Toolkits -&amp;gt; Colour -&amp;gt; ICC -&amp;gt; Export on the result with an sRGB profile (or going to Toolkits -&amp;gt; Colourspace -&amp;gt; sRGB), you generally will not get exactly the same results as &lt;b&gt;cmyk2srgbjpeg&lt;/b&gt;, especially if the CMYK image has an embedded ICC profile which is understood by VIPS, because in this case the conversion is done in one step by &lt;b&gt;cmyk2srgbjpeg &lt;/b&gt;instead of two separate steps that go through a linear float image format as it's done in &lt;b&gt;nip2&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;P.S. III &lt;/b&gt;Adobe source of ICC profiles:&amp;nbsp;&lt;a href="http://www.adobe.com/support/downloads/detail.jsp?ftpID=4075"&gt;http://www.adobe.com/support/downloads/detail.jsp?ftpID=4075&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;P.S. IV &lt;/b&gt;Best&amp;nbsp;way to find CMYK images to test with AFAIK: google "cmyk.jpg" or "cmyk.jpeg" (taking the period out also works, as well as just googling "cmyk" or "cmyk images").&lt;br /&gt;&lt;br /&gt;&lt;b&gt;P.S. V &lt;/b&gt;Finally found a CMYK image (TIFF, not JPEG) that does not look good when passed through the program. It has no embedded ICC and appears to have been produced with a rather whacked one. It is discussed here:&amp;nbsp;&lt;a href="http://imagemagick.org/discourse-server/viewtopic.php?f=1&amp;amp;t=19717&amp;amp;p=79318#p79318"&gt;http://imagemagick.org/discourse-server/viewtopic.php?f=1&amp;amp;t=19717&amp;amp;p=79318#p79318&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;P.S. VI &lt;/b&gt;It's likely a TIFF ("Thousands of Incompatible File Formats") issue. See&amp;nbsp;&lt;a href="http://imagemagick.org/discourse-server/viewtopic.php?f=1&amp;amp;t=19717&amp;amp;p=79318#p79332"&gt;http://imagemagick.org/discourse-server/viewtopic.php?f=1&amp;amp;t=19717&amp;amp;p=79318#p79332&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-2070337208825856617?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/2070337208825856617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/12/task-of-day-autodetect-cmyk-and-convert.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/2070337208825856617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/2070337208825856617'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/12/task-of-day-autodetect-cmyk-and-convert.html' title='Task of the day: autodetect CMYK and convert to sRGB JPEG'/><author><name>Nicolas Robidoux</name><uri>http://www.blogger.com/profile/01482580733771854842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/--ZNJwtHX4Ss/TgNa2x_EuoI/AAAAAAAAAB4/16-vMNoRd2k/s220/eye.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-1031669004085754357</id><published>2011-11-17T04:09:00.001-08:00</published><updated>2011-11-17T04:59:54.573-08:00</updated><title type='text'>vips8 progress</title><content type='html'>vips8 is coming along quite quickly now. The core was done (more or less)in the last stable release so now in git master we are working through theoperations rewriting them as classes. We've done about 25% of the operationsin the last couple of months.&lt;br /&gt;&lt;br /&gt;One of the big new features is optional output arguments. For example,&lt;a href="https://github.com/jcupitt/libvips/blob/master/libvips/arithmetic/min.c"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VipsMin&lt;/span&gt;&lt;/a&gt; is an operation that finds the minimum value of an image. You canrun it from the command-line like this:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ vips min fred.jpg&lt;br /&gt;12&lt;/div&gt;&lt;/blockquote&gt;Very similar to the old &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;im_min&lt;/span&gt;. But now there are also optional outputarguments to get the position of the minimum:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ vips min --x --y fred.jpg&lt;br /&gt;12&lt;br /&gt;2345&lt;br /&gt;245&lt;/div&gt;&lt;/blockquote&gt;and you get the same API in Python, Ruby, Javascript, nip2, C and C++:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt; m = im.min()&lt;br /&gt;&amp;gt;&amp;gt; print m&lt;br /&gt;12&lt;br /&gt;&amp;gt;&amp;gt; m, x, y = im.min("x", "y")&lt;br /&gt;&lt;br /&gt;VipsImage *fred;&lt;br /&gt;double m;&lt;br /&gt;int x, y;&lt;br /&gt;&lt;br /&gt;vips_min( fred, &amp;amp;m,&lt;br /&gt;&amp;nbsp;&amp;nbsp;"x", &amp;amp;x,&lt;br /&gt;&amp;nbsp;&amp;nbsp;"y", &amp;amp;y,&lt;br /&gt;&amp;nbsp;&amp;nbsp;NULL );&lt;/div&gt;&lt;/blockquote&gt;Args only need a few of lines of code to add to a class and everythingelse is generated for you automatically at runtime. For example, theoptional &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;--x&lt;/span&gt; arg for &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VipsMin&lt;/span&gt; is declared like this:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VIPS_ARG_INT( class, "x", 2,&lt;br /&gt;&amp;nbsp;&amp;nbsp;_( "x" ), _( "Horizontal position of minimum" ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;VIPS_ARGUMENT_OPTIONAL_OUTPUT,&lt;br /&gt;&amp;nbsp;&amp;nbsp;G_STRUCT_OFFSET( VipsMin, x ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;0, 1000000, 0 );&lt;/div&gt;&lt;/blockquote&gt;That binds an optional int arg with the range locked to 0 to10000000 to the member x of the class &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VipsMin&lt;/span&gt;. Your bit of Cjust needs to assign that member and the value will appear in alllanguages and all interfaces.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://github.com/jcupitt/libvips/blob/master/libvips/conversion/join.c"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VipsJoin&lt;/span&gt;&lt;/a&gt; has one of the fanciest ones. At a minimum it's:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ vips join left.v right.v out.v horizontal&lt;/div&gt;&lt;/blockquote&gt;to join two images left-right, but there are also extra optional arguments, for example:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ vips join --expand --background 0,255,0 --align centre --shim 50left.v right.v out.v horizontal&lt;/div&gt;&lt;/blockquote&gt;to join left-right with a 50 pixel gap, the output expanded to holdall of both left and right, and the background painted green.&lt;br /&gt;&lt;br /&gt;You can get a summary of the options by running with no args:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ vips join&lt;br /&gt;VipsJoin (join), join an image&lt;br /&gt;&amp;nbsp;&amp;nbsp;join in1 in2 out direction&lt;br /&gt;where:&lt;br /&gt;&amp;nbsp;&amp;nbsp;in1 :: VipsImage (input)&lt;br /&gt;&amp;nbsp;&amp;nbsp;in2 :: VipsImage (input)&lt;br /&gt;&amp;nbsp;&amp;nbsp;out :: VipsImage (output)&lt;br /&gt;&amp;nbsp;&amp;nbsp;direction :: VipsDirection (input)&lt;br /&gt;optional arguments:&lt;br /&gt;&amp;nbsp;&amp;nbsp;align :: VipsAlign (input)&lt;br /&gt;&amp;nbsp;&amp;nbsp;expand :: gboolean (input)&lt;br /&gt;&amp;nbsp;&amp;nbsp;shim :: gint (input)&lt;br /&gt;&amp;nbsp;&amp;nbsp;background :: VipsArrayDouble (input)&lt;br /&gt;&lt;br /&gt;join: too few arguments&lt;br /&gt;VipsObject: parameter in1 to VipsJoin not set&lt;br /&gt;VipsObject: parameter in2 to VipsJoin not set&lt;br /&gt;VipsObject: parameter direction to VipsJoin not set&lt;/div&gt;&lt;/blockquote&gt;vips8 includes full vips7 compatibility. The old interface:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ vips im_lrjoin left.v right.v out.v&lt;/div&gt;&lt;/blockquote&gt;is still there and still works well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-1031669004085754357?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/1031669004085754357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/11/vips8-progress.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/1031669004085754357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/1031669004085754357'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/11/vips8-progress.html' title='vips8 progress'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-7048759489181981673</id><published>2011-10-01T08:35:00.000-07:00</published><updated>2011-10-01T08:35:57.907-07:00</updated><title type='text'>Streaming intro to VIPS video</title><content type='html'>&lt;a href="http://river-valley.tv/vips-an-image-processing-system-for-large-and-not-so-large-images/"&gt;Streaming river-valley.tv video of a seminar giving an overview of VIPS.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-7048759489181981673?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/7048759489181981673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/10/streaming-intro-to-vips-video.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/7048759489181981673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/7048759489181981673'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/10/streaming-intro-to-vips-video.html' title='Streaming intro to VIPS video'/><author><name>Nicolas Robidoux</name><uri>http://www.blogger.com/profile/01482580733771854842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/--ZNJwtHX4Ss/TgNa2x_EuoI/AAAAAAAAAB4/16-vMNoRd2k/s220/eye.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-6643890702690466811</id><published>2011-09-02T05:39:00.000-07:00</published><updated>2011-09-02T05:39:58.988-07:00</updated><title type='text'>Major new stable version, 7.26</title><content type='html'>The new version is finally officially out. Here's what's new:&lt;br /&gt;&lt;dl&gt;&lt;dt&gt; New operations&amp;nbsp;&lt;/dt&gt;&lt;dd&gt;nip2 has a few new menus for drawing, ImageMagick operators and matrix conversion. There's a new approximate convolution operator that can be more than 100x faster than standard convolution, see below.&lt;/dd&gt;&lt;/dl&gt;&lt;dl&gt;&lt;dt&gt; More permissive operators&amp;nbsp;&lt;/dt&gt;&lt;dd&gt;All vips operators will now convert their inputs if necessary. This means you can add two images of different sizes, for example, without having to expand one of them first, see below.&lt;/dd&gt;&lt;/dl&gt;&lt;dl&gt;&lt;dt&gt; Better file format support&amp;nbsp;&lt;/dt&gt;&lt;dd&gt;The TIFF, JPEG, PNG and FITS readers and writers have all seen useful improvements, see below.&lt;/dd&gt;&lt;/dl&gt;&lt;dl&gt;&lt;dt&gt; Faster nip2&amp;nbsp;&lt;/dt&gt;&lt;dd&gt;nip2 now starts quickly enough to not need a splash screen, and should feel more responsive when in use.&lt;/dd&gt;&lt;/dl&gt;&lt;dl&gt;&lt;dt&gt; VIPS rewrite&amp;nbsp;&lt;/dt&gt;&lt;dd&gt;The whole of vips has been cleaned up and reorganised. There's now gtk-doc documentation for the whole library. The vips core, iofuncs, has been replaced and is 5,000 lines smaller, simpler, and much more flexible. There's full source compatibility with the old API, but not binary, you will need to recompile, see below.&lt;/dd&gt;&lt;/dl&gt;Plus the usual minor speed-ups, portability improvements, enhancements and bug fixes.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;New operations&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;nip2 has a new menu: Filter / Magick. This has a number of simple ImageMagick filters wrapped up as nip2 operations. On Windows and OS X, nip2 includes its own copy of ImageMagick, so there are no other packages to install.&lt;br /&gt;&lt;br /&gt;There's a new Histogram / Convert to Histogram menu item which makes moving between images, matrices and histograms simpler.&lt;br /&gt;&lt;br /&gt;There are a set of new items in Matrix / New which make building matrices easier.&lt;br /&gt;&lt;br /&gt;Filter / Convolution / Custom Blur/Sharpen has a new precision setting, Approximate. This is slightly less accurate, but typically 10x faster. There's a lot of machinery behind the scenes to support this which needs writing up. It can actually do arbitrary 2D convolutions, though this isn't exposed yet.&lt;br /&gt;&lt;br /&gt;Another new menu, Image / Draw, lets you use the paintbox operations like flood, rectangle and circle from menus. This can be very handy for making masks.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;More permissive operators&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;libvips operators used to be rather strict. When adding two images, for example, they had to be exactly the same size. This seemed like a good idea, since it forced users to think about these issues, but it was also very annoying and caused endless mysterious error messages.&lt;br /&gt;&lt;br /&gt;libvips has a new philosophy: only fail with an error if you really have to. All operations will now do their best to do something, even if the images are not quite correct. All operations now automatically format-alike, band-alike and size-alike as much as they can.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;File formats&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The file format support has had quite a bit of work:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Better JPEG handling, including support for embedded thumbnails and decompression from memory.&lt;/li&gt;&lt;li&gt; Better PNG handling, including support for image resolution tags, 1, 2, 4 bit palette images, and the libpng-1.5 API.&lt;/li&gt;&lt;li&gt; Better TIFF handling, including faster loading and support for 1, 2, and 4 bit palette images.&lt;/li&gt;&lt;li&gt; Much faster FITS load and save, much lower memory use, better metadata support, FITS write.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;VIPS rewrite&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The vips rewrite has been going on for a few years now. 7.26 is probably the largest change so far: the old vips core has been removed and the whole library is now sitting on top of the new system we've been building. There's full compatibility with the old API, but the bones of a new, much better system are there.&lt;br /&gt;&lt;br /&gt;The next stage is to start rewriting all the operators to use the new API, and to expose the new system to C++, Python and other languages. There's a little more work necessary on the new C API as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-6643890702690466811?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/6643890702690466811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/09/major-new-stable-version-726.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/6643890702690466811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/6643890702690466811'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/09/major-new-stable-version-726.html' title='Major new stable version, 7.26'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-2980696631622347148</id><published>2011-08-12T04:58:00.000-07:00</published><updated>2011-08-12T04:58:17.311-07:00</updated><title type='text'>Animated clustering</title><content type='html'>I made this fun animation of protein clustering:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-1faac6096b03daa7" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v16.nonxt6.googlevideo.com/videoplayback?id%3D1faac6096b03daa7%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1332226477%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D2BFE8B646A3EB09DB5C511C621FC38BCE5197954.4F7D314CCCF0BBEA3CCDC56FA4DBAA6FAA048D79%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D1faac6096b03daa7%26offsetms%3D5000%26itag%3Dw160%26sigh%3Do8iSvyDBj8Iykro1vuSaoun1o1k&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v16.nonxt6.googlevideo.com/videoplayback?id%3D1faac6096b03daa7%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1332226477%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D2BFE8B646A3EB09DB5C511C621FC38BCE5197954.4F7D314CCCF0BBEA3CCDC56FA4DBAA6FAA048D79%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D1faac6096b03daa7%26offsetms%3D5000%26itag%3Dw160%26sigh%3Do8iSvyDBj8Iykro1vuSaoun1o1k&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;/div&gt;&lt;br /&gt;It uses nip2 to make the frames for the animation, I thought I'd write it up.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Background&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This is an experiment with a line of cultured cells. The cells were split into eight batches and each batch given a different treatment. We used &lt;a href="http://en.wikipedia.org/wiki/Proteomics"&gt;proteomics&lt;/a&gt; to find the abundance of the most interesting 1000 proteins in each batch. You get a table with 1000 columns and 8 rows, one row for each of the conditions, with the number at each point representing abundance.&lt;br /&gt;&lt;br /&gt;Proteins which are related in some way (perhaps they are part of the same bit of biological machinery) ought to rise and fall together as conditions for the cells vary, so we calculated a correlation coefficient for every column against every other column. This gives you a 1000 by 1000 matrix with numbers between -1 and 1. Proteins which are related should have a large number of high values in common.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Clustering&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;We wrote a &lt;a href="http://www.vips.ecs.soton.ac.uk/development/bicluster5.rb"&gt;small program&lt;/a&gt; in Ruby to search for the closest two proteins (proteins are closer if they share a larger number of highly correlated proteins), join them, and loop until there are no proteins that are close together. The results were interesting but it was hard to get much insight into what the patterns the program had found meant. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Animation&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To make the animation, we got the Ruby program to write out an interesting part of the matrix every time it joined two proteins. To make the images, start nip2, click File / Open. click on the first frame0001.csv, shift-click on the last, and click Open. This will make a large group of images and should be almost instant since it will only process the first few elements.&lt;br /&gt;&lt;br /&gt;Each pixel will have a value in -1 to 1, no good for false colour which needs pixels in 0 to 255. Enter "255 * A1 ** 2" to square each pixel and multiply by 255. Now select Filter / Enhance / False Colour to turn the frames into RGB heat maps. You can see one of the frames by selecting Object / Group to List to make a plain list out of the group, and then selecting Math / List / Head to get the first element (alternatively, enter "A3.value?0" as I did here).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-PIZr24qpv7A/TkUTG3-l9cI/AAAAAAAAAFk/ixlEBLYYA-w/s1600/-untitled+-+unsaved+workspace_001.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="313" src="http://4.bp.blogspot.com/-PIZr24qpv7A/TkUTG3-l9cI/AAAAAAAAAFk/ixlEBLYYA-w/s400/-untitled+-+unsaved+workspace_001.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Right-click on the group of RGB images and select Save. Enter "frame00001.png" for the filename and click OK. This will take a minute or so, since nip2 will actually have to process all the images.&lt;br /&gt;&lt;br /&gt;You can use ImageMagick to make a GIF of the clustering like this:&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ convert -delay 20 -loop 1 frame*.png cluster.gif&lt;/div&gt;&lt;br /&gt;Or mencoder to make an mpeg4 like this:&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ mencoder "mf://frame*.png" -mf fps=10 -o cluster.avi -ovc lavc -lavcopts vcodec=mpeg4&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-2980696631622347148?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/2980696631622347148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/08/animated-clustering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/2980696631622347148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/2980696631622347148'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/08/animated-clustering.html' title='Animated clustering'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-PIZr24qpv7A/TkUTG3-l9cI/AAAAAAAAAFk/ixlEBLYYA-w/s72-c/-untitled+-+unsaved+workspace_001.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-7097289152758523332</id><published>2011-08-09T08:02:00.000-07:00</published><updated>2011-08-09T13:46:49.445-07:00</updated><title type='text'>Assembling Marble Earth</title><content type='html'>NASA have a wonderful image of the earth on their website:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://visibleearth.nasa.gov/view_detail.php?id=7104"&gt;http://visibleearth.nasa.gov/view_detail.php?id=7104&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;However it's split into eight 21,600 by 21,600 pixel jpeg images. This blog post builds the image in nip2.&lt;br /&gt;&lt;br /&gt;Download all 8 and load them into nip2:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-xQab3UOqq_k/TkFDLPom0PI/AAAAAAAAAFc/yzYlxWVdPo0/s1600/untitled+-+unsaved+workspace_002.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/-xQab3UOqq_k/TkFDLPom0PI/AAAAAAAAAFc/yzYlxWVdPo0/s320/untitled+-+unsaved+workspace_002.png" width="269" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The tiles join in a simple grid. You can use the Image / Join / Left to Right and Image / Join / Top to Bottom menu items to make a set of pair-wise joins. Click A1 to select it, hold ctrl and click A2 to select that as well and click Image / Join / Top to Bottom. Repeat for all the vertical pairs, then use Left to Right to join those strips to make the final image. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-wV5UOif-pgc/TkFKvJB5UCI/AAAAAAAAAFg/G01vK7BISAg/s1600/A10+-+1-_003.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="206" src="http://2.bp.blogspot.com/-wV5UOif-pgc/TkFKvJB5UCI/AAAAAAAAAFg/G01vK7BISAg/s320/A10+-+1-_003.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;You could also use Image / Join / Array to build the mosaic. This menu item expects a 2D array of images and joins them in the obvious way. In the expression box, enter:&lt;br /&gt;&lt;br /&gt;[[A1, A3, A5, A7], [A2, A4, A6, A8]]&lt;br /&gt;&lt;br /&gt;To make the 2D array, then click Image / Join / Array to make the same image as above.&lt;br /&gt;&lt;br /&gt;You can't save this monster as a jpeg, sadly, since jpeg has a limit of 65535 pixels horizontally or vertically. The best option is probably jpeg-compressed tiled tiff. VIPS format also works well, but of course not many other packages can read it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-7097289152758523332?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/7097289152758523332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/08/assembling-marble-earth.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/7097289152758523332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/7097289152758523332'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/08/assembling-marble-earth.html' title='Assembling Marble Earth'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-xQab3UOqq_k/TkFDLPom0PI/AAAAAAAAAFc/yzYlxWVdPo0/s72-c/untitled+-+unsaved+workspace_002.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-6481499773262068406</id><published>2011-07-26T07:27:00.000-07:00</published><updated>2011-07-26T07:27:27.162-07:00</updated><title type='text'>First beta of major new version, 7.26</title><content type='html'>The first beta of the next major version of libvips and nip2, 7.26, has gone up on the &lt;a href="http://www.vips.ecs.soton.ac.uk/development/7.26/"&gt;development download page&lt;/a&gt;. It seems to pass all the tests and work for all our projects, but more testing is very welcome please. If all goes well, this will be released properly before the end of August.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A new philosophy&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;libvips operators used to be rather strict. When adding two images, for example, they had to be exactly the same size. This seemed like a good idea, since it forced users to think about these issues, but it was also very annoying and caused enless mysterious error messages.&lt;br /&gt;&lt;br /&gt;libvips has a new philosophy: only fail with an error if you really have to. All operations will no do their best to do something, even if the images are not quite correct. All operations now automatically format-alike, band-alike and size-alike as much as they can.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A new core&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This version has a completely new core for libvips. It's smaller, simpler, and much more modern. See &lt;b&gt;History&lt;/b&gt; below for some background on this.&lt;br /&gt;&lt;br /&gt;Large, crusty areas of libvips have been formally deprecated. Many fewer  command-line programs are installed. Goodbye, cooc_features! The old vips7 API is still supported, but you will need to recompile.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;nip2&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;nip2 hasn't changed that much, but there are a few new things:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Faster startup. It should start more quickly, so the annoying splashscreen has gone.&lt;/li&gt;&lt;li&gt;ImageMagick filters. There's a new menu, Filter / Magick, containing a selection of simple ImageMagick (or GraphicsMagick, depending on how you configure it) effects.&lt;/li&gt;&lt;li&gt;Draw menu. There's a new menu, Image / Draw, containing the paintbox functions as menu items. You can use them to do things like flood-fill images programmatically.&lt;/li&gt;&lt;li&gt;Added many new items to the Matrix / New menu, added Convert to Matrix.&lt;/li&gt;&lt;li&gt;Various small fixes and speedups.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;File format support&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The file format support has had quite a bit of work:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Better JPEG handling, including support for embedded thumbnails and decompression from memory.&lt;/li&gt;&lt;li&gt;Better PNG handling, including support for image resolution tags, 1, 2, 4 bit palette images, and the libpng-1.5 API.&lt;/li&gt;&lt;li&gt;Better TIFF handling, including faster loading and support for 1, 2, and 4 bit palette images.&lt;/li&gt;&lt;li&gt;Much faster FITS load and save, much lower memory use, better metadata support, FITS write. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Approximate convolution&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;We've added im_aconv(), approximate convolution. For large masks this can be more than 100x faster than im_conv(). This needs writing up in it's own post, I'll try and get to it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Minor improvements&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.vips.ecs.soton.ac.uk/development/7.26/doc/libvips/index.html"&gt;Full gtk-doc documentation for all operations&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;And as a consequence, no more man pages for libvips operations.&lt;/li&gt;&lt;li&gt;Updated German translation.&lt;/li&gt;&lt;li&gt;Various bugfixes, speedups and portability improvements.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;History&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;About 5 years ago, when nip2 was more-or-less done, we began work fixing up libvips, which had rotted somewhat during nip2's development. There were a couple of false starts but for the last few years we've had a clear plan and we've been making progress on a large-scale modernisation leading up to what should become vips8.&lt;br /&gt;&lt;br /&gt;Here's what vips7 looked like inside:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-Rqmm33kLVrQ/Ti64aGwjp3I/AAAAAAAAAEw/l1ExkS-wu4I/s1600/arch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="296" src="http://2.bp.blogspot.com/-Rqmm33kLVrQ/Ti64aGwjp3I/AAAAAAAAAEw/l1ExkS-wu4I/s320/arch.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;With nip2 in about the same place as the command-line interface. The big problem with this design is that a lot of useful things were added to higher levels of the system which could then not be shared. For example, the C++ binding added automatic reference counting which  was then used by Python. nip2 in a separate branch was unable to use this and had to have it's own reference counting system. Equally, nip2 has a very nice recent operation cache which can't be used from Python.&lt;br /&gt;&lt;br /&gt;The aim in the vips8 redesign is to improve the core so that these useful features can be pushed down into it and shared between all the interfaces. At the same time, the vips7 core was mostly unchanged since the early 1990s, so we wanted to clean it up and modernise it.&lt;br /&gt;&lt;br /&gt;Here's what libvips looks like inside now: &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Gp3hwbrT-r8/Ti7H6x3QbCI/AAAAAAAAAE0/6lD0MxPA0VU/s1600/arch8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="258" src="http://3.bp.blogspot.com/-Gp3hwbrT-r8/Ti7H6x3QbCI/AAAAAAAAAE0/6lD0MxPA0VU/s400/arch8.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The new system is based on &lt;a href="http://developer.gnome.org/gobject/stable/"&gt;GObject&lt;/a&gt;, Gnome's object system. We have a class on top of that with some extra features, then all libvips types are subclasses of that, including all operations. Some interfaces hang directly off VipsObject, others are bound via &lt;a href="http://live.gnome.org/GObjectIntrospection"&gt;GObject introspection&lt;/a&gt;, a system that lets almost any language use any GObject-based library.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://libvips.blogspot.com/2011/03/new-api-takes-shape.html"&gt;A post back in April&lt;/a&gt; introduced the new API, though it's actually changed a bit since then.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-6481499773262068406?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/6481499773262068406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/07/first-beta-of-major-new-version-726.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/6481499773262068406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/6481499773262068406'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/07/first-beta-of-major-new-version-726.html' title='First beta of major new version, 7.26'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-Rqmm33kLVrQ/Ti64aGwjp3I/AAAAAAAAAEw/l1ExkS-wu4I/s72-c/arch.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-2141381982470486121</id><published>2011-07-08T05:51:00.000-07:00</published><updated>2011-07-08T05:51:46.812-07:00</updated><title type='text'>New stable version, 7.24.7</title><content type='html'>We have a new stable version, 7.24.7. This has three small fixes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;im_conv(), the vips convolver, could lose accuracy with some masks&lt;/li&gt;&lt;li&gt; CMYK JPEG images were not being written correctly, thanks Ole&lt;/li&gt;&lt;li&gt;the TIFF reader can now also read 1, 2 and 4-bit palette images; previously it could only read 8-bit palette&lt;/li&gt;&lt;/ul&gt;There is a new source tarball and a new win32 binary. There's a new nip2 as well, though the only change is a larger set of self-tests.&lt;br /&gt;&lt;br /&gt;http://www.vips.ecs.soton.ac.uk/supported/7.24&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-2141381982470486121?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/2141381982470486121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/07/new-stable-version-7247.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/2141381982470486121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/2141381982470486121'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/07/new-stable-version-7247.html' title='New stable version, 7.24.7'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-7775864686092715285</id><published>2011-06-23T09:41:00.000-07:00</published><updated>2011-06-23T09:47:51.514-07:00</updated><title type='text'>Using ImageMagick from nip2</title><content type='html'>The &lt;a href="https://github.com/jcupitt/nip2"&gt;development version&lt;/a&gt; has an experimental link to ImageMagick in now, built more-or-less in the style of &lt;a href="http://libvips.blogspot.com/2011/04/nip2-as-gui-for-imagemagick.html"&gt;this earlier blog post&lt;/a&gt;. There's a Filter / Magick menu with five sample operations, the most complex of which is Annotate, the ImageMagick operation for adding text to an image.&lt;br /&gt;&lt;br /&gt;The sourcecode for the Annotate menu item is pretty simple:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Annotate_item = class &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; Menuaction "_Annotate" "add text annotation" {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; action x = class &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _result {&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _vislevel = 3;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; text = text_widget;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; font = Font_widget;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; geometry = Geometry_widget; &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gravity = gravity_widget; &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreground = foreground_widget;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; antialias = antialias_widget;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; command = magick_command (join_sep " " [&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; font._flag,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; antialias._flag,&amp;nbsp; &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; gravity._flag,&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreground._flag, &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "-annotate", geometry._flag, "\"" ++ text.value ++ "\""]);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _result = system command x;&amp;nbsp; &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;But goodness me it turns into a beast when you click it:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-txIzIlqJs0g/TgNpclol9zI/AAAAAAAAACA/6y939erXNaY/s1600/Screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="250" src="http://1.bp.blogspot.com/-txIzIlqJs0g/TgNpclol9zI/AAAAAAAAACA/6y939erXNaY/s400/Screenshot.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;It can probably be made a little prettier, but it does need all those options. I suppose sections could be folded away until you needed them.&lt;br /&gt;&lt;br /&gt;The menu item supports nip2 Groups, so you can select a set of images and operate on them all at once. There's a toggle in Preferences that lets you switch between ImageMagick and GraphicsMagick (it just prepends "gm" to the command line that gets run). The "command" item shows the command that nip2 is running to generate the image. It knows about adding a ".exe" to the end of the executable name on Windows, though I've not tested that yet.&lt;br /&gt;&lt;br /&gt;It seems unlikely that much of the wrapping could be generated automatically: it's just too hard to work out which options modify which operations. Someone would have to go through the docs and make a class for each major command. At least the things are fairly brief.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-7775864686092715285?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/7775864686092715285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/06/using-imagemagick-from-nip2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/7775864686092715285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/7775864686092715285'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/06/using-imagemagick-from-nip2.html' title='Using ImageMagick from nip2'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-txIzIlqJs0g/TgNpclol9zI/AAAAAAAAACA/6y939erXNaY/s72-c/Screenshot.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-8115075113327237126</id><published>2011-05-23T03:10:00.000-07:00</published><updated>2011-05-23T03:34:09.386-07:00</updated><title type='text'>Image annotation with libvips and Python</title><content type='html'>I had a mail asking how to replace a bit of ImageMagick with libvips and Python. Here it is, wrapped up as a blog post. &lt;br /&gt;&lt;br /&gt;First, here's the ImageMagick:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;#!/bin/sh&lt;br /&gt;&lt;br /&gt;convert $1 \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -background Red -density 300 \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -font /usr/share/fonts/truetype/msttcorefonts/Arial.ttf \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -pointsize 12 -gravity south -splice 0x150 \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -gravity southwest -annotate +50+50 "left corner" \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -gravity southeast -annotate +50+50 'right corner' \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; +repage \&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $2&lt;/span&gt;&lt;/blockquote&gt;This adds a 150-pixel-high red banner to the bottom of an image, for example:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-O9u9NCzfzOY/Tdohrlob_tI/AAAAAAAAAB8/tb9R3N-Bo3c/s1600/test2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="300" src="http://2.bp.blogspot.com/-O9u9NCzfzOY/Tdohrlob_tI/AAAAAAAAAB8/tb9R3N-Bo3c/s320/test2.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;And here's the same thing in Python using libvips. It is rather fiddly, unfortunately:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;#!/usr/bin/python&lt;br /&gt;&lt;br /&gt;import sys&lt;br /&gt;from vipsCC import *&lt;br /&gt;&lt;br /&gt;im = VImage.VImage(sys.argv[1])&lt;br /&gt;&lt;br /&gt;zero = VImage.VImage.black(im.Xsize(), 150, 3)&lt;/span&gt;&lt;/blockquote&gt;Next we make a red image from the black (zero) image. im.&lt;a href="http://www.vips.ecs.soton.ac.uk/supported/7.24/doc/html/libvips/libvips-arithmetic.html#im-lintra-vec"&gt;lin&lt;/a&gt;(a, b) calculates (im * a + b), that is, it does a linear transform (hence the name). You can pass a number for a and b, or a list. If you pass a list, one list element is used for each image band. So therefore this adds 255 to the first band. The result of lin() is always float, so you need to cast back to 8-bit afterwards.&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;red = zero.lin([1, 1, 1], [255, 0, 0]).clip2fmt(VImage.VImage.FMTUCHAR)&lt;/span&gt;&lt;/blockquote&gt;&lt;a href="http://www.vips.ecs.soton.ac.uk/supported/7.24/doc/html/libvips/libvips-conversion.html#im-text"&gt;text&lt;/a&gt;(string, font, width, slignment, dpi) renders text with &lt;a href="http://www.pango.org"&gt;Pango&lt;/a&gt;. The text is rendered to fit to a maximum width (-1 meaning no width limit). The image is always one band, 8-bit, with 0 meaning background, 255 meaning text, and intermediate values being used for anti-aliasing.&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;txt = VImage.VImage.text("left corner", "sans 12", -1, 0, 300)&lt;/span&gt;&lt;/blockquote&gt;im.&lt;a href="http://www.vips.ecs.soton.ac.uk/supported/7.24/doc/html/libvips/libvips-conversion.html#im-embed"&gt;embed&lt;/a&gt;(type, left, top, width, height) 'embeds' im within a larger image of size (width, height) at position (left, top). The 'type' field sets how the new background pixels are created: 0 means 'fill with zero'.&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;txt = txt.embed(0, 50, 50, im.Xsize(), 150)&lt;br /&gt;&lt;br /&gt;txt2 = VImage.VImage.text("right corner", "sans 12", -1, 0, 300)&lt;br /&gt;txt2 = txt2.embed(0, im.Xsize() - txt2.Xsize() - 50, 50, im.Xsize(), 150)&lt;br /&gt;&lt;br /&gt;txt = txt.orimage(txt2)&lt;/span&gt;&lt;/blockquote&gt;condition.&lt;a href="http://www.vips.ecs.soton.ac.uk/supported/7.24/doc/html/libvips/libvips-relational.html#im-blend"&gt;blend&lt;/a&gt;(a, b) uses the condition image to blend between images a and b. Here we are using the text mask to blend between the red background and the black foreground.&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;txt = txt.blend(zero, red)&lt;/span&gt;&lt;/blockquote&gt;Finally, big.&lt;a href="http://www.vips.ecs.soton.ac.uk/supported/7.24/doc/html/libvips/libvips-conversion.html#im-insert"&gt;insert&lt;/a&gt;(small, left, top) pastes image small into image big at position (left, top), expanding the image as necessary.&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;im = im.insert(txt, 0, im.Ysize())&lt;br /&gt;&lt;br /&gt;im.write(sys.argv[2])&lt;/span&gt;&lt;/blockquote&gt;And we're done.&lt;br /&gt;&lt;br /&gt;On the plus side, because it's done with a 'real' programming language, you have a lot more flexibility in the way you do the layout. You could write a set of little functions to do the layout for you, and perhaps do a better job of centering the text.&lt;br /&gt;&lt;br /&gt;Benchmarking with a 5,000 by 5,000 pixel RGB image on my desktop machine, I get:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;$ time&amp;nbsp; ./try70.sh wtc_small.tif test2.tif&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;real&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m1.179s&lt;br /&gt;user&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m0.880s&lt;br /&gt;sys&amp;nbsp; &amp;nbsp;&amp;nbsp; 0m0.650s&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;peak RSS 400m &lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;$ time&amp;nbsp; ./try71.py wtc_small.tif test2.tif&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;real&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m0.549s&lt;br /&gt;user&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m0.290s&lt;br /&gt;sys&amp;nbsp; &amp;nbsp;&amp;nbsp; 0m0.330s&lt;br /&gt;peak RSS 25m&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;So libvips is about twice as fast in this case and needs a lot less memory. Repeating with a 10,000 x 10,000 pixel RGB TIFF image, I get:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;$ time ./try70.sh wtc.tif wtc2.tif&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;real&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m4.050s&lt;br /&gt;user&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m2.770s&lt;br /&gt;sys&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m2.200s&lt;br /&gt;peak RSS 1.3g&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;$ time ./try71.py wtc.tif wtc2.tif&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;real&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m3.206s&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;user&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m0.970s&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sys&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0m1.530s&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;peak RSS 25m&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;So vips needs roughly constant memory regardless of image size. The speed gain becomes smaller as the images become larger, since less time is spent processing and more time is spent reading and writing tiff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-8115075113327237126?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/8115075113327237126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/05/image-annotation-with-libvips-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/8115075113327237126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/8115075113327237126'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/05/image-annotation-with-libvips-and.html' title='Image annotation with libvips and Python'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-O9u9NCzfzOY/Tdohrlob_tI/AAAAAAAAAB8/tb9R3N-Bo3c/s72-c/test2.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-6004760869989982551</id><published>2011-05-16T03:46:00.000-07:00</published><updated>2011-05-16T03:46:25.824-07:00</updated><title type='text'>Using groups in nip2</title><content type='html'>&lt;a href="http://www.vips.ecs.soton.ac.uk/index.php?title=Nip2"&gt;nip2&lt;/a&gt; lets you group objects so you can use the menus to operate on many images at the same time. This post will try to explain how to use the grouping system and how it works.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Overview&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;Let's start with a quick example. Launch nip2, click File / Open, and navigate to a directory of images. Click on the first, shift-click on the last and click Open. You can open up to about 500 images at once, but please don't for this example, five is plenty. The main window should now look something like this:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-cB1TE3-w_nU/TdDvBkvIHpI/AAAAAAAAABo/05VwxmjdHUk/s1600/Screenshot-19.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="247" src="http://2.bp.blogspot.com/-cB1TE3-w_nU/TdDvBkvIHpI/AAAAAAAAABo/05VwxmjdHUk/s320/Screenshot-19.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Right-click on the row button and click Ungroup to open the group. This creates a new row for every group element. It will be unbearably slow for 500 images, but for five it works fine. &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-ObFQa7N5eW8/TdDvjEavklI/AAAAAAAAABs/ViTEMV0suYc/s1600/Screenshot-20.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="247" src="http://3.bp.blogspot.com/-ObFQa7N5eW8/TdDvjEavklI/AAAAAAAAABs/ViTEMV0suYc/s320/Screenshot-20.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Remove the extra rows you made (click on A2, shift-click on the last row, click Edit / Delete). Now click Filter / Convolution / Custom Blur/Sharpen, and set the parameters to be a Gaussian blur. You could pick any other operation, or any combination of operations.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-HfLgUcp4t0Y/TdDxD67zQKI/AAAAAAAAABw/hidDRrkOSKk/s1600/Screenshot-21.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="247" src="http://3.bp.blogspot.com/-HfLgUcp4t0Y/TdDxD67zQKI/AAAAAAAAABw/hidDRrkOSKk/s320/Screenshot-21.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Finally, right-click on the row button for the processed group and select Save As. Enter a filename of the form fred001.jpg and nip2 will save the processed images to fred001.jpg, fred002.jpeg, and so on.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Grouping and ungrouping&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;There are several ways to form groups. You can make them directly in the file chooser as above, but you can also form them from objects already in the workspace. Click on the first row, shift-click on the last, and select Edit / Group.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Ts-jrv4HVi4/TdDymQYYOUI/AAAAAAAAAB0/X74N1RB2zmw/s1600/Screenshot-22.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="247" src="http://1.bp.blogspot.com/-Ts-jrv4HVi4/TdDymQYYOUI/AAAAAAAAAB0/X74N1RB2zmw/s320/Screenshot-22.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Groups can contain any other object, even other groups.&lt;br /&gt;&lt;br /&gt;You can also form groups by typing. Enter (for example):&lt;br /&gt;&lt;blockquote style="font-family: Arial,Helvetica,sans-serif;"&gt;Group [1 .. 4]&lt;/blockquote&gt;You can turn lists into groups and back again, see Object / List to Group and friends. Once a group has been turned to a list, you can use any of the usual list-processing operations to operate on them.&lt;br /&gt;&lt;br /&gt;Saving a group will save each of the group elements in turn. You can also ungroup with Edit / Ungroup, though that won't work very well for large groups. For large groups it's usually better to turn the group to a list, then pick out a particular element with list index. This is easy to type:&lt;br /&gt;&lt;blockquote style="font-family: Arial,Helvetica,sans-serif;"&gt;A15.value?1&lt;/blockquote&gt;Will extract element 1 from a group.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Processing&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;Almost all of nip2's menu items will automatically loop over groups, as we saw in the introductory example. Almost all of the built-in operations will automatically loop as well. For example, try typing:&lt;br /&gt;&lt;blockquote style="font-family: Arial,Helvetica,sans-serif;"&gt;12 + Group [1 .. 4]&lt;/blockquote&gt;and you'll see&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;Group [13, 14, 15, 16]&lt;/div&gt;&lt;/blockquote&gt;The system is very general. Going back to the example in the screenshot above typing &lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;A15 + 99&lt;/span&gt; gives this:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-0EwQzfamjhc/TdD2uPdt9_I/AAAAAAAAAB4/3ESxtz_2v9k/s1600/Screenshot-23.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="247" src="http://1.bp.blogspot.com/-0EwQzfamjhc/TdD2uPdt9_I/AAAAAAAAAB4/3ESxtz_2v9k/s320/Screenshot-23.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Groups can have NULL elements, meaning 'skip this item'. This is handy in complex workspaces where not every group element may be valid. If you operate on a pair of groups and one contains a NULL element at some point, the result will also be NULL at that point.&lt;br /&gt;&lt;br /&gt;If one group is longer than the other, the results is as long as the shortest group.&lt;br /&gt;&lt;br /&gt;A convenient way to develop a workspace is to start out processing a single image, then when everything is working, edit the first row to drop in a group instead. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: large;"&gt;Limitations&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;Very large groups don't work very well: you'll find you start to run out of file descriptors if you have more than about 500 source images open at once. For very large jobs you'll be better off using nip2's command-line interface to run a workspace over a set of files.&lt;br /&gt;&lt;br /&gt;For technical reasons, nip2's list processing operations don't work well with groups. You'll find you can't type &lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;hd A1&lt;/span&gt;, where &lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;A1&lt;/span&gt; is a group of lists, for example. Fixing this would take a large rewrite of nip2's programming language, sadly.&lt;br /&gt;&lt;br /&gt;You also can't use Region on groups, annoyingly. This means that if your workspace includes any regions dragged out with the mouse, you won't be able to just drop a group in. Use Image / Crop instead.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-6004760869989982551?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/6004760869989982551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/05/using-groups-in-nip2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/6004760869989982551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/6004760869989982551'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/05/using-groups-in-nip2.html' title='Using groups in nip2'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-cB1TE3-w_nU/TdDvBkvIHpI/AAAAAAAAABo/05VwxmjdHUk/s72-c/Screenshot-19.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-8386931818410217817</id><published>2011-05-03T06:52:00.001-07:00</published><updated>2011-05-25T06:17:51.374-07:00</updated><title type='text'>Building VIPS for Windows</title><content type='html'>&lt;a href="http://lh4.ggpht.com/_0vNEItollDg/TcAIbyiMrUI/AAAAAAAAABU/S1iJD-dzXrs/s1600-h/image%5B4%5D.png"&gt;&lt;img align="right" alt="image" border="0" height="116" src="http://lh3.ggpht.com/_0vNEItollDg/TcAIcRvNpwI/AAAAAAAAABY/j8ZfjdgYS4w/image_thumb%5B2%5D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; float: right; margin: 0px 5px 5px 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="192" /&gt;&lt;/a&gt;[&lt;b&gt;Update 25/2/11&lt;/b&gt;: Rob's improvements have been merged back into the main win32 build system, with some small changes, and I've updated this post to reflect this]&lt;br /&gt;&lt;br /&gt;VIPS (as well as NIP) has an excellent history of providing executables to the Windows users of the world with &lt;a href="http://www.vips.ecs.soton.ac.uk/supported/"&gt;regular stable releases&lt;/a&gt;.&lt;br /&gt;Yet there always seems to be one individual who does not desire to wait for the next stable release, and would really like to see a windows executable with the &lt;a href="https://github.com/jcupitt/libvips/commits/master/"&gt;latest patch&lt;/a&gt; built sooner. &lt;br /&gt;That guy is usually me! Particularly once &lt;a href="https://github.com/jcupitt"&gt;John&lt;/a&gt; resolved the &lt;a href="https://github.com/jcupitt/libvips/commit/f13bf34ce3252c5129e24ab2a0200a2a5be12b73"&gt;n-bit palette tiff reader bug&lt;/a&gt; recently. However, there is no Visual Studio build for VIPS, and the normal &lt;a href="http://en.wikipedia.org/wiki/Configure_script_%28computing%29"&gt;./configure&lt;/a&gt; &amp;amp;&amp;amp; &lt;a href="http://en.wikipedia.org/wiki/Makefile"&gt;make&lt;/a&gt; &amp;amp;&amp;amp; &lt;a href="http://en.wikipedia.org/wiki/Makefile"&gt;make install&lt;/a&gt; commands tend to fail horribly on a non-UNIX platform.&lt;br /&gt;&lt;h1&gt;Why No Visual Studio Build?&lt;/h1&gt;&lt;a href="http://lh3.ggpht.com/_0vNEItollDg/TcAIc32rVRI/AAAAAAAAABc/ZQfFOrge0dk/s1600-h/image%5B7%5D.png"&gt;&lt;img align="left" alt="image" border="0" height="92" src="http://lh4.ggpht.com/_0vNEItollDg/TcAIdaxWo5I/AAAAAAAAABg/l0qJtUatY4c/image_thumb%5B3%5D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; float: left; margin: 5px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="216" /&gt;&lt;/a&gt;It is all about the dependencies. VIPS has approximately thirty libraries that it depends on, and all of those libraries are native *nix libraries. In order to compile VIPS in Visual Studio, you would need to find win32 Dynamic Linked Libraries (DLLs) compiled for each. No easy task, as many of them do not provide a supported win32 build.&lt;br /&gt;Your other option is build each of the libraries yourself and thus provide your own win32 DLL for linking with VIPS. While a noble idea, and one I would love to see someone else make happen, this quickly becomes complicated by the fact that the libraries that need to be compiled have other dependencies themselves. You quickly find that the number of builds you must support in order to manage building VIPS grows to something even more daunting than the dependencies VIPS is directly linked against.&lt;br /&gt;&lt;h1&gt;Cross Compiling - MinGW&lt;/h1&gt;&lt;b&gt;&lt;a href="http://www.mingw.org/"&gt;MinGW&lt;/a&gt;&lt;/b&gt; provides a complete Open Source programming tool set which is suitable for the development of native MS-Windows applications,&lt;a href="http://lh5.ggpht.com/_0vNEItollDg/TcAIe4xdOzI/AAAAAAAAABk/xEiDpx-DbRc/s1600-h/image%5B10%5D.png"&gt;&lt;img align="right" alt="image" border="0" height="59" src="http://lh6.ggpht.com/_0vNEItollDg/TcAIfW2QubI/AAAAAAAAABo/v_TyGATdLdo/image_thumb%5B4%5D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; float: right; margin: 5px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="150" /&gt;&lt;/a&gt; and which do not depend on any 3rd-party C-Runtime DLLs. (It &lt;i&gt;&lt;b&gt;does&lt;/b&gt;&lt;/i&gt; depend on a number of DLLs provided by Microsoft themselves, as components of the operating system; most notable among these is MSVCRT.DLL, the Microsoft C runtime library. Additionally, threaded applications &lt;i&gt;&lt;b&gt;must&lt;/b&gt;&lt;/i&gt; ship with a freely distributable thread support DLL, provided as part of &lt;b&gt;&lt;a href="http://www.mingw.org/"&gt;MinGW&lt;/a&gt;&lt;/b&gt; itself). &lt;br /&gt;Although primarily geared towards developers working on the MS-Windows platform itself, we run a cross-compiler variant of the &lt;b&gt;&lt;a href="http://www.mingw.org/"&gt;MinGW&lt;/a&gt;&amp;nbsp;&lt;/b&gt;tools on &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; to generate win32 applications for deployment to MS-Windows.&lt;br /&gt;&lt;h2&gt;What About Those Libraries?&lt;/h2&gt;&lt;a href="http://lh3.ggpht.com/_0vNEItollDg/TcAIfrBQdAI/AAAAAAAAABs/VNe_Y9FESHY/s1600-h/image%5B14%5D.png"&gt;&lt;img align="left" alt="image" border="0" height="140" src="http://lh5.ggpht.com/_0vNEItollDg/TcAIgaBXvRI/AAAAAAAAABw/K4I_xpQTGuM/image_thumb%5B6%5D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; float: left; margin: 5px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="99" /&gt;&lt;/a&gt;The GNOME project has us covered, given that they do quite a bit of work with &lt;a href="http://www.winehq.org/download"&gt;WINE&lt;/a&gt; and other windows emulators, they need &lt;a href="http://wget%20ftp//ftp.gnome.org/pub/GNOME/binaries/win32/"&gt;a large number of libraries compiled as DLLs&lt;/a&gt; as well!&lt;br /&gt;Someone very clever is about to ask, “Why don’t we just use the GNOME DLL’s as our Visual Studio Links?” Unfortunately, it's difficult to target MSVCRT.DLL in VS, unless you start doing tricks with the driver development toolkit. It is sort-of possible to mix C runtimes in one program, but really not advisable.&lt;br /&gt;The more appropriate answer is that &lt;a href="https://github.com/jcupitt"&gt;John&lt;/a&gt; already had a &lt;a href="http://live.gnome.org/Jhbuild"&gt;JHBUILD&lt;/a&gt; setup to take advantage of &lt;b&gt;&lt;a href="http://www.mingw.org/"&gt;MinGW&lt;/a&gt; &lt;/b&gt;on &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt;, and it worked. Certainly far easier than tackling the creation of a Windows Build.&lt;br /&gt;&lt;h1&gt;Getting Started&lt;/h1&gt;Head over to &lt;a href="https://github.com/"&gt;github&lt;/a&gt; and grab the latest from the&amp;nbsp;&lt;a href="https://github.com/jcupitt/build-win32"&gt;jcupitt/build-win32&lt;/a&gt; repository.&amp;nbsp;From there, take a quick peak at the README information that shows up at the bottom of the page. For the 7.24 build, it looks something like this:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 13px;"&gt;&lt;span class="name" style="font-size: 19px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.8em; padding-left: 0px; padding-right: 0px; padding-top: 0.8em;"&gt;7.24/README.md&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="wikistyle" style="background-color: #f8f8f8; border-bottom-color: rgb(233, 233, 233); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(233, 233, 233); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(233, 233, 233); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(233, 233, 233); border-top-style: solid; border-top-width: 1px; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 13px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.7em; padding-left: 0.7em; padding-right: 0.7em; padding-top: 0.7em;"&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: initial !important; border-top-style: none !important; border-top-width: initial !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.25em !important;"&gt;VIPS WIN32&lt;/h1&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;We use jhbuilder to git, mingw to compile, and good old zip to package the vips source code for WIN32.&lt;/div&gt;&lt;h2 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(224, 224, 224) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 20px; line-height: 1.4em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;&lt;a href="http://live.gnome.org/Jhbuild" style="color: #4183c4; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: none; outline-width: initial; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;JHBuild&lt;/a&gt;&lt;/h2&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;JHBuild is a tool designed to ease building collections of source packages, called “modules”. JHBuild uses “module set” files to describe the modules available to build. The “module set” files include dependency information that allows JHBuild to discover what modules need to be built and in what order.&lt;/div&gt;&lt;h2 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(224, 224, 224) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 20px; line-height: 1.4em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;&lt;a href="http://www.mingw.org/" style="color: #4183c4; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: none; outline-width: initial; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;MinGW&lt;/a&gt;&lt;/h2&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;MinGW, a contraction of "Minimalist GNU for Windows", is a minimalist development environment for native Microsoft Windows applications.&lt;/div&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;MinGW provides a complete Open Source programming tool set which is suitable for the development of native MS-Windows applications, and which do not depend on any 3rd-party C-Runtime DLLs. (It does depend on a number of DLLs provided by Microsoft themselves, as components of the operating system; most notable among these is MSVCRT.DLL, the Microsoft C runtime library. Additionally, threaded applications must ship with a freely distributable thread support DLL, provided as part of MinGW itself).&lt;/div&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(170, 170, 170) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;PREREQUISITES&lt;/h1&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="http://www.ubuntu.com/desktop/get-ubuntu/download" style="color: #4183c4; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: none; outline-width: initial; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;Ubuntu Desktop&lt;/a&gt;&amp;nbsp;- This doesn't mean you can't get the process to work on anything else. This is simply what we are using and know to work. Tested on 10.10 and 11.04, 32- and 64-bit. Though you can only make a 32-bit Windows binary for now.&lt;/div&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(170, 170, 170) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;OPTIONAL&lt;/h1&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;&lt;a href="http://www.vmware.com/products/player/" style="color: #4183c4; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: none; outline-width: initial; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;VMware Player&lt;/a&gt;&amp;nbsp;- Bubba runs his Ubuntu Desktop in a VMWare Player on a Windows 7 Ultimate x64 Desktop host.&lt;/div&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(170, 170, 170) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;&lt;a href="http://xkcd.com/754/" style="color: #4183c4; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: none; outline-width: initial; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none;"&gt;DEPENDENCIES&lt;/a&gt;&lt;/h1&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;It is possible that you already have some of these installed on your Ubuntu Desktop; however, it is not likely that you have all of them. Better safe than sorry, install them all. You might even want to update the whole kit, just for the heck of it.&lt;/div&gt;&lt;h2 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(224, 224, 224) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 20px; line-height: 1.4em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;Build/Tool Related Dependencies&lt;/h2&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;sudo apt-get install build-essential \&lt;br /&gt;wine \&lt;br /&gt;mingw32 \&lt;br /&gt;jhbuild \&lt;br /&gt;autoconf \&lt;br /&gt;automake1.4 \&lt;br /&gt;automake1.7 \&lt;br /&gt;automake1.9 \&lt;br /&gt;autotools-dev \&lt;br /&gt;docbook-utils \&lt;br /&gt;docbook2x \&lt;br /&gt;gtk-doc-tools&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(224, 224, 224) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 20px; line-height: 1.4em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;Library Dependencies&lt;/h2&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;sudo apt-get install libatk1.0-0 \&lt;br /&gt;libatk1.0-dev \&lt;br /&gt;libglib2.0-0 \&lt;br /&gt;libglib2.0-dev \&lt;br /&gt;libgtk2.0-0 \&lt;br /&gt;libgtk2.0-dev \&lt;br /&gt;libglade2-0 \&lt;br /&gt;libglade2-dev \&lt;br /&gt;libgsf-1-114 \&lt;br /&gt;libgsf-gnome-1-dev \&lt;br /&gt;libpango1.0-0 \&lt;br /&gt;libpango1.0-dev \&lt;br /&gt;libcairo2 \&lt;br /&gt;libcairo2-dev \&lt;br /&gt;libexpat1 \&lt;br /&gt;libexpat1-dev \&lt;br /&gt;libfontconfig1 \&lt;br /&gt;libfontconfig1-dev \&lt;br /&gt;libfreetype6 \&lt;br /&gt;libfreetype6-dev \&lt;br /&gt;gettext \&lt;br /&gt;libpng12-0 \&lt;br /&gt;libpng12-dev \&lt;br /&gt;libxml2 \&lt;br /&gt;libxml2-dev \&lt;br /&gt;tango-icon-theme \&lt;br /&gt;libcxxtools6 \&lt;br /&gt;libcxxtools-dev \&lt;br /&gt;zlib1g \&lt;br /&gt;zlib1g-dev \&lt;br /&gt;zlibc &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;These are Ubuntu binaries and of course we will be building a Windows binary. However, some of the packages we build are not very good at cross-compiling and builds can fail unless they can find a native library as well.&lt;/div&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(170, 170, 170) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;CONFIGURATION&lt;/h1&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;You will need to first check out this repository, if you haven't already.&lt;/div&gt;&lt;h2 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(224, 224, 224) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 20px; line-height: 1.4em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;git This&lt;/h2&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;mkdir ~/dev&lt;br /&gt;cd ~/dev&lt;br /&gt;git clone git://github.com/jcupitt/build-win32.git&lt;br /&gt;cd build-win32/7.24&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(224, 224, 224) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 20px; line-height: 1.4em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;GNOME win32 Packages&lt;/h2&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;As we are building a win32 executable, we need some DLLs to link against, and the GNOME project kindly provides us with a large number of these ready to use!&lt;/div&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;Run this script to create some directories for zips, tarballs and the build tree and download all the zips you need from Gnome:&lt;/div&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;./get-win32-packages.sh&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;If you desire to modify the packages used, just open up the script and edit the list near the end. This is completely optional though, as the ones checked out "should" work just fine for you needs.&lt;/div&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;After downloading, run the unpack script to unzip the files to your build area:&lt;/div&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;./unpack.sh&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(170, 170, 170) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;JHBUILD VERIFICATION&lt;/h1&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;We just want to make sure that jhbuild has everything it needs. If all steps have been properly followed up to this point, this should be a no brainer.&lt;/div&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;jhbuild --file=jhbuildrc sanitycheck&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;This will most likely complain that it couldn't find automake-1.8 which is fine, we didn't install that. If it complains about anything else, let me know.&lt;/div&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(170, 170, 170) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;BUILD&lt;/h1&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;jhbuild --file=jhbuildrc --moduleset=vips.modules build libvips&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(170, 170, 170) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;PACKAGE&lt;/h1&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;./package-vipsdev.sh&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(170, 170, 170) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;BUILD NIP2&lt;/h1&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;jhbuild --file=jhbuildrc --moduleset=vips.modules build nip2&lt;br /&gt;&lt;br /&gt;./package-nip2.sh&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(170, 170, 170) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;UPLOAD YOUR PACKAGE&lt;/h1&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;Assuming everything has worked perfectly up to this point, you will find vips-dev-7.24.5.zip all packaged up and ready to go. You might upload it to your favorite server via scp like this:&lt;/div&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;scp vips-dev-7.24.5.zip &amp;lt;YOURID&amp;gt;@&amp;lt;YOURSERVER&amp;gt;:/your/favorite/directory&lt;br /&gt;&lt;br /&gt;scp nip2-7.24.5-setup.exe &amp;lt;YOURID&amp;gt;@&amp;lt;YOURSERVER&amp;gt;:/your/favorite/directory&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(170, 170, 170) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;CLEAN UP&lt;/h1&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;It is always good to clean up after yourself. Be careful though, this command will delete the package you just created! You did upload it to your favorite server didn't you?&lt;/div&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;./clean.sh&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;You'll need to run the unpack script again if you clean up. You won't need to redownload the zips though.&lt;/div&gt;&lt;h1 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(170, 170, 170) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 23px; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;OTHER NOTES&lt;/h1&gt;&lt;h2 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(224, 224, 224) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 20px; line-height: 1.4em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;Version Numbers&lt;/h2&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;The scripts currently default to a versioning system of package-major.minor.micro-release like so 7.24.5-1 in order to make everything drop dead simple.&lt;/div&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;However, it is really preferred for you to version your own package micro-releases.&lt;/div&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;You can modify the versions by editing these scripts:&lt;/div&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;clean.sh&lt;br /&gt;package-vipsdev.sh&lt;br /&gt;package-nip2.sh&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 style="border-bottom-width: 0px !important; border-color: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-color: rgb(224, 224, 224) !important; border-top-style: solid !important; border-top-width: 4px !important; font-size: 20px; line-height: 1.4em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1.5em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0.5em !important;"&gt;Patching&lt;/h2&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;A primary reason one might desire to build their own executable, you simply want to make a few changes to the code, or otherwise control how it was compiled.&lt;/div&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;First, build as described above:&lt;/div&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;./unpack.sh&lt;br /&gt;&lt;br /&gt;jhbuild --file=jhbuildrc --moduleset=vips.modules build libvips&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;Now go to checkout/vips-7.24.5 and make any source changes you want. Build again to compile your changes.&lt;/div&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;jhbuild --file=jhbuildrc --moduleset=vips.modules build libvips&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;And package your new version.&lt;/div&gt;&lt;pre style="-webkit-box-shadow: rgba(0, 0, 0, 0.0664062) 0px 1px 2px inset; background-color: #eeeeee; border-bottom-color: rgb(221, 221, 221); border-bottom-left-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(221, 221, 221); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(221, 221, 221); border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-top-style: solid; border-top-width: 1px; color: #444444; font-size: 12px; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.5em; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 1em; overflow-x: auto; overflow-y: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px;"&gt;&lt;code style="background-color: rgb(238, 238, 238) !important; border-bottom-color: rgb(222, 222, 222) !important; border-bottom-style: none !important; border-bottom-width: 1px !important; border-color: initial !important; border-left-color: rgb(222, 222, 222) !important; border-left-style: none !important; border-left-width: 1px !important; border-right-color: rgb(222, 222, 222) !important; border-right-style: none !important; border-right-width: 1px !important; border-top-color: rgb(222, 222, 222) !important; border-top-style: none !important; border-top-width: 1px !important; border-width: initial !important; color: rgb(68, 68, 68) !important; font-size: 12px !important; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;"&gt;./package-vipsdev.sh&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="line-height: 1.5em !important; margin-bottom: 1em !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 1em !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"&gt;I suggest you rename your zip to avoid confusion. Call it something like vips-dev-7.24.5-rob1.zip.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;h1&gt;Conclusion&lt;/h1&gt;We have made it as simple as we possibly can to get your win32 build whenever you want it! There is also something a little bit tantalizing about building for Windows on Ubuntu, it’s like forbidden fruit or something. If nothing else, you should build vips.exe simply so that you can say you have cross-compiled an application!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-8386931818410217817?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/8386931818410217817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/05/building-vips-for-windows.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/8386931818410217817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/8386931818410217817'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/05/building-vips-for-windows.html' title='Building VIPS for Windows'/><author><name>Bubba</name><uri>http://www.blogger.com/profile/13047929190978798149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/-vxPjxVFYYKQ/TbrRMMKLcxI/AAAAAAAAAAM/AJElTZ62wDQ/s220/Original-color.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_0vNEItollDg/TcAIcRvNpwI/AAAAAAAAABY/j8ZfjdgYS4w/s72-c/image_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-8176985954315196016</id><published>2011-04-26T05:05:00.000-07:00</published><updated>2011-04-26T05:18:22.957-07:00</updated><title type='text'>nip2 as a GUI for ImageMagick</title><content type='html'>VIPS has an operation, &lt;a href="http://www.vips.ecs.soton.ac.uk/supported/7.24/doc/html/libvips/libvips-conversion.html#im-system-image" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;im_system_image()&lt;/a&gt;, that lets you run a command-line program on an image. You can use it to run ImageMagick commands from nip2's menus.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-nt8aryxEDR0/Tba39xcs-sI/AAAAAAAAABk/c5BdI0cRMzg/s1600/swirl.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="195" src="http://2.bp.blogspot.com/-nt8aryxEDR0/Tba39xcs-sI/AAAAAAAAABk/c5BdI0cRMzg/s320/swirl.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;im_system_image()&lt;/span&gt; writes the image to a temporary file, creates another filename for the output, uses &lt;a href="http://pubs.opengroup.org/onlinepubs/007908799/xsh/popen.html" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;popen()&lt;/a&gt; to run a command on it, loads the output file and returns that image. It arranges for the temporary files to be deleted when they are no longer needed. &lt;br /&gt;&lt;br /&gt;You can call this function from nip2. Load a test image (perhaps &lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;A1&lt;/span&gt;) and click &lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;Toolkits / Widgets / Scale&lt;/span&gt; to make a slider (perhaps &lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;A2&lt;/span&gt;). Now at the bottom of the column, type:&lt;br /&gt;&lt;blockquote style="font-family: Arial,Helvetica,sans-serif;"&gt;"convert %s -swirl " ++ print A2.value ++ " %s"&lt;/blockquote&gt;This will make A3, the template for the command-line we want to run. The first &lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;%s&lt;/span&gt; will soon get substituted for the input filename and the second for the output filename. If you drag the slider, you'll see that your command-line updates.&lt;br /&gt;&lt;br /&gt;(You may need to edit this a bit. For example, on Windows, you might need to give the full path to the &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;convert&lt;/span&gt; program, and you'll need a &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;.exe&lt;/span&gt; suffix as well. You might want to use GraphicsMagick instead, in which case you'll need "gm" at the front)&lt;br /&gt;&lt;br /&gt;Now type this:&lt;br /&gt;&lt;blockquote style="font-family: Arial,Helvetica,sans-serif;"&gt;im_system_image A1.value "%s.tif" "%s.tif" A3&lt;/blockquote&gt;This will run &lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;im_system_image&lt;/span&gt;&amp;nbsp;on the VIPS image underlying the nip2 object &lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;A1&lt;/span&gt;, with &lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;"%s.tif"&lt;/span&gt; as the template for the input and the output filename. The %s in the input and output filename templates will be substituted for something like &lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;/home/john/.nip2-7.24.1/tmp/348963498523-&lt;/span&gt;&lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;,&lt;/span&gt;&amp;nbsp;depending on your platform. You can use the filename templates to set the file format that is used to pass your image to the program you are running.&lt;br /&gt;&lt;br /&gt;If everything works, you'll get a two-element list back with the first element being the processed image and the second being all the output that the program sent to stdout while it ran. To view the processed image, you need to wrap it up in nip2's &lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;Image&lt;/span&gt; class. Just run the&amp;nbsp;constructor&amp;nbsp;on it:&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;Image A4?0&lt;/span&gt;&lt;/blockquote&gt;That is, pull element zero out of &lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;A4&lt;/span&gt; (the result of &lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;im_system_image&lt;/span&gt;) and use it to build an instance of Image.&lt;br /&gt;&lt;br /&gt;Now drag your slider, and the image should update!&amp;nbsp;The scale widget defaults to the range 0 to 255, which is not really right for swirl. Doubleclick on the &lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;A2&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&amp;nbsp;button and set the range to -360 to +360. You could set the caption to something like &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;"Swirl angle"&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; too.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;You can make a menu item that does all this with a click. Click &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;Toolkits / Edit&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;, select the &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;Filter&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; toolkit (this seems like a good place for it) and copypaste this code in:&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;Swirl x = class _result {&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;_vislevel = 3;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;angle = Scale "Swirl angle" (-360) 360 0;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;_result&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;= Image (im_system_image x.value fmt fmt cmd)?0&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;prg = "convert";&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;options = "-swirl " ++ print angle.value;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;cmd = join_sep " " [prg, "%s", options, "%s"];&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;fmt = "%s.tif";&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;br /&gt;}&lt;/span&gt;&lt;/blockquote&gt;Select &lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;File / Process&lt;/span&gt; to get nip2 to update.&amp;nbsp;Now you can select any image and click &lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;Toolkits / Filter / Swirl&lt;/span&gt; to swirl it. It would be pretty easy to make menu items for all the ImageMagick commands this way. You could even write a tiny bit of Python or Ruby to generate the code for you from the ImageMagick website.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Finally, that was the simplest, but not the best way to make a menu item. Here's a slightly fancier version:&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: Arial,Helvetica,sans-serif;"&gt;Swirl = class&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Menuaction "_Swirl" "swirl an image" {&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;action x = class&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;_result {&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;_vislevel = 3;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;angle = Scale "Swirl angle" (-360) 360 0;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;_result&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;= map_unary swirl x&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;{&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;prg = "convert";&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;options = "-swirl " ++ print angle.value;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;cmd = join_sep " " [prg, "%s", options, "%s"];&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;fmt = "%s.tif";&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;swirl x = Image (im_system_image x.value fmt fmt cmd)?0;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;}&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;br /&gt;}&lt;/span&gt;&lt;/blockquote&gt;This version will work correctly with Groups (so you can automatically loop over sets of images) and have a&amp;nbsp;mnemonic&amp;nbsp;and a tooltip.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-8176985954315196016?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/8176985954315196016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/04/nip2-as-gui-for-imagemagick.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/8176985954315196016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/8176985954315196016'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/04/nip2-as-gui-for-imagemagick.html' title='nip2 as a GUI for ImageMagick'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-nt8aryxEDR0/Tba39xcs-sI/AAAAAAAAABk/c5BdI0cRMzg/s72-c/swirl.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-6041387430032321797</id><published>2011-04-14T10:09:00.000-07:00</published><updated>2011-04-17T04:11:55.237-07:00</updated><title type='text'>Gegl with libvips as the back end (updated)</title><content type='html'>(since first making this post I've done a bit more work on gegl-vips, so this is version 2.0)&lt;br /&gt;&lt;br /&gt;I've put up a quick hack of gegl-0.1.6 which uses libvips to process images. It might be a way to put numbers on various possible optimisations of gegl.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://github.com/jcupitt/gegl-vips"&gt;https://github.com/jcupitt/gegl-vips&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It has some severe limitations. First, it will not work efficiently with interactive destructive operations, like "paint a line". This would need area cache invalidation in vips, which is a way off. Secondly, I've only implemented a few operations (load / crop / affine / unsharp / save / process), so all you can do is some very basic batch processing. It should work for dynamic graphs (change the parameters on a node and just downstream nodes will recalculate) but it'd need a "display" node to be able to test that.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Test program&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;span style="font-size: small;"&gt;Here's the test program I've been benchmarking with:&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div style="font-family: inherit;"&gt;&lt;/div&gt;&lt;div style="font-family: inherit;"&gt;&lt;/div&gt;&lt;pre style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;gegl.h&amp;gt;&lt;br /&gt;#include &amp;lt;vips/vips.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;main (int argc, char **argv)&lt;br /&gt;{&lt;br /&gt;  GeglNode *gegl, *load, *crop, *scale, *sharp, *save;&lt;br /&gt;&lt;br /&gt;  g_thread_init (NULL);&lt;br /&gt;  gegl_init (&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;&lt;br /&gt;  if (argc != 3) &lt;br /&gt;    {           &lt;br /&gt;      fprintf (stderr, "usage: %s file-in file-out\n", argv[0]);&lt;br /&gt;      exit (1);&lt;br /&gt;    }&lt;br /&gt;        &lt;br /&gt;  gegl = gegl_node_new ();&lt;br /&gt;        &lt;br /&gt;  load = gegl_node_new_child (gegl,&lt;br /&gt;                              "operation", "gegl:load",&lt;br /&gt;                              "path", argv[1], &lt;br /&gt;                              NULL);&lt;br /&gt;  crop = gegl_node_new_child (gegl, &lt;br /&gt;                              "operation", "gegl:crop",&lt;br /&gt;                              "x", 100.0,&lt;br /&gt;                              "y", 100.0,&lt;br /&gt;                              "width", 4800.0, &lt;br /&gt;                              "height", 4800.0, &lt;br /&gt;                              NULL);&lt;br /&gt;  scale = gegl_node_new_child (gegl,&lt;br /&gt;                               "operation", "gegl:scale",&lt;br /&gt;                               "x", 0.9,&lt;br /&gt;                               "y", 0.9,&lt;br /&gt;                               "filter", "linear", &lt;br /&gt;                               "hard-edges", FALSE, &lt;br /&gt;                               NULL);&lt;br /&gt;  sharp = gegl_node_new_child (gegl,&lt;br /&gt;                               "operation", "gegl:unsharp-mask",&lt;br /&gt;                               "std-dev", 1.2, // diameter 7 mask in vips&lt;br /&gt;                               //"std-dev", 1.0, // diameter 7 mask in gegl&lt;br /&gt;                               NULL);&lt;br /&gt;  save = gegl_node_new_child (gegl,&lt;br /&gt;                              "operation", "gegl:save",&lt;br /&gt;                              "path", argv[2], &lt;br /&gt;                              NULL);&lt;br /&gt;  gegl_node_link_many (load, crop, scale, sharp, save, NULL);&lt;br /&gt; &lt;br /&gt;  gegl_node_process (save);&lt;br /&gt;                &lt;br /&gt;  g_object_unref (gegl);&lt;br /&gt;&lt;br /&gt;  gegl_exit ();&lt;br /&gt;&lt;br /&gt;  return (0);&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;ie. load, crop 100 px off the edges (you need to give it a 5k x 5k RGB image), bilinear 10% shrink, sharpen, save.&lt;br /&gt;&lt;br /&gt;See:&lt;br /&gt;&lt;blockquote&gt; &lt;a href="http://www.vips.ecs.soton.ac.uk/index.php?title=Speed_and_Memory_Use"&gt;http://www.vips.ecs.soton.ac.uk/index.php?title=Speed_and_Memory_Use&lt;/a&gt;&amp;nbsp;&lt;/blockquote&gt;for results with other libraries.&lt;br /&gt;&lt;br /&gt;Compile with:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;gcc -g -Wall gegl.c `pkg-config gegl vips-7.25 --cflags --libs`&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/blockquote&gt;and run with something like:&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;$ time ./a.out wtc_small.png wtc2.png   &lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif; font-size: large;"&gt;&lt;b&gt;R&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif; font-size: large;"&gt;&lt;b&gt;esults&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;If I run the test program linked against gegl-0.1.6 on a 5,000 x 5,000 pixel RGB PNG image on my laptop (a c2d at 2.4GHz), I get 96s real, 44s user. I tried experimenting with various settings for GEGL_SWAP and friends, but I couldn't get it to go faster than that, I probably missed something. Perhaps gegl's disk cache plus my slow laptop harddrive are slowing it down.&lt;br /&gt;&lt;br /&gt;Linked against gegl-vips with the operations set to exactly match gegl's processing, the same thing runs in 27s real, 38s user. So it looks like some tuning of the disc cache, or maybe even turning it off for batch processing, where you seldom need pixels more than once, could give gegl a very useful speedup here. libvips has a threading system which is on by default and does double-buffered write-behind, which also help.&lt;br /&gt;&lt;br /&gt;I investigated some other optimisations:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt; If you use uncompressed tiff, you can save a further 15s off the runtime. libpng compression is slow, and even with compression off, file write is sluggish.&lt;/li&gt;&lt;li&gt; The alpha channel is not needed in this case, dropping it saves about 5s real time.&lt;/li&gt;&lt;li&gt; babl converts to linear float and back with exp() and log(). Using lookup tables instead saves 12s.&lt;/li&gt;&lt;li&gt; The gegl unsharp operator is implemented as gblur/sub/mul/add. These are all linear operations, so you can fold the maths into a single convolution. Redoing unsharp as a separable convolution saves 1s.&lt;/li&gt;&lt;li&gt; Finally, we don't really need 16-bit output here, 8 is fine. This saves only 0.5s for tiff, but 8s for PNG.&lt;/li&gt;&lt;/ul&gt;Putting all these together, you get the same program running in 2.3s real, 4s user. This is still using linear float light internally. If you switch to a full 8-bit path you get 1s real, 1.5s user. Gegl is committed to float, but it's interesting to put a number on the cost. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;&lt;span style="font-family: Arial,Helvetica,sans-serif;"&gt;TODO&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;A screen output node would be fun to experiment with.&lt;br /&gt;&lt;br /&gt;The tests ought to be repeated on a faster machine, especially one with a faster hard disk.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-6041387430032321797?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/6041387430032321797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/04/gegl-with-libvips-as-back-end.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/6041387430032321797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/6041387430032321797'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/04/gegl-with-libvips-as-back-end.html' title='Gegl with libvips as the back end (updated)'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-2812142408800505891</id><published>2011-04-04T09:57:00.000-07:00</published><updated>2011-04-04T09:57:58.151-07:00</updated><title type='text'>New stable version, 7.24.5</title><content type='html'>We have a new stable version, 7.24.5. This has two small fixes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The gamma was not being set correctly on png write, causing images to appear washed out in programs like Firefox. This is an error introduced in the previous version.&lt;/li&gt;&lt;li&gt;The tiff reader was confused by strip images where the entire image was one strip and there was no rows_per_strip field, or the rows_per_strip was set to UINT_MAX.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;Anyway, both these small problems are fixed. There is a new source tarball and a new win32 binary.&lt;br /&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;a href="http://www.blogger.com/goog_1332677940"&gt;&lt;/a&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;a href="http://www.vips.ecs.soton.ac.uk/supported/7.24"&gt;http://www.vips.ecs.soton.ac.uk/supported/7.24&lt;/a&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-2812142408800505891?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/2812142408800505891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/04/new-stable-version-7245.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/2812142408800505891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/2812142408800505891'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/04/new-stable-version-7245.html' title='New stable version, 7.24.5'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6260754590317264118.post-5138313759518759618</id><published>2011-03-30T04:28:00.000-07:00</published><updated>2011-04-05T03:55:01.713-07:00</updated><title type='text'>New API takes shape</title><content type='html'>libvips has had the same interface for C programmers since 1990, with just a few additions. We've been trying to make a fresh start for a while and it seems to be finally happening.&lt;br /&gt;&lt;br /&gt;The current development version has a new core rebuilt on top of &lt;a href="http://library.gnome.org/devel/gobject/stable/" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;GObject&lt;/a&gt;. Everything is stripped down, cleaned up and much more consistent. All types are created and destroyed with the same few functions, we have reference-counting everywhere (so object lifetime management is mostly automatic), and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VipsObject&lt;/span&gt; includes a simple layer which adds full runtime introspection (so all interfaces to libvips can always present all the available features).&lt;br /&gt;&lt;br /&gt;The old, busted &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;IMAGE&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;REGION&lt;/span&gt; types have become the fresh, new &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VipsImage&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VipsRegion&lt;/span&gt; classes. Like all &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;GObject&lt;/span&gt; classes, you create them with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;g_object_new() &lt;/span&gt;(or a convenience function, like &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;vips_image_new_from_file()&lt;/span&gt;) and unreference them when you're done with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;g_object_unref()&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Image-processing operations, like "add image1 to image2", are also classes. You run them with on images with something like:&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;vips_operation_new ("add", image1, image2, out, NULL);&lt;/div&gt;&lt;/blockquote&gt;Where the NULL marks the end of a list of name / values pairs listing optional arguments defined by &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VipsAdd&lt;/span&gt; or one of its superclasses.&lt;br /&gt;&lt;br /&gt;Internally, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;vips_operation_new()&lt;/span&gt; searches the class hierarchy below &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;VipsOperation&lt;/span&gt; for a class whose nickname is "add", makes an instance of that class with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;g_object_new()&lt;/span&gt;, loops over the required construct-time properties setting them from the arguments to the C function, then loops over the rest of the C args up to the NULL setting optional named construct-time properties.&lt;br /&gt;&lt;br /&gt;Sadly there's therefore no type safety. So there's also a convenience function:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;int vips_add (VipsImage *in1, VipsImage in2, VipsImage *out, ...); &lt;/span&gt;&lt;/blockquote&gt;And a macro which provides vips7 compatibility:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#define im_add(IN1, IN2, OUT) (vips_add(IN1, IN2, OUT, NULL))&lt;/span&gt;&lt;/blockquote&gt;The Python binding works at the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;vips_operation_new()&lt;/span&gt; level and overrides ".", so you can write:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;out = image1.add (image2)&lt;/span&gt;&lt;/blockquote&gt;and it turns into the call to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;vips_operation_new()&lt;/span&gt; above. Since almost the whole Python binding is generated at runtime, it's very small and will adapt automatically as new operations are added. &lt;br /&gt;&lt;br /&gt;So far only one operation has been redone in the new API. The other 299 are all there and working via a set of macros which implement the old vips7 API on top of the shiny new vips8 one. The vips7 compatibility macros are good enough that nip2 also works on the new system with no changes.&lt;br /&gt;&lt;br /&gt;The next stable release, due rather soon now, will include this new core. We see vips8 as emerging slowly over the next year or so as, one by one, the old vips7 operators are moved to the new API. When everything is swapped over, we'll document the new API, bump the version number to vips-8.0, and have a large party.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6260754590317264118-5138313759518759618?l=libvips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://libvips.blogspot.com/feeds/5138313759518759618/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://libvips.blogspot.com/2011/03/new-api-takes-shape.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/5138313759518759618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6260754590317264118/posts/default/5138313759518759618'/><link rel='alternate' type='text/html' href='http://libvips.blogspot.com/2011/03/new-api-takes-shape.html' title='New API takes shape'/><author><name>John Cupitt</name><uri>http://www.blogger.com/profile/12567002343578053459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
