Permalink
Commits on Jan 17, 2017
  1. Effects > Stylize > Palettize: many new features

    (Note: this effect was formerly the Image > Indexed color... menu, but
    as explained in a previous commit, it no longer makes sense there.)
    
    - Dithering is now supported across all adaptive quantization methods.
    11 different options, including both ordered (fixed) and error-diffusion
    methods are available.
    - An option to precisely preserve white and black in the final palette
    is now available.  Note that white and/or black are only preserved if
    they exist in the original image.  (Otherwise, we'd be wasting palette
    entries on them.)
    - Reduced color bleed is now an available option.
    - Minor bugfixes to the pdMedianCut class.
    committed Jan 17, 2017
Commits on Jan 16, 2017
  1. Image > Indexed color: move to Effects > Stylize menu and add Median …

    …Cut option
    
    The original Image menu position for "Indexed Color" was a byproduct of
    PD's pre-layer days.  Photoshop provides Indexed Color as a dedicated
    Image mode, but a similar approach in PD is never gonna happen (by
    design!).  Instead, PD's indexed color features exists primarily to
    support better image format I/O, and any direct exposure to the user
    exists mainly for fun or artistic purposes.  (Or for pros to fine-tune
    their 8-bpp conversion results.)
    
    To that end, it makes way more sense to remove all of the tool's current
    restrictions (like requiring layer flattening), and move it to the
    Effects menu.  Now, users can now apply color indexing to any arbitrary
    layer, and they can do it without flattening the entire damn image.
    
    I've also my new home-built median cut method to the quantization
    options, which provides much-improved results on photos of humans (as it
    preferentially favors preservation of flesh tones).
    
    Coming soon is dithering options, which have been missing from the
    program for far too long.
    committed Jan 16, 2017
  2. Fix automatic translations for Chinese languages

    Thank you to ChenLin for contributing an elegant fix
    committed Jan 16, 2017
Commits on Jan 15, 2017
  1. Big drop: lots of new 256-color / palette code

    PhotoDemon is (and always will be) focused on editing photos.  But that
    doesn't mean we can't do some cool things with palettes and indexed
    color modes.  (For example, there are a number of interesting features,
    adjustments, effects, and paint ops that lean on things like custom
    palettes.)
    
    To that end, I've dropped a bunch of palette-related code into PD.  At
    present, this code is not exposed to the user in meaningful ways.
    Instead, it is a large collection of algorithms, modules, and classes
    built around palette generation and application.  Effects and
    adjustments that use these tools are coming soon, alongside other
    feature-centric 7.0 development.
    
    Included in this commit are:
    
    1) A new "ResizeDIBByPixelCount" function.  This function resizes a
    target image to a specific number of pixels (e.g. "resize to 50,000
    pixels"), while preserving aspect ratio.  This is extremely helpful for
    things like image heuristics, because heuristics don't need a full copy
    of the image.  A small copy still provides all the information we need
    (when building things like histograms or color maps), and this function
    lets those heuristics run at a constant time, independent of image size.
    
    2) A new "GetOptimizedPalette()" function.  Given an arbitrary source
    image, this function returns an optimal palette of that image on the
    range [2, 256] colors (as specified by the caller).  This function is a
    custom-built median cut-like implementation, using pure VB6, and it's as
    fast (or faster) then the existing color quantizers we've been using
    from the FreeImage library.
    
    The main reason I wanted to custom-build my own quantizer is because
    FreeImage's quantizers require a lot of memory, they're not especially
    fast, they can't just return a palette (e.g. they *always* apply the
    palette to the image) and the library as a whole is prone to problematic
    edge-cases that aren't well-tested.
    
    Also, like most other features in the program, we can generally produce
    ones than free 3rd-party libraries.  (For example, the current quantizer
    runs in RGB space, but it would be trivial to add a Lab version for
    improved results.)
    
    Anyway, the quantizer is well-documented and straightforward in
    operation.
    
    3) Four (!!!) different "ApplyPaletteToImage" functions.  Not all of
    these functions may remain in the project, but I wanted to commit them
    all in case a revert is needed in the future.
    
    As it turns out, applying a palette to an image is actually much more
    time-consuming than generating the damn palette in the first place.  As
    such, I've tested a number of different prototypes over the past year,
    with a few interesting discoveries along the way.
    
    In order of performance (slowest to fastest), here are the ApplyPalette
    algorithms now available to PD:
    
    1) A naive, perfect matching function that searches the entire palette
    for a "best" match against each pixel.  As you'd expect, this function
    is slow, but it's useful because we can modify the color-matching
    algorithm to something much better than plain old Euclidean distance.
    (For example, it currently uses a weighted comparison where each color
    component is weighted by its sensitivity to the human eye.)
    
    This function will always yield the best results, but it'll take awhile
    to get there.
    
    2) A WAPI-optimized version of (1) above, using standard Euclidean
    distance matching for colors.  For whatever reason, GDI's
    GetNearestPaletteIndex() function is much faster than an identical
    function in VB, so this cuts the time of our naive function by about
    75%.  (It's also equally fast in the IDE or compiled, which is nice
    during testing phases.)
    
    3) A lossy hash-table lookup.  Colors are sorted by their distance from
    black, than organized into [n] hash buckets (where the caller controls
    [n]).  More buckets = faster performance but lower quality.  At its
    default setting, this is roughly 2x faster than an exhaustive match
    using GDI, while the resulting image is very close quality-wise.
    
    Hash tables are particularly useful if applying a palette with
    dithering, because dithering automatically compensates for the small
    errors due to hash table misses.  It is also unique in giving the caller
    some control over the performance vs accuracy trade-off.
    
    4) A self-pruning octree color lookup.  Octrees can also be used for
    palette generation (and I may actually implement this in the future,
    although our median-cut system will likely be better quality-wise), but
    here, I'm purely interested in using them to accelerate the
    color-matching process.  A self-pruning system means that colors are
    always placed in the highest-possible tree depth, making color lookups
    about as fast as you can physically get in VB (outside of VB-specific
    performance tricks).  This system is roughly 4x faster than the
    "perfect" GDI solution, but note that it is *not* guaranteed to return
    ideal matches.  (Colors are placed in the tree by bit-order, so colors
    that lie very near bit boundaries don't match well - e.g. RGB(127, 127,
    127) will map to RGB(0, 0, 0) instead of RGB(128,128,128) because it
    shares a top-most bit with the former, despite the latter being closer).
    
    I have some ideas for mitigating the imperfect color-matching nature of
    octrees, but as with hash-tables, the lossy nature is not a very big
    deal when dithering, as dithering minimizes the visual impact.  (In
    fact, the end result during dithering can sometimes be *better* if
    colors are matched imperfectly, as you escape some of the patterned-ness
    inherent to dithering.)
    
    So that's an overview what this commit contains.  Part of the reason I
    wanted to commit it now is that with paint tool development in full
    swing, the color selector would greatly benefit from a "generate a
    palette with colors from my current image" feature.  We can now do that
    with just a few lines of (very fast) code.
    
    Note that this commit is also a prerequisite to proper swatch support,
    which has been in the pipeline for a very long time.
    committed Jan 15, 2017
Commits on Jan 13, 2017
  1. Add first round of failsafe checks for missing theme+resource data

    I still have issues with users who use crappy old .zip software (*cough*
    WinZip *cough*) to unzip PhotoDemon downloads.  Said software will
    sometimes .zip all folder contents into a single base folder instead of
    preserving proper folder structure.
    
    I've now added failsafe recoveries for theme data, which is now integral
    to proper PD operation.
    
    In the future, I'll be adding an additional failsafe where missing data
    is recovered directly from the resource section of PD's base .exe... but
    given the amount of binary data involved, I don't want to do that until
    the theme and resource files are closer to their "final" state.
    committed Jan 13, 2017
  2. Language Editor: harden against browser issues

    IE users who install the Chrome Frame plugin will mess up any automated
    IE scripting (see
    http://stackoverflow.com/questions/9713936/chromeactivedocument-returned-from-internetexplorer-application-object).
    
    PD's automatic "Google Translate" suggestions in the Language Editor
    rely on this functionality.  I've now reworked the interface so things
    shouldn't crash when this happens.
    
    Thank you to ChenLin for reporting.
    committed Jan 13, 2017
  3. Resources: detect 256-color images and store them specially

    For images that aren't colored dynamically at run-time (like PD's logo),
    we have historically just saved them as 32-bpp resources, even though
    there are technically few enough colors in the image to use an 8-bpp
    format.
    
    I've now upgraded the resource compressor to properly identify such
    8-bpp images and save them as a palette + palette index stream.  This
    doesn't actually make a meaningful difference in the final resource file
    size (as zstd was smart enough to compress the original 32-bpp data very
    well), but I wanted to implement this before moving PD's logos to the
    new resource format, as they are quite a bit larger than the average
    resource image (which has implications for both decode time, and storage
    size).
    
    So alongside this work, as of this commit, PD's logo is now loaded and
    rendered from our custom resource file.  As a nice bonus, this shaves
    some ~50-100 ms off program load time (because our internal decompressor
    is much faster than GDI+'s PNG decompressor.)
    committed Jan 13, 2017
Commits on Jan 12, 2017
  1. Menus: new central manager

    One of my (long-term) goals for PD is to allow more customization over
    menu layouts.  If a user is accustomed to Photoshop or GIMP's layouts,
    they shouldn't have to  learn a whole new system just for PD.
    
    Actually implementing a system flexible enough to do this is a long ways
    off, but we can start making baby steps toward it.  First up is managing
    all menu interactions through a central menu manager, which tracks
    things like menu captions, positions, icons and more.  (Note that I have
    yet to merge accelerator handling with this class; that's coming.)  I've
    migrated the existing File menu and submenu handling to this new
    manager, and other menus will follow as I get their icons sorted out.
    committed Jan 12, 2017
  2. Geometry engine: performance improvements

    I was getting bored of all this UI work, so I spent a little time today
    optimizing PD's Atan2() function.  The end result is a function about
    50% faster than the old iteration, which translates to a 1+ second
    benefit across various distort and effect functions.  (Higher quality
    settings see larger benefits, since Atan2() is often called inside the
    supersampling loop.)
    committed Jan 12, 2017
  3. Update generator+patcher: add support for new theming data

    Eventually I'll build the theme files directly into PD's executable
    file, so it can extract them as a failsafe if they go missing or become
    corrupted.  For now, however, the files are still in flux so I don't
    want to commit them just yet.  (In other words, don't delete or screw
    with the /App/PhotoDemon/Themes folder - it's essential to proper
    program operation.)
    
    That said, PD's update builder and patcher have been updated to create
    and patch files in the /Themes folder.  This should fix problems with
    broken auto-upgrades from past versions.
    
    (Thank you to ChenLin for mentioning this problem to me.)
    committed Jan 12, 2017
Commits on Jan 11, 2017
  1. Theme Editor: fix resource removal code

    Turns out I actually need to use this sometimes
    committed Jan 11, 2017
  2. Fix rare issue with exporting grayscale + alpha PNGs

    FreeImage makes this inordinately difficult, so we have to work around
    some of their issues.  (Fortunately, OptiPNG can restore the idealized
    bit-depth after the fact, but man... what I'd give for a well-written
    image I/O library.)
    committed Jan 11, 2017
  3. Selection tools: fix a bunch of issues related to the new tool panel …

    …design
    
    Selections are still in desperate need of an overhaul, but one problem
    at a time...
    committed Jan 11, 2017
  4. Move/size tool: fix max/min syncing behavior

    Also fixed a similar problem on the "quick-fix" tool, which is still
    slated for destruction in the near future...
    committed Jan 11, 2017
Commits on Jan 10, 2017
  1. Autosave engine: fix recovery algorithm to match new 7.0 features

    This fixes a number of pesky issues with both the "recover autosaves
    UI", and the algorithm that recovers multiple images at once.
    
    I hope no one ever needs to use these features, but just in case,
    they're working now. ;)
    committed Jan 10, 2017
  2. Migrate remaining large icons to new resource format

    This is exciting!  Now the largest remaining project are the menu icons,
    but as these are far less mission-critical, they'll go much much faster.
    committed Jan 10, 2017
  3. Improve image load time

    I'm still trying to isolate UI synchronization events and only apply
    them when absolutely possible; this makes more good strides toward a
    "perfect" solution, and it pays off after loading an image (as we have
    to update a ton of UI elements to match).
    committed Jan 10, 2017
  4. Updated language files

    Thank you to Roy K for his ongoing translation work
    committed Jan 10, 2017
  5. Tools > Options: continued refinement and trimming

    There are still way too many superfluous bits in this dialog, but I'm
    slowly trimming them down.  In this round, redundant tooltips are gone,
    unnecessary color management performance settings are gone (LittleCMS
    handles this for us), and I've tried to improve dialog load time a bit.
    committed Jan 10, 2017
  6. Effects > Blur > Radial blur: apply in premultiplied alpha space

    Faster + better results = good idea
    committed Jan 10, 2017
Commits on Jan 9, 2017
  1. Continued theming improvements

    - When assigning images to various buttons (and button-like controls),
    the caller no longer has access to custom hover/disabled behavior.  This
    is all handled automatically by the theme engine.
    - The Image > Canvas Size dialog has been migrated to the new theme
    engine.  Instead of pulling "arrow image" resources from the resource
    file, it instead renders them dynamically, at run-time, using current
    theme settings.   (This function is externally accessible, so we can
    reuse it anywhere where we need arrows drawn to the UI.)
    - Other misc clean-up to theming-related code
    committed Jan 9, 2017
Commits on Jan 8, 2017
Commits on Jan 7, 2017
  1. Translation engine: performance improvements

    Now that PD is running on its own UI toolkit, a lot of the old
    translation code can disappear (since PD controls self-manage
    translations).  This makes things like changing the language at run-time
    much faster, since we don't need to "undo" the previous translation
    prior to applying a new one.
    
    Minor improvements to language file load time have also been
    implemented.
    committed Jan 7, 2017
Commits on Jan 6, 2017
  1. Another round of UI performance improvements

    - Enforce case-sensitive matching of XML colors.  This greatly improves
    performance of theme parsing, which further improves load-time of all PD
    custom controls.  (Also, program startup time as a whole is meaningfully
    improved by this.)
    
    - When synchronizing various UI elements against image settings, PD now
    skips checks for tool panels that are not loaded.  (A few weeks ago, I
    rewrote the tool panel manager to only load tool option panels
    on-demand; as such, they are no longer guaranteed to be loaded at any
    given time.)
    
    - Skip text translation efforts in various places if translations are
    not active.  This happens automatically in the translation manager, but
    in many places we can avoid ever needing to call those functions in the
    first place (if the default English translation is in use).
    
    Many other, smaller performance improvements are scattered throughout
    this commit; apologies for not separating them out, but I implemented
    many small fixes while profiling various regions of the project.
    
    As an FYI, over the past few days, program start time has been cut by
    more than 50%.  Never a bad thing!
    committed Jan 6, 2017
  2. Myriad UI performance improvements

    Lots of little updates here, including things like...
    
    1) Avoiding re-theming a control if the current theme matches the theme
    at the last redraw.   (All user controls have been updated to support
    this.)
    2) Faster validation of colors imported from the theme files (e.g. the
    hex -> RGB conversion)
    3) When matching user controls, controls are now searched in the rough
    "popularity order" corresponding to how often they occur in the project
    4) Unnecessary interface reflows are better detected and skipped
    
    No individual update here is necessarily a Big Deal (tm), but the net
    effect of all these small changes should help program responsiveness a
    good deal.  (Also, things like startup time should be meaningfully
    improved.)
    committed Jan 6, 2017
  3. Fix lingering selection issues (due to 32bpp masks)

    When I switched selection masks over to 32bpp so I didn't have to deal
    with stride issues, I didn't realize there were some functions
    hard-coded against the old 24bpp implementation.  These should now be
    fixed.
    committed Jan 6, 2017
  4. Large language file update

    Many thanks to Roy K for his ongoing work in maintaining these.  It's a
    huge amount of work, and having up-to-date translations in the nightly
    builds is something not many projects can afford to offer.
    
    Thank you, Roy!
    committed Jan 6, 2017
  5. Effects > Stylize > Outline

    Since I have this code available, I may as well expose it to the user.
    
    At present, the function only renders the *first* discovered outline on
    a given image.  It works best for contiguous images on a transparent
    background, and there is also an option for solid-colored background
    detection.  I could rework it to detect *all* contiguous outlines in an
    image, but this makes it quite a bit slower... so it'll have to wait.
    committed Jan 6, 2017
  6. Image tabstrip: myriad improvements

    First off, resources have been upgraded to the new format.  I've also
    reworked the tabstrip so it won't load any of its image resources until
    they are actually required, which shaves a few GDI objects off if you're
    just loading one image at a time during a session.
    
    Next, this project led to the development of a new tool in kind of a
    funny way.  I've never been happy with the "image has unsaved changes"
    icon used by the tabstrip.  Because this icon appears over the image
    thumbnail's corner - and the image thumbnail can use any colors under
    the sun - it's difficult to design an icon that works on any combination
    of colors.  The usual tricks (like drop shadows) don't work very well on
    tiny images, so I finally broke down and wrote a proper "render outline
    on any arbitrary 32-bpp image" function.
    
    The new outline generator uses a marching squares algorithm
    (https://en.wikipedia.org/wiki/Marching_squares) to detect the image's
    outline at run-time and return a polygon describing the edges.  These
    edges can then be stroked with any pen of your choosing.
    
    This results in a nice asterisk image that can still be colored however
    we want at run-time, and the outline is then dynamically rendered atop
    it afterward.
    
    has been upgraded to use an outline drawn dynamically at run-time
    committed Jan 6, 2017
Commits on Jan 5, 2017
  1. Adjustments> Levels tool: modernize UI

    The "level node" interface bits are now dynamically rendered at
    run-time, using theme settings, instead of pulling static images from
    the resource file.  This means the dialog now adheres to the same UI
    rules as the rest of the program (finally!).
    
    I've also removed a number of other unused resources, and as a result,
    .exe size continues to drop.
    committed Jan 5, 2017
Commits on Jan 4, 2017