Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Branch: master
Commits on Oct 6, 2015
  1. Fix magic wand selection rendering

    I'm not sure when these broke, but they needed to be revisited anyway in
    light of GDI+'s faulty effect behavior on Win 8+.
Commits on Oct 5, 2015
  1. Temporary fix for clipped combo box text

    It's official: I'm going to write my own combo box instead of wrapping
    the system one.  Combo box behavior in Windows 10 (finally) works how it
    does in OSX, where a "dropped" combo box places the currently selected
    item centered over the underlying combo box.  This is way more intuitive
    and intelligent than the old method of always dropping beneath or above
    the box itself.
    Last year, I tried implementing this behavior manually, but older OSes
    get deeply confused if the combo box dropdown lies over the combo box -
    in fact, the "mouse up" after clicking a drop-down registers directly on
    the dropdown, automatically closing it, and making it impossible to
    raise the dropdown at all!  Working around this behavior in some Windows
    versions but not others was a mess, and I dropped it.
    I don't want to rewrite pdComboBox until I'm done with pdListBox, as
    I'll be using it to handle the dropdown rendering, but that will finally
    solve #171, among other things.  In the meantime, this (cheap and dirty)
    fix at least prevents combo box text from being cropped until the box
    has been clicked at least once.
  2. Purge old tooltip class

    A lot of dialogs were affected by this, but perhaps best of all, this
    decreases load time for pretty much every dialog in the program, as we
    don't have to iterate through all controls a second time to check for
    tooltip-specific translations.
  3. First test of the new XML-based function parameter system

    My goal for PD 7.0 is to reduce all effect functions to take a single
    parameter of type String.  (Preview-related flag parameters will still
    be present; the single String parameter is for function-specific
    parameters, only.)  This approach simplifies many things across the
    program: the central processor sub, macro recording/editing/versioning,
    the eventual move to a plugin-based architecture.
    PD already makes use of a param string system, where effect dialogs
    forward parameter lists, as a pipe-delimited string, to the central
    processor.  The central processor then stores those strings (as
    necessary), and when an effect is actually run, the processor parses out
    individual parameters, converts them to their appropriate numeric types,
    then forwards them to the effect function in their correct order.
    There are problems with this technique.  It makes the central processor
    huge and complicated.  Changes to individual filters require
    corresponding changes in the processor, complicating maintenance.  And
    if a filter is changed between versions, the filter itself has no way to
    handle missing parameters from (e.g.) old macro files, because the
    central processor is the one who detects the missing parameter and plugs
    in a default value for them.
    By letting filter modules control all their own parameter handling, a
    lot of things become simpler.  The central processor is now just a dumb
    router, sending strings where they need to go.  Individual filters can
    use identical parameter handling code for previews and full effects.
    Parameters will be handled by name, not ordinal, making maintenance (and
    enhancement) much easier, especially if we change function parameters
    between releases.
    The nightmare, of course, is rewriting every filter and function in the
    program to use this new parameter system.  I'm going to roll out the
    changes gradually, as there's a large potential for typos and accidental
    breakage, so apologies for the mishmash of parameter methods in the
  4. Effects > Artistic > Film Noir: rewrite from scratch with a new dialog

    One more one-click filter converted to something actually useful!
    As part of the overhaul, this is PD's first effect to operate entirely
    in a floating-point (HDR-friendly) luminance space.  This provides a
    much nicer result when working with a black-and-white image,
    particularly one meant as an homage to classic 40's noir stylings.  The
    long-term goal is to add HDR support to many more tools, but that's
    still a ways off.
  5. Minor cosmetic fixes

Commits on Oct 3, 2015
  1. Effects > Light and Shadow > Cross Screen: overhaul and greatly optimize

    New features like unidirectional IIR blur and API-based
    rotate/edge-clamp functionality have made this tool significantly
    faster, and its results much better-looking.  I was actually looking at
    dropping this effect if I couldn't get the speed up, but now it's better
    in pretty much every way - always a nice win.
  2. Effects > Blur > Motion Blur: provide Gaussian (IIR) option

    This greatly improves the utility of Motion Blur.  The new Gaussian
    option causes the blur to "fall-off" as its distance from the pixel
    increases, causing a much more natural blur.  The end result is
    identical to Photoshop's methodology, and similar to the "wind" stylize
    effect they provide.  (In fact, I may look at providing a "wind" stylize
    option now that this is available!)
  3. Generic filters: new horizontal-only IIR implementation

    This highly-optimized IIR blur can be used to blur in a single
    direction, either asymmetrically (e.g. [n] pixels to the right), or
    symmetrically (e.g. [n] pixels both right and left).
    Directional blur is used in a number of different PD filters, and IIR
    gives a much more natural result than box blur, at a small speed and
    memory trade-off.  However, the memory trade-off is basically a wash, as
    IIR is an in-place transform, meaning we do not need separate source and
    destination images to obtain correct results.
  4. Effects > Noise > Mean-shift filter: new noise removal technique

    The mean shift operator is described nicely at Wikipedia:
    It can be thought of as a faster, cheaper version of the bilateral
    filter.  Mean-shifting involves searching some radius [r] around a
    pixel, and taking the average of all pixels that lie within some
    user-specified threshold [t].  This makes it different from blurring,
    because only similar pixels are considered, while dissimilar pixels are
    ignored.  This nicely preserves high-contrast edges in the target image.
    At low levels of [r] and [t], lightweight denoising occurs.  At high
    levels of [r] and/or [t], an effect similar to bilateral smoothing
    occurs, where edges are preserved, but contiguous patches of color are
    As part of this change, I have also renamed @audioglider's Bilateral
    filter tool to "Bilateral smoothing" in the menu, rather than the
    generic "Remove noise" title I gave it before.  I've gotten multiple
    requests for a bilateral smoothing tool, so I may as well ensure people
    know that such a tool does actually exist in the project.  :)
Commits on Oct 2, 2015
  1. Effects > Artistic > Comic book: add additional strength option

    Still need to rework the "ink" method at some point, but in the interim,
    this provides more control over the final coloring result.
  2. Effects > Pixelate > Mosaic: add support for variable angles

    A perfect test for the new "rotate + edge-extend" function.  No
    performance hit, and lots of new possibilities.  Cool!
  3. Effects > Blur > Motion Blur: 10x speed increase

    To put this tool's performance into perspective, it is faster than GIMP
    and Paint.NET *while inside the IDE*.
    When compiled, it's ~15x faster than GIMP, and ~30x faster than
    Paint.NET.  Not bad for little ol' VB6.
  4. Finally crack the math for API-accelerated rotation + edge clamping

    This was unpleasant, but it opens up a large range of possibilities for
    extending existing filters.
    The basic idea is this: many filters operate on a horizontal+vertical
    grid (e.g. blur).  These operations could be much more useful and/or
    interesting if variable angles were supported, but attempting to
    interpolate something like blur at any angle incurs a massive hit to
    For an operation like motion blur, where angle support is a necessity,
    we can optimize the filter by rotating the image once, applying an
    optimized horizontal/vertical blur, then rotating the image back to its
    original orientation.  The problem with this method, as usual, is how to
    handle image edges.
    When rotating an image into a new container, there are large, blank
    corners where the rotated image doesn't fill the new container.  This
    introduces blank pixels into any horizontal or vertical calculations,
    which screws up all calculations because those blank pixels didn't exist
    in the original image!
    The highest-quality workaround is to stretch out the edges of the
    original image to cover the bare areas left behind by rotation.  PD has
    long provided a way to do this, but it's incredibly time-consuming, as
    we have to manually interpolate each pixel of the bare regions, and VB's
    SafeArrays incur a heavy penalty during interpolation since we have to
    do at least four array accesses for each interpolation, then a bunch of
    floating-point math to calculate accurate colors.
    It occurred to me that the "edge clamp" step could be accelerated using
    a parallelogram approach, and something like PlgBlt (but antialiased and
    interpolated, obviously).  GDI+ offers such a function, but working out
    the math for all four image edges, while also taking into account GDI+'s
    propensity for things being off by subpixel amounts, wasn't pretty.
    Anyway, the function is finally working, and I've already integrated it
    into PD's motion blur tool (which cut the existing code amount by dozens
    of lines; always nice!).
    The speed increase of this new version massive; on a 6 megapixel 32-bpp
    image, the latest versions of GIMP and Paint.NET clock in at 33 and 58
    seconds respectively, for a 200 px motion blur.  PD does the same thing
    in just over two seconds - an order of magnitude faster, and with
    identical results, including proper handling of alpha bytes.
    This new function allows variable angles to be extended to any grid
    function with little-to-no speed penalty, which is a massive win, let
    alone the speed increases it provides to existing functions like motion
Commits on Oct 1, 2015
  1. Layers toolbar: add dummy panel for testing

    So far, so good!
  2. pdCaption: add support for bold fonts

    Not sure if I'll make use of this in most PD controls, but it's there if
    I need it
Commits on Sep 30, 2015
  1. Macro recording: warn the user prior to saving empty macros

    Fixes #175.  Many thanks to @vhreal1302 for catching and reporting.
    If the user attempts to save an empty macro, they will now be warned,
    and given the choice to continue recording.  If they ignore the warning,
    an empty macro file is no longer saved.
    Additional failsafes are also in place for previously saved macros with
    zero playback steps (although PD cannot physically write such files now,
    I figure "better safe than sorry").
  2. Import online image: trim whitespace from URL prior to processing

    Can't believe I missed this before; sorry!
  3. Minor bugfixes and additional hardening against potential window mana…

    …ger errors
    There are some weird window manager issues when the image tabstrip
    orientation is changed and the program is restarted, but I'm having
    trouble tracking down an exact cause.  In the meantime, these fixes
    prevent a hard crash.
    (Fun sidenote: PD should now be runnable with the IDE set to "Break on
    all errors", thanks to rewriting a bunch of code that relies on error
    handling for proper behavior.)
  4. pdTitle: a new UI element for controlling collapsible panels.

    The main place I'm implementing this is on the right-side toolbar on the
    main window, where the layers toolbar is soon going to become a
    multipurpose toolbar with a number of other panels.
    Final appearance of the UC is TBD, pending implementation of other
    panels on the toolbar.
Commits on Sep 27, 2015
  1. Layer toolbox: start prepping for collapsible panel support

    The right-side toolbox is going to be a lot more useful by the time 7.0
    releases.  My goal is to finally implement independently collapsible
    sections with some new tools PD's been lacking for too long (a Navigator
    panel, for example).  This is also a necessary step to preparing for a
    selection tool overhaul, where selections work more like layers (with
    independently editable selection objects that can be merged via various
    set operators).
    To that end, the main toolbox form is now just a minimalist container
    for various subforms, each of which contains a single collapsible panel.
    New helper classes for sub-window management will make this much easier,
    but still to-do is a new clickable label+button UC that will handle the
    actual collapsing/expanding of each panel.
    At present, the dialog works pretty much how it did before, except that
    the layer toolbox / blend mode / opacity controls now live on an
    entirely separate form that's dynamically synchronized to the toolbox's
    size and shape, as necessary.
  2. Screen capture: minor fixes to improve Windows 8.1/10 capturing

    The whole way this tool functions on Win 10 probably needs to be
    revisited, but in the meantime, this commit enables capturing of
    DirectX-style windows (assuming the window response to WM_PRINT
    messages, which is never guaranteed).  This allows some universal
    Windows apps to be captured correctly, regardless of their z-order on
    the desktop.
Commits on Sep 24, 2015
  1. Add first paint brush toolbox button

    Lots left to do before this button actually does anything, but I gotta
    start somewhere
  2. Simplify UI reflow code for the primary toolbox

    ...because it's time to add new buttons!
Commits on Sep 23, 2015
  1. Improve high-DPI support for pdCanvas, pdComboBox, and pdLabel

    pdComboBox is proving to be a nasty piece of work.  Given the
    complexities involved in trying to synchronize a system combo box with
    an underlying VB control, I'm heavily considering wiping my existing
    work and writing my own combo box from scratch.
    With that in mind, there are still some small pixel-level issues with
    certain combo boxes that dynamically set their size according to their
    contents.  Fixing this is on my to-do list.
  2. pdWindowSize: new helper class for DPI-aware manipulation of user con…

    I hate to resort to this, but VB's internal measurements (and
    accompanying size/position functions) are hopelessly broken on any DPI
    where TwipsPerPixel doesn't resolve to a whole number.  While there are
    workarounds, they are clumsy and hackish, so I'd rather just rely on API
    functions to handle all movement and positioning code.
    To that end, user controls can now attach a pdWindowSize class to handle
    movement/size data for them.  A few helper functions can also be exposed
    to simplify move/size requests for outside callers, as relevant.  I
    think this is the least of many evils when it comes to creating proper
    high-DPI support across PD's wide range of UCs.
  3. pdDisplays: calculate all twips modifiers internally

    Otherwise, the splash screen may not be centered correctly as we process
    it before initializing a bunch of PD's generic Interface systems
  4. Fix system DPI detection method

    Surface systems may use a different (custom?) scaling system, but this
    method works well enough on traditional PCs.  Will investigate further
    as necessary.
Something went wrong with that request. Please try again.