summaryrefslogtreecommitdiff
path: root/basebmp/inc/basebmp/colormisc.hxx
blob: d2142968d3bac6d06813138f59bd197fc8b6bdb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_BASEBMP_COLORMISC_HXX
#define INCLUDED_BASEBMP_COLORMISC_HXX

#include <osl/diagnose.h>
#include <basebmp/color.hxx>
#include <basebmp/colortraits.hxx>
#include <basebmp/accessortraits.hxx>
#include <vigra/mathutil.hxx>

// Contents of this header moved out of color.hxx, as it is not useful
// for the general public (drags in vigra and other template
// functionality, that shouldn't be necessary for the ordinary client
// of BitmapDevice etc.)

namespace basebmp
{

template< bool polarity > struct ColorBitmaskOutputMaskFunctor;
template<> struct ColorBitmaskOutputMaskFunctor<true> : MaskFunctorBase<Color,sal_uInt8>
{
    Color operator()( Color v1, sal_uInt8 m, Color v2 ) const
    {
        OSL_ASSERT(m<=1);

        return Color(v1.toInt32()*(sal_uInt8)(1-m) + v2.toInt32()*m);
    }
};
template<> struct ColorBitmaskOutputMaskFunctor<false> : MaskFunctorBase<Color,sal_uInt8>
{
    Color operator()( Color v1, sal_uInt8 m, Color v2 ) const
    {
        OSL_ASSERT(m<=1);

        return Color(v1.toInt32()*m + v2.toInt32()*(sal_uInt8)(1-m));
    }
};

/// Specialized output mask functor for Color value type
template<bool polarity> struct outputMaskFunctorSelector< Color, sal_uInt8, polarity, FastMask >
{
    typedef ColorBitmaskOutputMaskFunctor<polarity> type;
};

template< bool polarity > struct ColorBlendFunctor8
  : public TernaryFunctorBase<sal_uInt8,Color,Color,Color>
{
    Color operator()( sal_uInt8 alpha,
                      Color     v1,
                      Color     v2 ) const
    {
        alpha = polarity ? alpha : 255 - alpha;

        const sal_uInt8 v1_red( v1.getRed() );
        const sal_uInt8 v1_green( v1.getGreen() );
        const sal_uInt8 v1_blue( v1.getBlue() );

        // using '>> 8' instead of '/ 0x100' is ill-advised (shifted
        // value might be negative). Better rely on decent optimizer
        // here...
        return Color(((((sal_Int32)v2.getRed() - v1_red)*alpha) / 0x100) + v1_red,
                     ((((sal_Int32)v2.getGreen() - v1_green)*alpha) / 0x100) + v1_green,
                     ((((sal_Int32)v2.getBlue() - v1_blue)*alpha) / 0x100) + v1_blue);
    }
};

template< bool polarity > struct ColorBlendFunctor32
  : public TernaryFunctorBase<Color,Color,Color,Color>
{
    Color operator()( Color input,
                      Color v1,
                      Color v2 ) const
    {
        sal_uInt8 alpha = input.getGreyscale();
        alpha = polarity ? alpha : 255 - alpha;

        const sal_uInt8 v1_red( v1.getRed() );
        const sal_uInt8 v1_green( v1.getGreen() );
        const sal_uInt8 v1_blue( v1.getBlue() );

        // using '>> 8' instead of '/ 0x100' is ill-advised (shifted
        // value might be negative). Better rely on decent optimizer
        // here...
        return Color(((((sal_Int32)v2.getRed() - v1_red)*alpha) / 0x100) + v1_red,
                     ((((sal_Int32)v2.getGreen() - v1_green)*alpha) / 0x100) + v1_green,
                     ((((sal_Int32)v2.getBlue() - v1_blue)*alpha) / 0x100) + v1_blue);
    }
};

//-----------------------------------------------------------------------------

template<> struct ColorTraits< Color >
{
    /// @return number of color channels
    static int numChannels() { return 3; }

    /// Type of a color component (i.e. the type of an individual channel)
    typedef sal_uInt8 component_type;

    /// Metafunction to select blend functor from color and alpha type
    template< typename AlphaType, bool polarity > struct blend_functor;

    /// Calculate normalized distance between color c1 and c2
    static inline double distance( const Color& c1,
                                   const Color& c2 )
    {
        return (c1 - c2).magnitude();
    }

    static inline component_type toGreyscale( const Color& c )
    {
        return c.getGreyscale();
    }

    static inline Color fromGreyscale( component_type c )
    {
        return Color(c,c,c);
    }
};

/// The version for plain 8 bit alpha
template<bool polarity> struct ColorTraits< Color >::blend_functor< sal_uInt8, polarity >
{
    typedef ColorBlendFunctor8<polarity> type;
};

/// The version taking grey value of a Color
template<bool polarity> struct ColorTraits< Color >::blend_functor< Color, polarity >
{
    typedef ColorBlendFunctor32<polarity> type;
};

} // namespace basebmp

namespace vigra
{

template<>
struct NumericTraits<basebmp::Color>
{
    typedef basebmp::Color Type;
    typedef basebmp::Color Promote;
    typedef basebmp::Color RealPromote;
    typedef std::complex<basebmp::Color> ComplexPromote;
    typedef sal_uInt8 ValueType;

    typedef VigraTrueType  isIntegral;
    typedef VigraFalseType isScalar;
    typedef VigraTrueType  isSigned;
    typedef VigraTrueType  isOrdered;
    typedef VigraFalseType isComplex;

    static Type zero() { return Type(); }
    static Type one() { return Type(0x01010101); }
    static Type nonZero() { return Type(0x01010101); }

    static Promote toPromote(const Type& v) { return v; }
    static RealPromote toRealPromote(const Type& v) { return v; }
    static Type fromPromote(const Promote& v) { return v; }
    static Type fromRealPromote(const RealPromote& v) { return v; }
};

} // namespace vigra

#endif /* INCLUDED_BASEBMP_COLORMISC_HXX */

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */