[Gegl-developer] new GEGL samplers: what they are and where they are going
Question about future direction for resamplers: Would it be better if there was only one sampler tuned for upsampling, and one tuned for downsampling? My previous vision for GEGL was that my research group would contribute TWO resamplers tuned for upsampling and TWO resamplers tuned for downsampling. The four new samplers would (eventually) integrate the best of the 16 resamplers programmed by Eric and Adam for GSoC 2009. Within each of the two pairs of resamplers, one was to be interpolatory (and more aliased) and the other would minimally blur (and be less aliased). Now: I just figured out how to use the Jacobian matrix information so that the sampler only add noticeable antialiasing blur when the operation is performing significant upsampling or downsampling. What this means for the resamplers tuned for upsampling, for example, is that we could seamlessly integrate Nohalo and Snohalo in such a way that the sampler behaves like Nohalo when translating and rotating (hence is blur free) but behaves increasingly like Snohalo as the transformation (locally) deviates from being distance preserving (hence is more anti-aliased), resulting in one single sampler which would please everyone and their father. I imagine that a few people would want the added control over the aliasing vs blur trade-off which having pairs of methods would provide (also, methods can be faster if they are not jack of all trades). But I am wondering if for GEGL's target user base an always pretty good default is preferable to choose your poison. Comments? Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] new GEGL samplers: what they are and where they are going
, finishing with bilinear interpolation. Nohalo level 2 is an unpublished, state of the art method. Upsize is interpolatory, co-monotone and exact on linears. It is especially suited for enlarging colour photographs (which typically are sub-critical, that is, have smallest relevant details/transitions which are several pixel wide). Future improvements: Research by Chantal Racette suggests that one level of subdivision (that is, Nohalo level 1) followed by a variant of symmetrized MP-quadratic instead of bilinear may yield a better method than Nohalo level 2. == Upsizefast sampler == Upsizefast is an implementation of Nohalo level 1, which is described in CPU, SMP and GPU implementations of Nohalo level 1, a fast co-convex antialiasing image resampler, by Nicolas Robidoux, Minglun Gong, John Cupitt, Adam Turcotte and Kirk Martinez, published in the Proceedings of the Canadian Conference on Computer Science Software Engineering, C3S2E 2009, Montreal, Quebec, Canada, May 19-21, 2009, ACM International Conference Proceedings Series, pages 185-195. http://doi.acm.org/10.1145/1557626.1557657 Nohalo level 1 consists of one diagonal straightening subdivision followed by bilinear interpolation. Upsizefast is interpolatory, co-monotone and exact on linears. Upsmooth sampler Upsmooth is an implementation of (the simplest version of) Snohalo level 2 (Snohalo = smooth no halo), which consists of Nohalo level 2 preceded by a de-noising and antialiasing smoothing convolution tuned so that a sharp black on white diagonal line or interface is straight following the first subdivision. Snohalo level 2 is an unpublished, state of the art method. Upsmooth is co-monotone and exact on linears. Upsmooth is strongly anti-aliasing. It is especially suited for enlarging text, old school game characters, and heavily (destructively) compressed images and photographs (jpg with heavy compression, for example). Future improvements: It is possible that applying smoothing between every level instead of only initially, or doing one level of subdivision and then using a relative of symmetrized MP-quadratic as a finishing scheme, will yield better results. Upsmoothfast sampler Upsmoothfast is an implementation of Snohalo level 1, which consists of Nohalo level 1 preceded by the antialiasing blur. Snohalo level 1 is another unpublished, state-of-the-art method. Upsmoothfast is co-monotone and exact on linears. = Downsharp sampler = Downsharp is an exact area method which is similar to exact area box filtering with an averaging rectangle that has sides 1/sqrt(2) of those of the smallest rectangle (with sides aligned with untransformed coordinate axes) which contains the approximate inverse image of an output pixel area (a square centered at the sampling location in transformed space, with sides, of length one, aligned with the axes). The inverse image is approximated using the inverse Jacobian matrix of the transformation. The averaging is done over the minmod surface which is implicit to the S/Nohalo methods. The 1/sqrt(2) factor ensures that when the transformation does not downsample in any direction, the sampler is interpolatory. It also implies that, of the six downsamplers, it is the one which behaves most like nearest neighbour (although it is very different from it). Downsharp is yet another unpublished method. Downsharp is co-monotone and exact on linears. When upsampling, it is also interpolatory. Downsharp is well-suited for producing thumbnails and other transformations (perspective?) in which large areas become a single pixel. Future improvements: Fix things so that downsampling ratios larger than about 100 are better handled. The simplest way would be to have the downsamplers use a larger buffer than the current 64x64; otherwise, use branching and multiple get pointer to input buffer calls if necessary. And, as mentioned above, possibly get rid of it. Downsize sampler Downsize is like downsharp except that the rectangle always fully contains the approximate inverse image of a pixel area. Downsize is yet another unpublished method. It was inspired somewhat by the PDL::Transform method of Craig DeForest. Downsize is co-monotone. When upsizing (no rotation or warp), it is interpolatory and exact on linears. Downsize is well-suited for producing thumbnails etc. Future improvements: Like downsharp, better handling of very large downsampling ratios. It is possible that averaging over the actual approximate inverse image, or over a related disk or ellipse, give better results than over the smallest containing rectangle (programming this well is a non-trivial programming task). == Downsmooth sampler == Downsmooth is like downsize except that the rectangle is twice the size required
Re: [Gegl-developer] Abyss color
What would be the most general way of getting this abyss color to gegl-buffer-access.c? gegl/operations/affine/affine.c would take care of rotation and scaling and a few other things, although it probably is still not general enough. Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] use of bitwise arithmetic in GEGL code
Is the use of such tricks discouraged for GEGL (because gfloats could be doubles at some point?) We can take the absolute value by setting the sign bit to zero: // Example 13.24 float f; *(int*)f = 0x7FFF; // set sign bit to zero (From http://www.agner.org/optimize/optimizing_cpp.pdf) Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] use of bitwise arithmetic in GEGL code
Ralf Meyer (another Laurentian prof) did some quick and dirty experimentation with preliminary versions of bit-twiddling minmods and found that on PowerPC chips it made a big difference. Not on Intel. Not really surprising: Avoiding branches like the plague is more relevant to PowerPC/cell than Intel. In GEGL (production) code? Not sure. Nicolas Robidoux ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Passing parameter to sampler from XML file
Suggestion implementing the s/nohalo family and the nohalobox family without an explicit, visible, parameter: Would it be possible/desirable to use the current code (which has a parameter) as some sort of template? Then, the nohalobox code would produce four independent samplers: sharperbox - smoothing = 0 sharpbox - smoothing = 1/3. smoothbox - smoothing = 2/3. smootherbox - smoothing = 1. which could be called like, say, linear. And the s/nohalo code would produce four independent samplers: sharper - nohalo (nohalo produces the same results as snohalo with smoothing = 0, just faster) sharp - snohalo with smoothing = 1/3. smooth - snohalo with smoothing - 2/3. smoother - snohalo with smoothing = 1. Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Passing parameter to sampler from XML file
yahvuu writes: uh, what, me? i wouldn't want to be bothered with choosing different samplers for up/down-scaling. (I'm surprised. You are always happy with the thumbnails you get? Result after rotating an image? Maybe I'm too invested in this field to know what matters and what matters not.) Peter just gave me more ideas of how it could look in a menu: bigger (sharp) and bigger (smooth) and smaller (sharp) and smaller (smooth) The fact that bigger can be used for arbitrary warps (including downsampling) and smaller can be used for arbitrary warps (including upsampling) should not confuse anyone. (I think.) Keep the ideas coming! Nicolas Robidoux Laurentian University ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Passing parameter to sampler from XML file
sharpEnlarge and smoothEnlarge and sharpShrink and smoothShrink (or sharpReduce and smoothReduce) ? PS Let me know if you'd rather I think about all this off list. ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Passing parameter to sampler from XML file
sharpsmall and smoothsmall and sharpbig and smoothbig ? In a scale image menu, the most likely appropriate method could be chosen automatically (depending on the requested resizing), with an extra smoothing toggle set by default to off. Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Passing parameter to sampler from XML file
Nicolas Robidoux writes: For example, nohalo1 (same result as snohalo1 with smoothing = 0, but runs faster) would be sharper, snohalo1 with smoothing = 1 would be smoother, and snohalo1 with smoothing = .5 would be halfandhalf, or something kind of like that? If there were only four named presets, I supposed they could be sharpest, sharp, smooth, smoothest corresponding to smoothness = 0, 1/3, 2/3 and 1. with the added bonus that smoothness = 1/3 kind of corresponds to the Mitchell-Netravali choice of smoothing/interpolation balance. Øyvind: Does the above seem like a good choice, or did I change your mind with my smoothness slider idea (or do you like neither)? Nicolas Robidoux Laurentian University ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] API change for samplers to pass inverse Jacobian data to samplers
Martin Nordhotls wrote: Personally I don't see the point in duplicating a matrix lib in every software, i.e. I question the introduction of GeglMatrix3 in the first place, I mean there certainly must be high quality libs for matrix operations out there, but that's a different story... IMHO, when all you are dealing with are 3x3 matrices (which are not arbitrary 3x3, since they represent affine + perspective transformations), it is likely that a general purpose matrix library would be slower. Even more so with 2x2. So, my vote is actually for not library. Nicolas Robidoux ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] API change for samplers to pass inverse Jacobian data to samplers
Adam: (Ignore if my last email about GeglMatrix3 was off the mark.) Is it that affine transformations, stored in 3x3 matrices, get simplified when they are chained? If so, where is the final overall 3x3 representation? Hopefully, extracting the linear part from it to compute the inverse Jacobian could be done there. Nicolas Robidoux ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] API change for samplers to pass inverse Jacobian data to samplers
Adam Turcotte writes: In addition, I will need to expand the OpAffine struct to include an additional GeglMatrix3 (call it matrix_inverse or inverse_jacobian?) to store this data. GeglMatrix3? Is this a 3x3 matrix type? (Ignore the following if it is not.) Maybe the matrix created by the create_matrix () method is not really the plain Jacobian matrix even for affine transformations. I understand that there are convenient representations of common image transforms in terms of 3x3 matrices, but I wonder if using a 3x3 to store either the Jacobian or its inverse just confuses things, at least for our purposes. My suggestion: If create_matrix () returns a 3x3, keep the inverse Jabocian computation out of create_matrix (). Because I am far from certain that there would ever be a need to do matrix operations on the inverse Jacobian, I actually am not even sure that it is necessary to store it in an explicit matrix type. For documentation sake? Can anyone foresee a use for the inverse Jacobian matrix being stored in a 3x3? Nicolas Robidoux ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] [GSoC] Midterm project evaluations coming up
Adam Turcotte's midterm deliverables: -- Figure out how to use/adapt/emulate intermediate buffers to store intermediate results (kind of like nohalo runs on the GPU: intermediate buffer would be like a texture). -- Figure out how to use/adapt/emulate variable size sampler buffers for non-recursive reasonable quality downsampling. -- Make good progress in implementing the above (hopefully, be done) nicolas ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] [GSoC] Midterm project evaluations coming up
Argh! My explanation (RE: Adam's GSoC deliverables) was terrible (Adam just called me on it). What I meant: Somehow allowing a variable footprint (stencil) in (re)samplers. Right now, the footprint is fixed (from gegl/gegl/buffer/gegl-sampler-cubic.c): GEGL_SAMPLER (self)-context_rect.x = -1; GEGL_SAMPLER (self)-context_rect.y = -1; GEGL_SAMPLER (self)-context_rect.width = 4; GEGL_SAMPLER (self)-context_rect.height = 4; The RHS's are arbitrary, but I don't think they can be changed at run-time on a pixel by pixel basis (or even on a run by run basis?). Hopefully, it makes sense now. We already have some ideas of how to emulate it. Nicolas Robidoux ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] [GSoC] Midterm project evaluations coming up
Eric Daoust's GSoC midterm deliverables: 1) Sped up nohalo level 1 code. 2) New fast resampling method targeted for downsampling (without the affine transformation info passed from above, and without variable size buffers, which will be implemented later in the SoC). This will be the lower quality (but most likely very fast) version. (I'll email RE: Adam's deliverables when I have them nailed down. Adam is currently focusing on the much trickier nohalo level 2 and buffer issues.) Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] new gegl-sampler code (GSoC): maximum expected downsampling ratio
In case it turns out to be difficult to set the context_rect to be variable (set on an output pixel by pixel basis--Eric is looking into this), I'd like to know what I could assume is the largest reasonable downsampling ratio, meaning that larger downsampling ratios would be clamped down to this ceiling. Such clamping would allow us to set the context rectangle to a (reasonably small) fixed value. More specifically, could I reasonably clamp the downsampling ratio (in each direction) to one of the following values? 1.0 (context_rect.width = 4) 2.7182818284 (context_rect.width = 5) 7.3890560989 (context_rect.width = 6) 20.0855369231 (context_rect.width = 7) 54.5981500331 148.4131591025 403.4287934927 1096.6331584284 2980.9579870417 (context_rect.width = 12) (first and last ones included for the sake of completeness.) The smaller the maximum, the faster the code will run. (As the above table makes pretty obvious, the method will be more suitable for mild downsampling that heavy duty.) Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] alignment of pixels with coordinates
Øyvind Kolås writes: ... I agree that the convention should be that pixel sampling sites are at integer coordinates. I also feel it would be natural to let the extent of a pixel be half way towards the neighbour pixel sites, this however has the issue of not matching the display GIMP provides when zoomed into the image. ... GEGL might in the future also offer other resamplers for blitting / display purposes, the best would of course be if all resamplers could be plugged in and interchangeably used for different purposes, at the moment the resampling that happens in gegl_node_blit does not use the resamplers to do its job for the general cases it probably shouldn't either since it needs to be as fast as possible. Thank you! I finally figured it out: Image size conventions are actually decoupled from the pixel-coordinates convention. (Although they often are linked, they don't need to be.) The resamplers can all use one convention (center-based physical coordinates, as you suggest, and as I prefer). But the operations which call resamplers can have an optional toggle, with defaults dependent on the called resampler. - I am not totally sure this is easy to implement, but this would be ideal. So, an affine operation calling a resampler targeted at downsampling (e.g. exact area box filtering) would use the image size convention which corresponds to exact area resampling---that is, the image sticks out half a pixel from the centers of the boundary pixels (this is the big image convention)---unless overridden by the user (note that this is separate, althought related, to the issue of where the pixel coordinates are). Likewise, an affine operation calling an interpolatory resampler (targeted for point transformations) would use the image convention which is normally associated with it---the image ends right at the centers of the boundary pixels (the small image convention). Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] GSoC 2009: implementing multiple quality levels in resamplers
Any suggestions RE: the intelligent way of implementing samplers with multiple quality levels? (Note that Adam and Eric may be able to figure this out without your or my guidance, but in the interest of faster progress I am asking planning questions here.) My question will make more sense if I explain things a bit: The nohalo family of resamplers has levels, which are most easily understood as quality levels. Currently, an outdated nohalo level 1 is in the gegl library as gegl/gegl/buffer/gegl-sampler-sharp.c. (It is correct, but it is much slower than it has to be.) Nohalo level 2 is near ready (for VIPS), and by the end of the Summer we hope to have levels 3 and 4 implemented in GEGL. Now, these could be associated with quality requests (say, if quality .25, use nohalo level 1, if quality .5 use level 2, etc). Note, for example, that the footprint (stencil) gets larger as the quality increases (think of Lanczos methods, for example). How would you like this to be set up? Are there examples we could follow? A related issue: The upcoming snohalo (snohalo level 1 is ready in VIPS, no progress on snohalo level 2) also has quality levels (analogous to the nohalo quality levels). The key aspect is that snohalo has a blur parameter which, when set to 0, reduces the method to the same level nohalo, which runs considerably faster (because, among other things, it has a much smaller footprint). Any suggestion on how to implement this in GEGL so that a call to snohalo actually return nohalo when blur = 0, but the codes are kept separate? Or should we simply put the two together with an if statement which steers internally things toward nohalo when they should? Thanks (for your patience), Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Introduction to GEGL Buffers
Hello Utkarsh, Maybe implementing multi-threading in GEGL would be a good, not yet taken, project? (Note that I do not have enough of a broad/detailed view on GEGL to make this suggestion from a position of authority.) Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Introduction to GEGL Buffers
Dear Utkarsh: I was talking about CPU multi-threading, that is, using multi-cores, e.g. http://www.vips.ecs.soton.ac.uk/index.php?title=Benchmarks#Results_in_detail And unfortunately, I am swamped, and consequently, I basically can't help. I may be wrong, but I am pretty sure that GEGL does not multi-thread as of now. Nicolas Robidoux ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Introduction to GEGL Buffers
Utkarsh: Although clearly the two projects probably should not proceed without some mutual consultation, I feel that GPU and multi-core involve fairly seperate programming. For this reason, I would not be overly concerned that your fixing multi-core (say) would duplicate the GPU effort. Clearly, some coordination would be desirable. However, in the nitty gritty, these are separate projects. Nicolas Robidoux Laurentian University ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Introduction to GEGL Buffers
I expect the following items from Øyvind's list to be tackled by Adam Turcotte and Eric Daoust (both GSoC students which I mentor). Consequently, if someone is planning to tackle these issues in the foreseable future, please let everyone know. Øyvind Kolås writes: ... What follows is a blue-sky wishlist of features that should be possible to add to the architecture making it and GEGL a powerful base. - Make the background/empty color configurable (by making the empty tile's contents configurable). - Add abyss policies to be used by resamplers, allowing configuring the behavior of affine transforms and warping image operations. I'm not making promises on the following (given that they are not part of the original GSoC) but they are related to Adam and Eric GSoCs, but it would make sense to have them have a look at the following (I may give more programming help with the resampler parts to free them for what's below): - Detect when a tile is set to be a solid block of the background color, and make the tiled shared with the empty tile. - Detect uniformly colored and perhaps other types of tiles and store them more compactly, perhaps even just compressing tile contents and share duplicate tiles detected through hashing of their compressed data. Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Introduction to GEGL Buffers
Øyvind Kolås writes: I forgot to add one more item to my list of potential/desired enhancements of GeglBuffer and that is to make the extent (width and heights) of the buffer be updated on demand when tiles are changed, allowing automatically growing buffers that are auto-clipped to the bounding box of content that differs from the configured background color. Do I gather correctly that this is related to the possible solution you gave for http://bugzilla.gnome.org/show_bug.cgi?id=54 namely, The bug is manifest because the different interpolation methods have different sampling footprints. The resulting image size is computed based on the size of the kernel, this is similar in behaviour to the gaussian blur which increases the size of the input image as well by smearing it out. The upper left corner of the bounding box is stored to be in negative coordinats so sampling from 0,0 would yield the upper left sample anyways. One way to work around this would be to crop the image to the original bounding box. Not completely sure if this is a bug or not, I guess it depends on what types of behavior we want to support for the edges of transformed buffers. Please let me know if I am completely off track, but there are some issues which I want to understand if possible (even though you may have explained it to me already) in order to guide Eric and Adam: Question 1: If my memory is good, samplers in GIMP use the center image size convention, which means that the centers of the boundary pixels creep in when downsampling, but creep out when upsampling, because what is kept fixed is the position of the corners of the areas implied by the boundary pixels, which are half a pixel width out from their centers. The most common alternative is the corner convention, which anchors the positions of the centers of the boundary pixels. I am omitting discussion the pros and cons for each. (Generally, center is better for downsampling, and corner is better for upsampling, so no single convention works best for all situations.) However, it is my opinion that corner convention is generally better. Do you have a preferred implied convention for GEGL? Should it comply with what is generally the implied convention in GIMP? This matters, because if the abyss policy is no blending: image goes to the boundary ignoring the abyss, and the abyss is constant whatever (0, say, but one of your requested features is that this be configurable), we need to know where the boundary is. Question 2: Do you want resampled image sizes to be enlarged by the size of the footprint (more specifically, by the size of smallest rectangle which contains the footprint, since, for example, the footprint of nohalo is not a rectangle), or do you want the resampled image size to be cropped, in accordance with the image size convention (in the corner convention, the image ends right at the center of the boundary pixels, in the center convention, it ends one half pixel past it). Prior to our conversations last week, I was sure that cropping should be done. however, now that I have been exposed to the wonderfulness of GEGL buffers, I have the impression that the buffer should be extended by this footprint so that the blending implicit in most abyss policies be applied not only inside the extent of the original image, but also outside. A consequence is that the bounding box will depend on the abyss policy, which is the case now. In other words, this would be a feature, not a bug. Question 3: Because the footprint of the samplers is often asymetrical (for example, for bicubic, the anchor is the second pixel from the left, out of the four positions which make up the footprint in the horizontal direction; this breaks left/right symmetry) the number of pixels by which the image is extended at the top and left is often not the same as the number by which it is extended at the bottom and right. Of course, symmetry is resolved in that extra ones are set to the background abyss colour (0). Again, I previously saw this as a bug, which in principle could be avoided using some logic or cropping. However, at this point, I am enclined to treat it as a quirky feature which is a side effect of a sound design decision. Is this agreed? -- I hope that I am not making my confusion too manifest here. Cheers, Nicolas Robidoux Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Introduction to GEGL Buffers
Christopher Montgomery writes: ... I suspect you are conflating center/corner with 'are we point sampling or area sampling the pixel?'. ... I am not. Although area sampling generally works better with the center convention, and point sampling works better with the corner convention, one can use either with either convention. In my mind, these are related, but separate, issues. I have programmed and used area sampling methods with either convention, for example. More about this later. - (Thanks for joining the discussion.) Nicolas Robidoux Laurentian University ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Introduction to GEGL Buffers
Let me try to be a bit more specific, one issue at a time. -- I agree that, at least at low order (which is all we're doing for now), abyss policies are independent of whether we are using the center or corner image conventions, and are also independent of whether we are implementing an exact area method (like most implementations of box filtering), or a point resampler (like standard bicubic). However, Øyvind expressed a desire to have something implemented in or for the resamplers which cannot really be done with the usual abyss policy implementations. Here is: Associate a default constant colour with a buffer. What Øyvind would like (if I understand correctly) is that instead of sampling through the implied boundary using the resampler as if there was no boundary (filling in the missing footprint values using the abyss policy), the resampled values drop dead at the boundary and from then on are filled (filled, not blended) with the default colour. For example, the sampler could use the nearest neighbour abyss policy (a.k.a. clamp) for requested values up to the boundary line, and return the default colour past it. Comment: Thinking about this some more, I am starting to think that it is a bad idea to implement this. (Later.) Irregardless of whether this is a good or bad idea, the main point is: Where should the drop dead transition occur: Aligned with the (center of) the boundary pixels? Or half a pixel width out (at the boundary of the pixel area associated with boundary pixels)? One of my worries is that if one when doing something else than resizing this will essentially behave like nearest neighbour (from the outside in), which will be ugly. So, I am actually starting to think that drop dead is not such a good idea. But I'd love to hear opinions on this. nicolas ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Introduction to GEGL Buffers
Christopher Montgomery writes: ... Ah, you mean that the implementation is easier, not that the output results differ? ... Christopher: Can we start from scratch? I'm afraid that we may take a long time explaining to each other exactly what we mean, with the most likely end result that we agree with each other on the essential (code-wise consequences). I started the ball rolling being vague, let me see if I can stop it. It's not that I don't welcome your input (I actually sought it, and it is important to me that we align the GEGL resampler team with their GIMP counterparts), it is just that I am too tired/busy to get into a I actually mean this, which really is the same although it is different from what you mean, is that right? Oh! you were talking about this limited situation but I was talking about the more general one and things are not the same but you can emulate the other if you are willing to blah blah blah debate. It's more important to me to be useful than to be right. nicolas ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] Documenting gegl
Hello Henrik: I don't know if this was mentioned before, but the open source VIPS http://www.vips.ecs.soton.ac.uk/index.php?title=VIPS although quite different to GEGL, is also somewhat similar. VIPS handles CMPs well. Maybe some of VIPS' under the hood parallel machinery would carry over? Nicolas Robidoux Laurentian University/Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] How to get bounding box from inside a sampler
Hello all: This question will make clear that I don't understand c++. Suppose that, in the code for, say, gegl/gegl/buffer/gegl-sampler-cubic.c, I want to use information about the bounding box of the input data. More precisely: I (believe that) I already know that the relevant pixel values start at indices 0,0. Requested values to the left and above those are created by the (currently 0,0,0,0) abyss policy. Which is to say that 0 and 0 are the smallest x and y for which I have real data. What I want to know is the width and height (in pixels) the area with valid pixel values. This is almost the same as: I want to know the lowest positive indices at which the abyss policy kicks in. Which is almost the same as: What is the index of the rightmost/lowest pixel with real data associated to it. -- Once I have this info, I can finish the yafr code. With thanks, Nicolas Robidoux Laurentian University/Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] Speeding up/documenting the gegl code
(Forgive me for preaching, done from the vantage point of a very stubby soapbox.) One thing which I would not mind seeing throughout the gegl code is the systematic use of the const keyword. My understanding is that the const keyword can also be used effectively to indicate to the compiler that it can optimize without worrying about aliasing (of course, if the object is not const, the restrict keyword is the only weapon). If is also good for documentation, because it allows one (me!) to find out easily which arguments can be changed by a function. (Akin to classical fortran subroutine documentation: declare the input arguments first, then the arguments which are both input and output, then those which are strictly output. About const correctness: http://www.cprogramming.com/tutorial/const_correctness.html ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] #defining the restrict keyword
Hello Sven: Given that the restrict keyword may be defined by default for other compilers than gcc (it is in gcc http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/gcc/Other-Builtins.html wouldn't the following be better? #ifndef restrict #ifndef G_GNUC_RESTRICT #if defined (__GNUC__) (__GNUC__ = 4) #define G_GNUC_RESTRICT __restrict__ #else #define G_GNUC_RESTRICT #endif #define restrict G_GNUC_RESTRICT #endif #endif This appears to work in (the not yet patched in svn) yafr. -- Even better: It appears that autoconf can take care of this in one fell swoop: http://www.gnu.org/software/libtool/manual/autoconf/C-Compiler.html See the Macro: AC_C_RESTRICT section. Nicolas Robidoux Laurentian University/Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
[Gegl-developer] more benchmarking: restrict vs no restrict
Hello: I did some quick benchmarks, having to do with qualifying pointers local to gegl-sampler-yafr.c and gegl-sampler-linear.c with the restrict keyword. The upshoot: Speed wise, this makes not difference. Comments: These functions are fairly simple, so it could be that gcc can untangle aliasing, since there is not much opportunity for it. When pointers are dealing with stripes, separating them into different pointers may lead to more benefit when using the restrict keyword. It could be that more globally defined pointers benefit more from the restrict keyword. But I am starting to suspect that const has more likely impact on speed than restrict. Nicolas Robidoux Laurentian University/Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Question about the use of C99/gcc built-in math intrinsics within GEGL on gfloats
Hello Sven: Thanks for your answer. Simplifies my life a lot. -- There is another C99/gcc built-in with the potential to speed up code a lot: the restrict keyword. See: http://www.cellperformance.com/mike_acton/2006/05/demystifying_the_restrict_keyw.html I'll build two versions of the gegl-sampler-yafr code (one of which which I'll masquerade as gegl-sampler-cubic so I can run both without recompiling) and run careful benchmarks this weekend. One version will stay away from restrict and c99 math intrinsics, the other will not (first pass, I may not go as far as making explicit calls to fma, although my code is structured in the hope that the compiler recognizes fused multiply-adds when appropriate). I don't quite understand the issues of writing c++ code using c99 features (this is why knowing that they are gcc built-ins is useful, provided one knows that gcc will be the compiler). Maybe I'll inspire myself from http://www.ddj.com/cpp/184401653 Nicolas Robidoux Laurentian University/Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer
Re: [Gegl-developer] Question about the use of C99/gcc built-in math intrinsics within GEGL on gfloats
I just completed a quick and dirty benchmark comparing the use of arithmetic branching using c99/gcc intrinsics within the yafr sampler code, to using the standard c if then else. These tests were performed on a Thinkpad t60p with Intel(R) Core(TM)2 CPU T7200 @ 2.00GHz with 2025MiB memory running 2.6.24-19-generic #1 SMP by way of a pretty standard Ubuntu 8.04. Warning: There seems to be something wrong with math.h with the current version of gcc, as suggested by some recent bug postings. For example, according to the gcc documentation, I should not have to prefix fminf with __builtin_. Consequently, it could be that the benchmark results will soon be made irrelevant. Second warning: If my memory is good, Intel chips have a good and fast implementation of the ? : branching construct (having to do with selecting which register to copy into another), as well as good branch prediction. My code without intrinsics is structured to take advantage of this. Third warning: I have not optimized looking at the assembler output of gcc, and have done no optimization of the arithmetic branching version of the code. In particular, I have not used fmaf, even though my code is peppered with opportunity to use it (this may not be a big deal: apparently, gcc attempts to spot opportunities to use fused multiply-add). -- quick description of the test: -- I ran a bunch of consecutive scalings (times 20) of a digital photograph with initial dimensions 200x133, driving the gegl scale through an xml file analogous to the ones in gegl/docs/gallery, alternating between the with branching and arithmetic branching with intrinsics versions, and throwing in four scalings with the gegl stock linear. - Differences between the two versions of the code: - 16 code segments resembling the following (note the ?: this the version with branching): const gfloat prem_squared = prem * prem_; const gfloat deux_squared = deux * deux_; const gfloat troi_squared = troi * troi_; const gfloat prem_times_deux = prem * deux; const gfloat deux_times_troi = deux * troi; const gfloat deux_squared_minus_prem_squared = deux_squared - prem_squared; const gfloat troi_squared_minus_deux_squared = troi_squared - deux_squared; const gfloat prem_vs_deux = deux_squared_minus_prem_squared (gfloat) 0. ? prem : deux; const gfloat deux_vs_troi= troi_squared_minus_deux_squared (gfloat) 0. ? deux: troi; const gfloat my__up = prem_times_deux (gfloat) 0. ? prem_vs_deux : (gfloat) 0.; const gfloat my_dow = deux_times_troi (gfloat) 0. ? deux_vs_troi : (gfloat) 0.; were replaced by (this is the version with arithmetic branching): const gfloat abs_prem = fabsf( prem ); const gfloat abs_deux = fabsf( deux ); const gfloat abs_troi = fabsf( troi ); const gfloat prem_vs_deux = __builtin_fminf( abs_prem, abs_deux ); const gfloat deux_vs_troi = __builtin_fminf( abs_deux, abs_troi ); const gfloat sign_prem = copysignf( prem, (gfloat) 1. ); const gfloat sign_deux = copysignf( deux, (gfloat) 1. ); const gfloat sign_troi = copysignf( troi, (gfloat) 1. ); const gfloat my__up = ( sign_prem * sign_deux + (gfloat) 1. ) * prem_vs_deux; const gfloat my_dow = ( sign_deux * sign_troi + (gfloat) 1. ) * prem_deux_0_vs_troi; Basically, what the code snippets does is this: If prem and deux have the same sign, put the smallest one (in absolute value) in my__up. Otherwise, set my__up to zero. Do likewise with deux, troi and my_dow. The above two code snippets represent the best ways of performing this that I could figure. === Overall conclusion: === Arithmetic branching (without other improvements) does not appear to be worth the trouble. Average timings: stock gegl linear scale: 47.50 = ( 47.474 + 47.581 + 47.345 + 47.595 ) / 4 gegl yafr with ? branching and no use of intrinsics: 52.58 = ( 52.422 + 52.479 + 52.748 + 52.501 + 52.680 + 52.623 + 52.537 + 52.518 + 52.576 + 52.487 + 52.542 + 52.485 + 52.645 + 52.810 + 52.667 + 52.554 ) / 16 gegl yafr performing arithmetic branching with fabsf, copysignf and fminf: 52.70 = ( 52.568 + 52.447 + 52.763 + 52.524 + 52.772 + 52.652 + 52.524 + 52.765 + 52.596 + 52.850 + 52.733 + 52.799 + 52.627 + 52.897 + 52.871 + 52.866 ) / 16 As you can see, the ? version is slightly faster overall. Probably not in a significant way, but this certainly does not suggest that this is worth the hassle. Nicolas Robidoux Laurentian University/Universite Laurentienne ___ Gegl-developer mailing list Gegl-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer