b9337e22ce
see https://gerrit.libreoffice.org/#/c/3367/ and Change-Id: I00c96fa77d04b33a6f8c8cd3490dfcd9bdc9e84a for details Change-Id: I199a75bc4042af20817265d5ef85b1134a96ff5a
331 lines
12 KiB
C++
331 lines
12 KiB
C++
/* -*- 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_RGBMASKPIXELFORMATS_HXX
|
|
#define INCLUDED_BASEBMP_RGBMASKPIXELFORMATS_HXX
|
|
|
|
#include <basebmp/color.hxx>
|
|
#include <basebmp/colortraits.hxx>
|
|
#include <basebmp/accessor.hxx>
|
|
#include <basebmp/pixeliterator.hxx>
|
|
#include <basebmp/pixelformatadapters.hxx>
|
|
#include <basebmp/metafunctions.hxx>
|
|
#include <basebmp/endian.hxx>
|
|
|
|
#include <vigra/numerictraits.hxx>
|
|
#include <vigra/metaprogramming.hxx>
|
|
|
|
#include <functional>
|
|
|
|
namespace basebmp
|
|
{
|
|
|
|
/** Base class operating on RGB truecolor mask pixel
|
|
|
|
Use this template, if you have an (integer) pixel type, and three
|
|
bitmasks denoting where the channel bits are.
|
|
|
|
@tpl PixelType
|
|
Input pixel type to operate on
|
|
|
|
@tpl ColorType
|
|
Underlying color type, to convert the pixel values into
|
|
|
|
@tpl RedMask
|
|
Bitmask, to access the red bits in the data type
|
|
|
|
@tpl GreenMask
|
|
Bitmask, to access the green bits in the data type
|
|
|
|
@tpl BlueMask
|
|
Bitmask, to access the blue bits in the data type
|
|
|
|
@tpl SwapBytes
|
|
When true, the final pixel values will be byte-swapped before
|
|
passed on.
|
|
*/
|
|
template< typename PixelType,
|
|
typename ColorType,
|
|
unsigned int RedMask,
|
|
unsigned int GreenMask,
|
|
unsigned int BlueMask,
|
|
bool SwapBytes > struct RGBMaskFunctorBase
|
|
{
|
|
typedef PixelType pixel_type;
|
|
typedef ColorType color_type;
|
|
typedef typename make_unsigned<pixel_type>::type unsigned_pixel_type;
|
|
typedef typename ColorTraits<ColorType>::component_type component_type;
|
|
|
|
// calc corrective shifts for all three channels in advance
|
|
enum {
|
|
red_shift = numberOfTrailingZeros<RedMask>::value,
|
|
green_shift = numberOfTrailingZeros<GreenMask>::value,
|
|
blue_shift = numberOfTrailingZeros<BlueMask>::value,
|
|
|
|
red_bits = bitcount<RedMask>::value,
|
|
green_bits = bitcount<GreenMask>::value,
|
|
blue_bits = bitcount<BlueMask>::value
|
|
};
|
|
};
|
|
|
|
template< typename PixelType,
|
|
typename ColorType,
|
|
unsigned int RedMask,
|
|
unsigned int GreenMask,
|
|
unsigned int BlueMask,
|
|
bool SwapBytes > struct RGBMaskGetter :
|
|
public RGBMaskFunctorBase<PixelType,
|
|
ColorType,
|
|
RedMask,
|
|
GreenMask,
|
|
BlueMask,
|
|
SwapBytes>,
|
|
public std::unary_function<PixelType, ColorType>
|
|
{
|
|
typedef RGBMaskFunctorBase<PixelType,
|
|
ColorType,
|
|
RedMask,
|
|
GreenMask,
|
|
BlueMask,
|
|
SwapBytes> base_type;
|
|
|
|
ColorType operator()( PixelType v ) const
|
|
{
|
|
v = SwapBytes ? byteSwap(v) : v;
|
|
|
|
const typename base_type::unsigned_pixel_type red (v & RedMask);
|
|
const typename base_type::unsigned_pixel_type green(v & GreenMask);
|
|
const typename base_type::unsigned_pixel_type blue (v & BlueMask);
|
|
|
|
// shift color nibbles to right-aligend position. ORing it
|
|
// channel value shifted twice the number of channel bits, to
|
|
// spread the value into the component_type range
|
|
ColorType res( (shiftRight(red,
|
|
base_type::red_shift-8*
|
|
(signed)sizeof(typename base_type::component_type)+
|
|
base_type::red_bits)) |
|
|
(shiftRight(red,
|
|
base_type::red_shift-8*
|
|
(signed)sizeof(typename base_type::component_type)+
|
|
2*base_type::red_bits)),
|
|
|
|
(shiftRight(green,
|
|
base_type::green_shift-8*
|
|
(signed)sizeof(typename base_type::component_type)+
|
|
base_type::green_bits)) |
|
|
(shiftRight(green,
|
|
base_type::green_shift-8*
|
|
(signed)sizeof(typename base_type::component_type)+
|
|
2*base_type::green_bits)),
|
|
|
|
(shiftRight(blue,
|
|
base_type::blue_shift-8*
|
|
(signed)sizeof(typename base_type::component_type)+
|
|
base_type::blue_bits)) |
|
|
(shiftRight(blue,
|
|
base_type::blue_shift-8*
|
|
(signed)sizeof(typename base_type::component_type)+
|
|
2*base_type::blue_bits)) );
|
|
return res;
|
|
}
|
|
};
|
|
|
|
template< typename PixelType,
|
|
typename ColorType,
|
|
unsigned int RedMask,
|
|
unsigned int GreenMask,
|
|
unsigned int BlueMask,
|
|
bool SwapBytes > struct RGBMaskSetter :
|
|
public RGBMaskFunctorBase<PixelType,
|
|
ColorType,
|
|
RedMask,
|
|
GreenMask,
|
|
BlueMask,
|
|
SwapBytes>,
|
|
public std::unary_function<ColorType, PixelType>
|
|
{
|
|
typedef RGBMaskFunctorBase<PixelType,
|
|
ColorType,
|
|
RedMask,
|
|
GreenMask,
|
|
BlueMask,
|
|
SwapBytes> base_type;
|
|
|
|
PixelType operator()( ColorType const& c ) const
|
|
{
|
|
const typename base_type::unsigned_pixel_type red (c.getRed());
|
|
const typename base_type::unsigned_pixel_type green(c.getGreen());
|
|
const typename base_type::unsigned_pixel_type blue (c.getBlue());
|
|
|
|
typename base_type::unsigned_pixel_type res(
|
|
(shiftLeft(red,
|
|
base_type::red_shift-8*
|
|
(signed)sizeof(typename base_type::component_type)+
|
|
base_type::red_bits) & RedMask) |
|
|
(shiftLeft(green,
|
|
base_type::green_shift-8*
|
|
(signed)sizeof(typename base_type::component_type)+
|
|
base_type::green_bits) & GreenMask) |
|
|
(shiftLeft(blue,
|
|
base_type::blue_shift-8*
|
|
(signed)sizeof(typename base_type::component_type)+
|
|
base_type::blue_bits) & BlueMask) );
|
|
|
|
return SwapBytes ? byteSwap(res) : res;
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
template< typename PixelType,
|
|
unsigned int RedMask,
|
|
unsigned int GreenMask,
|
|
unsigned int BlueMask,
|
|
bool SwapBytes > struct PixelFormatTraitsTemplate_RGBMask
|
|
{
|
|
typedef PixelType pixel_type;
|
|
|
|
typedef RGBMaskGetter<pixel_type,
|
|
Color,
|
|
RedMask,
|
|
GreenMask,
|
|
BlueMask,
|
|
SwapBytes> getter_type;
|
|
typedef RGBMaskSetter<pixel_type,
|
|
Color,
|
|
RedMask,
|
|
GreenMask,
|
|
BlueMask,
|
|
SwapBytes> setter_type;
|
|
|
|
typedef PixelIterator<pixel_type> iterator_type;
|
|
typedef StandardAccessor<pixel_type> raw_accessor_type;
|
|
typedef AccessorSelector<
|
|
getter_type, setter_type> accessor_selector;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Hopefully this is an understandable plaintext explanation that matches
|
|
// reality...
|
|
|
|
// BASEBMP_TRUECOLORMASK_LSB_SWAP means that on a big-endian platform, a pixel
|
|
// value when viewed as an integer (16 or 32 bits) has to be byte-swapped for
|
|
// the channels to match the masks. Or equivalently (I think), on a big-endian
|
|
// platform, the masks need to be byte-swapped to be correct.
|
|
|
|
// I.e. on a litte-endian platform the masks work as such.
|
|
|
|
// BASEBMP_TRUECOLORMASK_MSB_SWAP means the opposite. The masks work as such
|
|
// on big-endian platforms, on little-endian platforms the pixel needs to be
|
|
// byte-swapped for the masks to work.
|
|
|
|
// So in a sense these two names are "backward". It sounds to me as if
|
|
// BASEBMP_TRUECOLORMASK_LSB_SWAP would mean "when on LSB, swap" ;)
|
|
|
|
#ifdef OSL_LITENDIAN
|
|
# define BASEBMP_TRUECOLORMASK_LSB_SWAP false
|
|
# define BASEBMP_TRUECOLORMASK_MSB_SWAP true
|
|
#else
|
|
# ifdef OSL_BIGENDIAN
|
|
# define BASEBMP_TRUECOLORMASK_LSB_SWAP true
|
|
# define BASEBMP_TRUECOLORMASK_MSB_SWAP false
|
|
# else
|
|
# error Undetermined endianness!
|
|
# endif
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// 16bpp MSB RGB
|
|
typedef PixelFormatTraitsTemplate_RGBMask<
|
|
sal_uInt16,
|
|
0xF800,
|
|
0x07E0,
|
|
0x001F,
|
|
BASEBMP_TRUECOLORMASK_MSB_SWAP > PixelFormatTraits_RGB16_565_MSB;
|
|
BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_RGB16_565_MSB::getter_type,
|
|
PixelFormatTraits_RGB16_565_MSB::setter_type);
|
|
|
|
// 16bpp LSB RGB
|
|
typedef PixelFormatTraitsTemplate_RGBMask<
|
|
sal_uInt16,
|
|
0xF800,
|
|
0x07E0,
|
|
0x001F,
|
|
BASEBMP_TRUECOLORMASK_LSB_SWAP > PixelFormatTraits_RGB16_565_LSB;
|
|
BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_RGB16_565_LSB::getter_type,
|
|
PixelFormatTraits_RGB16_565_LSB::setter_type);
|
|
|
|
|
|
// 32bpp formats
|
|
|
|
// The intent is that the order of channel names in the names of the 32bpp
|
|
// format typedefs below correspond to the order of the channel bytes in
|
|
// memory, if I understand correctly.... I think the point with the below
|
|
// formats is that the channel byte order in memory is the same regardless of
|
|
// platform byte order.
|
|
|
|
// This one used to be called PixelFormatTraits_RGB32_888.
|
|
|
|
typedef PixelFormatTraitsTemplate_RGBMask<
|
|
sal_uInt32,
|
|
0x00FF0000,
|
|
0x0000FF00,
|
|
0x000000FF,
|
|
BASEBMP_TRUECOLORMASK_LSB_SWAP > PixelFormatTraits_BGRX32_8888;
|
|
BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_BGRX32_8888::getter_type,
|
|
PixelFormatTraits_BGRX32_8888::setter_type);
|
|
|
|
// This one used to be called PixelFormatTraits_BGR32_888.
|
|
|
|
typedef PixelFormatTraitsTemplate_RGBMask<
|
|
sal_uInt32,
|
|
0x00FF0000,
|
|
0x0000FF00,
|
|
0x000000FF,
|
|
BASEBMP_TRUECOLORMASK_MSB_SWAP > PixelFormatTraits_XRGB32_8888;
|
|
BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_XRGB32_8888::getter_type,
|
|
PixelFormatTraits_XRGB32_8888::setter_type);
|
|
|
|
// The following two ones were added for Android needs and for completeness
|
|
|
|
typedef PixelFormatTraitsTemplate_RGBMask<
|
|
sal_uInt32,
|
|
0xFF000000,
|
|
0x00FF0000,
|
|
0x0000FF00,
|
|
BASEBMP_TRUECOLORMASK_LSB_SWAP > PixelFormatTraits_XBGR32_8888;
|
|
BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_XBGR32_8888::getter_type,
|
|
PixelFormatTraits_XBGR32_8888::setter_type);
|
|
|
|
typedef PixelFormatTraitsTemplate_RGBMask<
|
|
sal_uInt32,
|
|
0xFF000000,
|
|
0x00FF0000,
|
|
0x0000FF00,
|
|
BASEBMP_TRUECOLORMASK_MSB_SWAP > PixelFormatTraits_RGBX32_8888;
|
|
BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_RGBX32_8888::getter_type,
|
|
PixelFormatTraits_RGBX32_8888::setter_type);
|
|
|
|
} // namespace basebmp
|
|
|
|
#endif /* INCLUDED_BASEBMP_RGBMASKPIXELFORMATS_HXX */
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|