File indexing completed on 2024-05-19 04:22:56

0001 
0002 /*
0003    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
0004    All rights reserved.
0005 
0006    Redistribution and use in source and binary forms, with or without
0007    modification, are permitted provided that the following conditions
0008    are met:
0009 
0010    1. Redistributions of source code must retain the above copyright
0011       notice, this list of conditions and the following disclaimer.
0012    2. Redistributions in binary form must reproduce the above copyright
0013       notice, this list of conditions and the following disclaimer in the
0014       documentation and/or other materials provided with the distribution.
0015 
0016    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0017    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0018    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0019    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0020    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0021    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0022    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0023    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0024    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0025    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0026 */
0027 
0028 
0029 #define DEBUG_KP_EFFECT_BALANCE 0
0030 
0031 
0032 #include "kpEffectBalance.h"
0033 
0034 #include <cmath>
0035 
0036 #include <QImage>
0037 
0038 #include "kpLogCategories.h"
0039 
0040 #include "pixmapfx/kpPixmapFX.h"
0041 
0042 
0043 #if DEBUG_KP_EFFECT_BALANCE
0044     #include <qdatetime.h>
0045 #endif
0046 
0047 
0048 static inline int between0And255 (int val)
0049 {
0050     if (val < 0) {
0051         return 0;
0052     }
0053 
0054     if (val > 255) {
0055         return 255;
0056     }
0057 
0058     return val;
0059 }
0060 
0061 
0062 static inline int brightness (int base, int strength)
0063 {
0064     return between0And255 (base + strength * 255 / 50);
0065 }
0066 
0067 static inline int contrast (int base, int strength)
0068 {
0069     return between0And255 ((base - 127) * (strength + 50) / 50 + 127);
0070 }
0071 
0072 static inline int gamma (int base, int strength)
0073 {
0074     return between0And255 (qRound (255.0 * std::pow (base / 255.0, 1.0 / std::pow (10., strength / 50.0))));
0075 }
0076 
0077 
0078 static inline int brightnessContrastGamma (int base,
0079                                            int newBrightness,
0080                                            int newContrast,
0081                                            int newGamma)
0082 {
0083     return gamma (contrast (brightness (base, newBrightness),
0084                             newContrast),
0085                   newGamma);
0086 }
0087 
0088 // public static
0089 kpImage kpEffectBalance::applyEffect (const kpImage &image,
0090         int channels,
0091         int brightness, int contrast, int gamma)
0092 {
0093 #if DEBUG_KP_EFFECT_BALANCE
0094     qCDebug(kpLogImagelib) << "kpEffectBalance::applyEffect("
0095                << "channels=" << channels
0096                << ",brightness=" << brightness
0097                << ",contrast=" << contrast
0098                << ",gamma=" << gamma
0099                << ")";
0100     QTime timer; timer.start ();
0101 #endif
0102 
0103     QImage qimage = image;
0104 #if DEBUG_KP_EFFECT_BALANCE
0105     qCDebug(kpLogImagelib) << "\tconvertToImage=" << timer.restart ();
0106 #endif
0107 
0108 
0109     quint8 transformRed [256],
0110             transformGreen [256],
0111             transformBlue [256];
0112 
0113     for (int i = 0; i < 256; i++)
0114     {
0115         auto applied = static_cast<quint8> (brightnessContrastGamma (i, brightness, contrast, gamma));
0116 
0117         if (channels & kpEffectBalance::Red) {
0118             transformRed [i] = applied;
0119         }
0120         else {
0121             transformRed [i] = static_cast<quint8> (i);
0122         }
0123 
0124         if (channels & kpEffectBalance::Green) {
0125             transformGreen [i] = applied;
0126         }
0127         else {
0128             transformGreen [i] = static_cast<quint8> (i);
0129         }
0130 
0131         if (channels & kpEffectBalance::Blue) {
0132             transformBlue [i] = applied;
0133         }
0134         else {
0135             transformBlue [i] = static_cast<quint8> (i);
0136         }
0137     }
0138 
0139 #if DEBUG_KP_EFFECT_BALANCE
0140     qCDebug(kpLogImagelib) << "\tbuild lookup=" << timer.restart ();
0141 #endif
0142 
0143 
0144     if (qimage.depth () > 8)
0145     {
0146         for (int y = 0; y < qimage.height (); y++)
0147         {
0148             for (int x = 0; x < qimage.width (); x++)
0149             {
0150                 const QRgb rgb = qimage.pixel (x, y);
0151 
0152                 const auto red = static_cast<quint8> (qRed (rgb));
0153                 const auto green = static_cast<quint8> (qGreen (rgb));
0154                 const auto blue = static_cast<quint8> (qBlue (rgb));
0155                 const auto alpha = static_cast<quint8> (qAlpha (rgb));
0156 
0157                 qimage.setPixel (x, y,
0158                     qRgba (transformRed [red],
0159                            transformGreen [green],
0160                            transformBlue [blue],
0161                            alpha));
0162             }
0163         }
0164     }
0165     else
0166     {
0167         for (int i = 0; i < qimage.colorCount (); i++)
0168         {
0169             const QRgb rgb = qimage.color (i);
0170 
0171             const auto red = static_cast<quint8> (qRed (rgb));
0172             const auto green = static_cast<quint8> (qGreen (rgb));
0173             const auto blue = static_cast<quint8> (qBlue (rgb));
0174             const auto alpha = static_cast<quint8> (qAlpha (rgb));
0175 
0176             qimage.setColor (i,
0177                 qRgba (transformRed [red],
0178                        transformGreen [green],
0179                        transformBlue [blue],
0180                        alpha));
0181         }
0182 
0183     }
0184 
0185     return qimage;
0186 }
0187