2010-10-14 08:27:31 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
re-base on ALv2 code. Includes (at least) relevant parts of:
linecap: Reintegrating finished LineCap feature
Patch contributed by Regina Henschel
http://svn.apache.org/viewvc?view=revision&revision=1232507
Patches contributed by Sven Jacobi
impress212: #i81610# fixed animation export
http://svn.apache.org/viewvc?view=revision&revision=1167620
impress212: drawinglayer gbuild environment changes
http://svn.apache.org/viewvc?view=revision&revision=1167627
http://svn.apache.org/viewvc?view=revision&revision=1167628
impress212: DffPropSet -> minor code improvements, removing table
http://svn.apache.org/viewvc?view=revision&revision=1167634
impress212: #158494# fixed excel import (text rotation)
http://svn.apache.org/viewvc?view=revision&revision=1167638
Patches contributed by Armin Le Grand
Svg: Reintegrated Svg replacement from /branches/alg/svgreplavement
http://svn.apache.org/viewvc?view=revision&revision=1220836
#118728# changed indentifying definitions for Svg file detection
http://svn.apache.org/viewvc?view=revision&revision=1229961
#118838# LineGeometry creation for complicated cases optimized to
create single Polygons
http://svn.apache.org/viewvc?view=revision&revision=1236232
#119176# corrected file type detection for SVG for svg files
without xml header
http://svn.apache.org/viewvc?view=revision&revision=1309445
#118728# Extended Svg file detection
http://svn.apache.org/viewvc?view=revision&revision=1230531
#118529# solve break converters and convert commands for OLEs and images
http://svn.apache.org/viewvc?view=revision&revision=1186168
svg: added WaE changes from branch svgreplacement to trunc
http://svn.apache.org/viewvc?view=revision&revision=1222974
svg: corrected missing member initialization
http://svn.apache.org/viewvc?view=revision&revision=1226134
fix for #118525#: Using primitives for chart sub-geometry visualisation
http://svn.apache.org/viewvc?view=revision&revision=1226879
#118898# Adapted ImpGraphic::ImplGetBitmap to correctly convert
metafiles to bitmapEx ...
http://svn.apache.org/viewvc?view=revision&revision=1293316
fix for #118525#: removed no longer used variable maOriginalMapMode, one
more exception eliminated
http://svn.apache.org/viewvc?view=revision&revision=1227097
#16758# Added buffering to the VDev usages of the VclProcessor2D derivates...
http://svn.apache.org/viewvc?view=revision&revision=1229521
#116758# Secured VDev buffer device to Vcl deinit
http://svn.apache.org/viewvc?view=revision&revision=1230574
#116758# added remembering allocated VDevs for VDevBuffer to be able to also
delete these when vcl goes down; it should never happen, but You never know
http://svn.apache.org/viewvc?view=revision&revision=1230927
#118730# Changed SvgClipPathNode to use MaskPrimitive2D for primitive
representation instead of TransparencePrimitive2D
http://svn.apache.org/viewvc?view=revision&revision=1231198
#118822# secured 3D geometry creation (slices) by subdividing the 2D
source polyPolygon early
http://svn.apache.org/viewvc?view=revision&revision=1234749
#118829# enhanced Svg gradient quality, obstacles avoided
http://svn.apache.org/viewvc?view=revision&revision=1235361
#118834# Unified usage of TextBreakupHelper as single tooling class
for i18n text primitive breakup
http://svn.apache.org/viewvc?view=revision&revision=1236110
#118853# added square pixel size limit to conversion of
TransparencePrimitive2D to Metafile action
http://svn.apache.org/viewvc?view=revision&revision=1237656
#118824# coreccted mirroring and boundrect when the graphicmanager
is used for bitmap output
http://svn.apache.org/viewvc?view=revision&revision=1240097
#115092# Corrected VclProcessor2D::RenderPolygonStrokePrimitive2D for
various optimization scenarios
http://svn.apache.org/viewvc?view=revision&revision=1241434
#118783# Corrected errors in ID strings, corrected Svg line/fill export,
corrected polygon close state
http://svn.apache.org/viewvc?view=revision&revision=1232006
#118796# corrected null-pointer usage in SVG text exporter
http://svn.apache.org/viewvc?view=revision&revision=1240262
#118729# Use GraphicStreamUrl and GraphicUrl to allow multi image
import with linked graphics, too
http://svn.apache.org/viewvc?view=revision&revision=1229962
#118898# corrected error in GDIMetaFile::GetBoundRect in handling
MetaFloatTransparentAction
http://svn.apache.org/viewvc?view=revision&revision=1293349
#118855# Corrected handling of possibly created empty clipRegions
after PolyPolygon clipping
http://svn.apache.org/viewvc?view=revision&revision=1237725
#115962# Better (but not yet optimal, see comments in task) handling
of MetaFloatTransparentAction in PDF export
http://svn.apache.org/viewvc?view=revision&revision=1241078
IP clearance: #118466# This patch removes librsvg, libcroco, libgsf, ...
http://svn.apache.org/viewvc?view=revision&revision=1200879
118779# Added svg content streaming in/out to ImpGraphic stream operators
http://svn.apache.org/viewvc?view=revision&revision=1231908
linecap: correctons for WaE and mac drawing
http://svn.apache.org/viewvc?view=revision&revision=1232793
svg: uses current system Dpi for Svg replacement image creation
http://svn.apache.org/viewvc?view=revision&revision=1233948
Patches contributed by Mathias Bauer (and others)
gnumake4 work variously
http://svn.apache.org/viewvc?view=revision&revision=1394326
http://svn.apache.org/viewvc?view=revision&revision=1396797
http://svn.apache.org/viewvc?view=revision&revision=1397315
http://svn.apache.org/viewvc?view=revision&revision=1394326
Remove duplicate header includes.
cws mba34issues01: #i117720#: convert assertion into warning
http://svn.apache.org/viewvc?view=revision&revision=1172352
118485 - Styles for OLEs are not saved. Submitted by Armin Le Grand.
http://svn.apache.org/viewvc?view=revision&revision=1182166
cws mba34issues01: #i117714#: remove assertion
http://svn.apache.org/viewvc?view=revision&revision=1172357
Patch contributed by Jurgen Schmidt
add some additional checks to ensure proper reading operations
http://svn.apache.org/viewvc?view=revision&revision=1209022
mostly prefer our stream / bounds checking work.
Patches contributed by Herbert Duerr
#i118816# add clarifying comment regarding Font::*Color*() methods
http://svn.apache.org/viewvc?view=revision&revision=1233833
extend macro->string handling for empty strings
http://svn.apache.org/viewvc?view=revision&revision=1175801
avoid magic constants for SALCOLOR_NONE
http://svn.apache.org/viewvc?view=revision&revision=1177543
initialize slant properly in ImplFontMetricData constructor (author=iorsh)
http://svn.apache.org/viewvc?view=revision&revision=1177551
#i118675# make check for extension updates more stable
http://svn.apache.org/viewvc?view=revision&revision=1214797
#a118617# remove VBasicEventListener.dll binary
There are no known users depending on its CLSID
http://svn.apache.org/viewvc?view=revision&revision=1203697
Patches contributed by Ariel Constenla-Haile
Fix build breaker on Linux/gcc
http://svn.apache.org/viewvc?view=revision&revision=1221104
Fix crash when trying to instantiate css.graphic.GraphicRasterizer_RSVG
http://svn.apache.org/viewvc?view=revision&revision=1215559
Patches contributed by Oliver-Rainer Wittmann
sw34bf06: #i117962# - method <SwFlyFrm::IsPaint(..)> - consider
instances of <SwFlyDrawObj>
http://svn.apache.org/viewvc?view=revision&revision=1172120
sw34bf06: #i117783# - Writer's implementation of XPagePrintable -
apply print settings to new printing routines
http://svn.apache.org/viewvc?view=revision&revision=1172115
gnumake4 work variously from Hans-Joachim Lankenau
http://svn.apache.org/viewvc?view=revision&revision=1397315
http://svn.apache.org/viewvc?view=revision&revision=1396797
http://svn.apache.org/viewvc?view=revision&revision=1396782
http://svn.apache.org/viewvc?view=revision&revision=1394707
plus some amount of re-splitting of legacy headers.
Patch contributed by Pavel Janik
WaE: Remove unused variables.
http://svn.apache.org/viewvc?view=revision&revision=1230697
Patches contributed by Takashi Ono
mingwport35: i#117795: MinGW port fix for vcl2gnumake
http://svn.apache.org/viewvc?view=revision&revision=1172091
mingwport35: i#117795: MinGW port fix for vcl2gnumake
http://svn.apache.org/viewvc?view=revision&revision=1172091
Patch contributed by Christian Lippka
impress212: #i98044# re enable Text menu for outline and title shapes
http://svn.apache.org/viewvc?view=revision&revision=1167639
Patch contributed by Andre Fischer
118674: Made category B code optional and disabled by default.
http://svn.apache.org/viewvc?view=revision&revision=1215131
118881: Ignore empty paragraphs after bullets.
http://svn.apache.org/viewvc?view=revision&revision=1296205
Patches contributed by Philipp Lohmann
ooo340fixes: #i117780# use rtl allocator
http://svn.apache.org/viewvc?view=revision&revision=1172087
ooo34gsl02: #i117807# fix an off by one error (index actually
inside the pfb section header)
http://svn.apache.org/viewvc?view=revision&revision=1167576
various cleanups, related compilation fixes, warning cleanups, re-working
of obsolete stl template pieces to use boost instead, changed string
classes, re-adapt KDE about data, about dialog, fixing warnings,
and other fixes & improvements.
Disable svg import / render for about/ branding code-paths for now.
Restore full icon theme set.
Remove OS/2 conditionals and sources.
Remove conflicting gtk/full-screen monitors support.
Retain existing svg rasterizer files - temporarily disabled.
Standardize stringificaiton and fixup dllpostfix issues.
Rename SvgGradientHelper::== to equalTo to avoid overloading issues.
Use the flat GdiPlus API for LineCaps calls.
2012-10-09 12:22:23 +01:00
|
|
|
/*
|
|
|
|
* 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 .
|
|
|
|
*/
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2011-01-24 16:34:14 +01:00
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
#include <rtl/crc.h>
|
|
|
|
#include <tools/stream.hxx>
|
2004-01-06 12:27:32 +00:00
|
|
|
#include <tools/poly.hxx>
|
|
|
|
#include <tools/rc.h>
|
2011-01-24 16:34:14 +01:00
|
|
|
#include <vcl/salbtype.hxx>
|
|
|
|
#include <vcl/bmpacc.hxx>
|
|
|
|
#include <vcl/outdev.hxx>
|
2007-06-27 19:09:30 +00:00
|
|
|
#include <vcl/bitmap.hxx>
|
|
|
|
#include <vcl/bitmapex.hxx>
|
|
|
|
#include <vcl/svapp.hxx>
|
|
|
|
#include <vcl/image.hxx>
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2011-01-24 16:34:14 +01:00
|
|
|
#include <impbmp.hxx>
|
|
|
|
#include <salbmp.hxx>
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
Bitmap::Bitmap() :
|
|
|
|
mpImpBmp( NULL )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Bitmap::Bitmap( const ResId& rResId ) :
|
|
|
|
mpImpBmp( NULL )
|
|
|
|
{
|
2004-05-21 13:37:38 +00:00
|
|
|
const BitmapEx aBmpEx( rResId );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2004-05-21 13:37:38 +00:00
|
|
|
if( !aBmpEx.IsEmpty() )
|
|
|
|
*this = aBmpEx.GetBitmap();
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Bitmap::Bitmap( const Bitmap& rBitmap ) :
|
|
|
|
maPrefMapMode ( rBitmap.maPrefMapMode ),
|
|
|
|
maPrefSize ( rBitmap.maPrefSize )
|
|
|
|
{
|
|
|
|
mpImpBmp = rBitmap.mpImpBmp;
|
|
|
|
|
|
|
|
if ( mpImpBmp )
|
|
|
|
mpImpBmp->ImplIncRefCount();
|
|
|
|
}
|
|
|
|
|
2006-08-11 16:44:10 +00:00
|
|
|
Bitmap::Bitmap( SalBitmap* pSalBitmap )
|
|
|
|
{
|
|
|
|
mpImpBmp = new ImpBitmap();
|
|
|
|
mpImpBmp->ImplSetSalBitmap( pSalBitmap );
|
|
|
|
maPrefMapMode = MapMode( MAP_PIXEL );
|
|
|
|
maPrefSize = mpImpBmp->ImplGetSize();
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
Bitmap::Bitmap( const Size& rSizePixel, sal_uInt16 nBitCount, const BitmapPalette* pPal )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
if( rSizePixel.Width() && rSizePixel.Height() )
|
|
|
|
{
|
|
|
|
BitmapPalette aPal;
|
|
|
|
BitmapPalette* pRealPal = NULL;
|
|
|
|
|
|
|
|
if( nBitCount <= 8 )
|
|
|
|
{
|
|
|
|
if( !pPal )
|
|
|
|
{
|
|
|
|
if( 1 == nBitCount )
|
|
|
|
{
|
|
|
|
aPal.SetEntryCount( 2 );
|
|
|
|
aPal[ 0 ] = Color( COL_BLACK );
|
|
|
|
aPal[ 1 ] = Color( COL_WHITE );
|
|
|
|
}
|
|
|
|
else if( ( 4 == nBitCount ) || ( 8 == nBitCount ) )
|
|
|
|
{
|
|
|
|
aPal.SetEntryCount( 1 << nBitCount );
|
|
|
|
aPal[ 0 ] = Color( COL_BLACK );
|
|
|
|
aPal[ 1 ] = Color( COL_BLUE );
|
|
|
|
aPal[ 2 ] = Color( COL_GREEN );
|
|
|
|
aPal[ 3 ] = Color( COL_CYAN );
|
|
|
|
aPal[ 4 ] = Color( COL_RED );
|
|
|
|
aPal[ 5 ] = Color( COL_MAGENTA );
|
|
|
|
aPal[ 6 ] = Color( COL_BROWN );
|
|
|
|
aPal[ 7 ] = Color( COL_GRAY );
|
|
|
|
aPal[ 8 ] = Color( COL_LIGHTGRAY );
|
|
|
|
aPal[ 9 ] = Color( COL_LIGHTBLUE );
|
|
|
|
aPal[ 10 ] = Color( COL_LIGHTGREEN );
|
|
|
|
aPal[ 11 ] = Color( COL_LIGHTCYAN );
|
|
|
|
aPal[ 12 ] = Color( COL_LIGHTRED );
|
|
|
|
aPal[ 13 ] = Color( COL_LIGHTMAGENTA );
|
|
|
|
aPal[ 14 ] = Color( COL_YELLOW );
|
|
|
|
aPal[ 15 ] = Color( COL_WHITE );
|
|
|
|
|
|
|
|
// Dither-Palette erzeugen
|
|
|
|
if( 8 == nBitCount )
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_uInt16 nActCol = 16;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
for( sal_uInt16 nB = 0; nB < 256; nB += 51 )
|
|
|
|
for( sal_uInt16 nG = 0; nG < 256; nG += 51 )
|
|
|
|
for( sal_uInt16 nR = 0; nR < 256; nR += 51 )
|
|
|
|
aPal[ nActCol++ ] = BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
// Standard-Office-Farbe setzen
|
|
|
|
aPal[ nActCol++ ] = BitmapColor( 0, 184, 255 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pRealPal = (BitmapPalette*) pPal;
|
|
|
|
}
|
|
|
|
|
|
|
|
mpImpBmp = new ImpBitmap;
|
|
|
|
mpImpBmp->ImplCreate( rSizePixel, nBitCount, pRealPal ? *pRealPal : aPal );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
mpImpBmp = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bitmap::~Bitmap()
|
|
|
|
{
|
|
|
|
ImplReleaseRef();
|
|
|
|
}
|
|
|
|
|
2008-05-30 09:05:52 +00:00
|
|
|
const BitmapPalette& Bitmap::GetGreyPalette( int nEntries )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
static BitmapPalette aGreyPalette2;
|
|
|
|
static BitmapPalette aGreyPalette4;
|
|
|
|
static BitmapPalette aGreyPalette16;
|
|
|
|
static BitmapPalette aGreyPalette256;
|
|
|
|
|
|
|
|
// create greyscale palette with 2, 4, 16 or 256 entries
|
|
|
|
if( 2 == nEntries || 4 == nEntries || 16 == nEntries || 256 == nEntries )
|
|
|
|
{
|
|
|
|
if( 2 == nEntries )
|
|
|
|
{
|
|
|
|
if( !aGreyPalette2.GetEntryCount() )
|
|
|
|
{
|
|
|
|
aGreyPalette2.SetEntryCount( 2 );
|
|
|
|
aGreyPalette2[ 0 ] = BitmapColor( 0, 0, 0 );
|
|
|
|
aGreyPalette2[ 1 ] = BitmapColor( 255, 255, 255 );
|
|
|
|
}
|
|
|
|
|
|
|
|
return aGreyPalette2;
|
|
|
|
}
|
|
|
|
else if( 4 == nEntries )
|
|
|
|
{
|
|
|
|
if( !aGreyPalette4.GetEntryCount() )
|
|
|
|
{
|
|
|
|
aGreyPalette4.SetEntryCount( 4 );
|
|
|
|
aGreyPalette4[ 0 ] = BitmapColor( 0, 0, 0 );
|
|
|
|
aGreyPalette4[ 1 ] = BitmapColor( 85, 85, 85 );
|
|
|
|
aGreyPalette4[ 2 ] = BitmapColor( 170, 170, 170 );
|
|
|
|
aGreyPalette4[ 3 ] = BitmapColor( 255, 255, 255 );
|
|
|
|
}
|
|
|
|
|
|
|
|
return aGreyPalette4;
|
|
|
|
}
|
|
|
|
else if( 16 == nEntries )
|
|
|
|
{
|
|
|
|
if( !aGreyPalette16.GetEntryCount() )
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_uInt8 cGrey = 0, cGreyInc = 17;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
aGreyPalette16.SetEntryCount( 16 );
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
for( sal_uInt16 i = 0; i < 16; i++, cGrey = sal::static_int_cast<sal_uInt8>(cGrey + cGreyInc) )
|
2000-09-18 16:07:07 +00:00
|
|
|
aGreyPalette16[ i ] = BitmapColor( cGrey, cGrey, cGrey );
|
|
|
|
}
|
|
|
|
|
|
|
|
return aGreyPalette16;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( !aGreyPalette256.GetEntryCount() )
|
|
|
|
{
|
|
|
|
aGreyPalette256.SetEntryCount( 256 );
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
for( sal_uInt16 i = 0; i < 256; i++ )
|
|
|
|
aGreyPalette256[ i ] = BitmapColor( (sal_uInt8) i, (sal_uInt8) i, (sal_uInt8) i );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return aGreyPalette256;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-03-01 19:08:19 +01:00
|
|
|
OSL_FAIL( "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)" );
|
2011-11-03 23:40:04 +00:00
|
|
|
return aGreyPalette2;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-03 23:40:04 +00:00
|
|
|
bool BitmapPalette::IsGreyPalette() const
|
|
|
|
{
|
|
|
|
const int nEntryCount = GetEntryCount();
|
|
|
|
if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping
|
|
|
|
return true;
|
|
|
|
// see above: only certain entry values will result in a valid call to GetGreyPalette
|
|
|
|
if( nEntryCount == 2 || nEntryCount == 4 || nEntryCount == 16 || nEntryCount == 256 )
|
|
|
|
{
|
|
|
|
const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette( nEntryCount );
|
|
|
|
if( rGreyPalette == *this )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool bRet = false;
|
|
|
|
// TODO: is it worth to compare the entries for the general case?
|
|
|
|
if (nEntryCount == 2)
|
|
|
|
{
|
|
|
|
const BitmapColor& rCol0(mpBitmapColor[0]);
|
|
|
|
const BitmapColor& rCol1(mpBitmapColor[1]);
|
|
|
|
bRet = rCol0.GetRed() == rCol0.GetGreen() && rCol0.GetRed() == rCol0.GetBlue() &&
|
|
|
|
rCol1.GetRed() == rCol1.GetGreen() && rCol1.GetRed() == rCol1.GetBlue();
|
|
|
|
}
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
Bitmap& Bitmap::operator=( const Bitmap& rBitmap )
|
|
|
|
{
|
|
|
|
maPrefSize = rBitmap.maPrefSize;
|
|
|
|
maPrefMapMode = rBitmap.maPrefMapMode;
|
|
|
|
|
|
|
|
if ( rBitmap.mpImpBmp )
|
|
|
|
rBitmap.mpImpBmp->ImplIncRefCount();
|
|
|
|
|
|
|
|
ImplReleaseRef();
|
|
|
|
mpImpBmp = rBitmap.mpImpBmp;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::IsEqual( const Bitmap& rBmp ) const
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
return( IsSameInstance( rBmp ) ||
|
|
|
|
( rBmp.GetSizePixel() == GetSizePixel() &&
|
|
|
|
rBmp.GetBitCount() == GetBitCount() &&
|
|
|
|
rBmp.GetChecksum() == GetChecksum() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bitmap::SetEmpty()
|
|
|
|
{
|
|
|
|
maPrefMapMode = MapMode();
|
|
|
|
maPrefSize = Size();
|
|
|
|
|
|
|
|
ImplReleaseRef();
|
|
|
|
mpImpBmp = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Size Bitmap::GetSizePixel() const
|
|
|
|
{
|
|
|
|
return( mpImpBmp ? mpImpBmp->ImplGetSize() : Size() );
|
|
|
|
}
|
|
|
|
|
2006-09-08 07:33:22 +00:00
|
|
|
void Bitmap::SetSourceSizePixel( const Size& rSize)
|
|
|
|
{
|
|
|
|
if( mpImpBmp )
|
|
|
|
mpImpBmp->ImplSetSourceSize( rSize);
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_uInt16 Bitmap::GetBitCount() const
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
return( mpImpBmp ? mpImpBmp->ImplGetBitCount() : 0 );
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::HasGreyPalette() const
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
const sal_uInt16 nBitCount = GetBitCount();
|
2011-11-03 23:40:04 +00:00
|
|
|
sal_Bool bRet = nBitCount == 1 ? sal_True : sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2011-11-03 23:40:04 +00:00
|
|
|
BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
|
2010-03-23 18:54:21 +01:00
|
|
|
|
2011-11-03 23:40:04 +00:00
|
|
|
if( pRAcc )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2011-11-03 23:40:04 +00:00
|
|
|
bRet = pRAcc->HasPalette() && pRAcc->GetPalette().IsGreyPalette();
|
|
|
|
( (Bitmap*) this )->ReleaseAccess( pRAcc );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2011-01-12 15:07:10 +01:00
|
|
|
sal_uLong Bitmap::GetChecksum() const
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2011-01-12 15:07:10 +01:00
|
|
|
sal_uLong nRet = 0UL;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( mpImpBmp )
|
|
|
|
{
|
|
|
|
nRet = mpImpBmp->ImplGetChecksum();
|
|
|
|
|
|
|
|
if( !nRet )
|
|
|
|
{
|
|
|
|
BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
|
|
|
|
|
|
|
|
if( pRAcc && pRAcc->Width() && pRAcc->Height() )
|
|
|
|
{
|
|
|
|
sal_uInt32 nCrc = 0;
|
|
|
|
SVBT32 aBT32;
|
|
|
|
|
|
|
|
pRAcc->ImplZeroInitUnusedBits();
|
|
|
|
|
2006-04-19 12:54:17 +00:00
|
|
|
UInt32ToSVBT32( pRAcc->Width(), aBT32 );
|
2000-09-18 16:07:07 +00:00
|
|
|
nCrc = rtl_crc32( nCrc, aBT32, 4 );
|
|
|
|
|
2006-04-19 12:54:17 +00:00
|
|
|
UInt32ToSVBT32( pRAcc->Height(), aBT32 );
|
2000-09-18 16:07:07 +00:00
|
|
|
nCrc = rtl_crc32( nCrc, aBT32, 4 );
|
|
|
|
|
2006-04-19 12:54:17 +00:00
|
|
|
UInt32ToSVBT32( pRAcc->GetBitCount(), aBT32 );
|
2000-09-18 16:07:07 +00:00
|
|
|
nCrc = rtl_crc32( nCrc, aBT32, 4 );
|
|
|
|
|
2006-04-19 12:54:17 +00:00
|
|
|
UInt32ToSVBT32( pRAcc->GetColorMask().GetRedMask(), aBT32 );
|
2000-09-18 16:07:07 +00:00
|
|
|
nCrc = rtl_crc32( nCrc, aBT32, 4 );
|
|
|
|
|
2006-04-19 12:54:17 +00:00
|
|
|
UInt32ToSVBT32( pRAcc->GetColorMask().GetGreenMask(), aBT32 );
|
2000-09-18 16:07:07 +00:00
|
|
|
nCrc = rtl_crc32( nCrc, aBT32, 4 );
|
|
|
|
|
2006-04-19 12:54:17 +00:00
|
|
|
UInt32ToSVBT32( pRAcc->GetColorMask().GetBlueMask(), aBT32 );
|
2000-09-18 16:07:07 +00:00
|
|
|
nCrc = rtl_crc32( nCrc, aBT32, 4 );
|
|
|
|
|
|
|
|
if( pRAcc->HasPalette() )
|
|
|
|
{
|
|
|
|
nCrc = rtl_crc32( nCrc, pRAcc->GetPalette().ImplGetColorBuffer(),
|
|
|
|
pRAcc->GetPaletteEntryCount() * sizeof( BitmapColor ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
nCrc = rtl_crc32( nCrc, pRAcc->GetBuffer(), pRAcc->GetScanlineSize() * pRAcc->Height() );
|
|
|
|
|
|
|
|
mpImpBmp->ImplSetChecksum( nRet = nCrc );
|
|
|
|
}
|
2007-07-31 15:08:21 +00:00
|
|
|
|
|
|
|
if (pRAcc) ( (Bitmap*) this )->ReleaseAccess( pRAcc );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bitmap::ImplReleaseRef()
|
|
|
|
{
|
|
|
|
if( mpImpBmp )
|
|
|
|
{
|
|
|
|
if( mpImpBmp->ImplGetRefCount() > 1UL )
|
|
|
|
mpImpBmp->ImplDecRefCount();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete mpImpBmp;
|
|
|
|
mpImpBmp = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bitmap::ImplMakeUnique()
|
|
|
|
{
|
|
|
|
if( mpImpBmp && mpImpBmp->ImplGetRefCount() > 1UL )
|
|
|
|
{
|
|
|
|
ImpBitmap* pOldImpBmp = mpImpBmp;
|
|
|
|
|
|
|
|
pOldImpBmp->ImplDecRefCount();
|
|
|
|
|
|
|
|
mpImpBmp = new ImpBitmap;
|
|
|
|
mpImpBmp->ImplCreate( *pOldImpBmp );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bitmap::ImplAssignWithSize( const Bitmap& rBitmap )
|
|
|
|
{
|
|
|
|
const Size aOldSizePix( GetSizePixel() );
|
|
|
|
const Size aNewSizePix( rBitmap.GetSizePixel() );
|
|
|
|
const MapMode aOldMapMode( maPrefMapMode );
|
|
|
|
Size aNewPrefSize;
|
|
|
|
|
|
|
|
if( ( aOldSizePix != aNewSizePix ) && aOldSizePix.Width() && aOldSizePix.Height() )
|
|
|
|
{
|
|
|
|
aNewPrefSize.Width() = FRound( maPrefSize.Width() * aNewSizePix.Width() / aOldSizePix.Width() );
|
|
|
|
aNewPrefSize.Height() = FRound( maPrefSize.Height() * aNewSizePix.Height() / aOldSizePix.Height() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
aNewPrefSize = maPrefSize;
|
|
|
|
|
|
|
|
*this = rBitmap;
|
|
|
|
|
|
|
|
maPrefSize = aNewPrefSize;
|
|
|
|
maPrefMapMode = aOldMapMode;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImpBitmap* Bitmap::ImplGetImpBitmap() const
|
|
|
|
{
|
|
|
|
return mpImpBmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bitmap::ImplSetImpBitmap( ImpBitmap* pImpBmp )
|
|
|
|
{
|
|
|
|
if( pImpBmp != mpImpBmp )
|
|
|
|
{
|
|
|
|
ImplReleaseRef();
|
|
|
|
mpImpBmp = pImpBmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BitmapReadAccess* Bitmap::AcquireReadAccess()
|
|
|
|
{
|
|
|
|
BitmapReadAccess* pReadAccess = new BitmapReadAccess( *this );
|
|
|
|
|
|
|
|
if( !*pReadAccess )
|
|
|
|
{
|
|
|
|
delete pReadAccess;
|
|
|
|
pReadAccess = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pReadAccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
BitmapWriteAccess* Bitmap::AcquireWriteAccess()
|
|
|
|
{
|
|
|
|
BitmapWriteAccess* pWriteAccess = new BitmapWriteAccess( *this );
|
|
|
|
|
|
|
|
if( !*pWriteAccess )
|
|
|
|
{
|
|
|
|
delete pWriteAccess;
|
|
|
|
pWriteAccess = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pWriteAccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bitmap::ReleaseAccess( BitmapReadAccess* pBitmapAccess )
|
|
|
|
{
|
|
|
|
delete pBitmapAccess;
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::Erase( const Color& rFillColor )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2008-10-29 09:25:50 +00:00
|
|
|
if( !(*this) )
|
2010-09-29 15:46:40 +08:00
|
|
|
return sal_True;
|
2008-10-29 09:25:50 +00:00
|
|
|
|
2000-09-18 16:07:07 +00:00
|
|
|
BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( pWriteAcc )
|
|
|
|
{
|
2011-01-12 15:07:10 +01:00
|
|
|
const sal_uLong nFormat = pWriteAcc->GetScanlineFormat();
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_uInt8 cIndex = 0;
|
|
|
|
sal_Bool bFast = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
switch( nFormat )
|
|
|
|
{
|
|
|
|
case( BMP_FORMAT_1BIT_MSB_PAL ):
|
|
|
|
case( BMP_FORMAT_1BIT_LSB_PAL ):
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
|
2000-09-18 16:07:07 +00:00
|
|
|
cIndex = ( cIndex ? 255 : 0 );
|
2010-09-29 15:46:40 +08:00
|
|
|
bFast = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case( BMP_FORMAT_4BIT_MSN_PAL ):
|
|
|
|
case( BMP_FORMAT_4BIT_LSN_PAL ):
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
|
2000-09-18 16:07:07 +00:00
|
|
|
cIndex = cIndex | ( cIndex << 4 );
|
2010-09-29 15:46:40 +08:00
|
|
|
bFast = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case( BMP_FORMAT_8BIT_PAL ):
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
|
|
|
|
bFast = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case( BMP_FORMAT_24BIT_TC_BGR ):
|
|
|
|
case( BMP_FORMAT_24BIT_TC_RGB ):
|
|
|
|
{
|
|
|
|
if( ( rFillColor.GetRed() == rFillColor.GetGreen() ) &&
|
|
|
|
( rFillColor.GetRed() == rFillColor.GetBlue() ) )
|
|
|
|
{
|
|
|
|
cIndex = rFillColor.GetRed();
|
2010-09-29 15:46:40 +08:00
|
|
|
bFast = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
else
|
2010-09-29 15:46:40 +08:00
|
|
|
bFast = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2010-09-29 15:46:40 +08:00
|
|
|
bFast = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( bFast )
|
|
|
|
{
|
2011-01-12 15:07:10 +01:00
|
|
|
const sal_uLong nBufSize = pWriteAcc->GetScanlineSize() * pWriteAcc->Height();
|
2004-01-06 12:27:32 +00:00
|
|
|
memset( pWriteAcc->GetBuffer(), cIndex, nBufSize );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Point aTmpPoint;
|
|
|
|
const Rectangle aRect( aTmpPoint, Size( pWriteAcc->Width(), pWriteAcc->Height() ) );
|
|
|
|
pWriteAcc->SetFillColor( rFillColor );
|
|
|
|
pWriteAcc->FillRect( aRect );
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseAccess( pWriteAcc );
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::Invert()
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
BitmapWriteAccess* pAcc = AcquireWriteAccess();
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( pAcc )
|
|
|
|
{
|
|
|
|
if( pAcc->HasPalette() )
|
|
|
|
{
|
|
|
|
BitmapPalette aBmpPal( pAcc->GetPalette() );
|
2010-09-29 15:46:40 +08:00
|
|
|
const sal_uInt16 nCount = aBmpPal.GetEntryCount();
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
for( sal_uInt16 i = 0; i < nCount; i++ )
|
2000-09-18 16:07:07 +00:00
|
|
|
aBmpPal[ i ].Invert();
|
|
|
|
|
|
|
|
pAcc->SetPalette( aBmpPal );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const long nWidth = pAcc->Width();
|
|
|
|
const long nHeight = pAcc->Height();
|
|
|
|
|
|
|
|
for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ )
|
|
|
|
pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nX ).Invert() );
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseAccess( pAcc );
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2011-01-12 15:07:10 +01:00
|
|
|
sal_Bool Bitmap::Mirror( sal_uLong nMirrorFlags )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bHorz = ( ( nMirrorFlags & BMP_MIRROR_HORZ ) == BMP_MIRROR_HORZ );
|
|
|
|
sal_Bool bVert = ( ( nMirrorFlags & BMP_MIRROR_VERT ) == BMP_MIRROR_VERT );
|
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( bHorz && !bVert )
|
|
|
|
{
|
|
|
|
BitmapWriteAccess* pAcc = AcquireWriteAccess();
|
|
|
|
|
|
|
|
if( pAcc )
|
|
|
|
{
|
|
|
|
const long nWidth = pAcc->Width();
|
|
|
|
const long nHeight = pAcc->Height();
|
|
|
|
const long nWidth1 = nWidth - 1L;
|
|
|
|
const long nWidth_2 = nWidth >> 1L;
|
|
|
|
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
for( long nX = 0L, nOther = nWidth1; nX < nWidth_2; nX++, nOther-- )
|
|
|
|
{
|
|
|
|
const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
|
|
|
|
|
|
|
|
pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nOther ) );
|
|
|
|
pAcc->SetPixel( nY, nOther, aTemp );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseAccess( pAcc );
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( bVert && !bHorz )
|
|
|
|
{
|
|
|
|
BitmapWriteAccess* pAcc = AcquireWriteAccess();
|
|
|
|
|
|
|
|
if( pAcc )
|
|
|
|
{
|
|
|
|
const long nScanSize = pAcc->GetScanlineSize();
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_uInt8* pBuffer = new sal_uInt8[ nScanSize ];
|
2000-09-18 16:07:07 +00:00
|
|
|
const long nHeight = pAcc->Height();
|
|
|
|
const long nHeight1 = nHeight - 1L;
|
|
|
|
const long nHeight_2 = nHeight >> 1L;
|
|
|
|
|
|
|
|
for( long nY = 0L, nOther = nHeight1; nY < nHeight_2; nY++, nOther-- )
|
|
|
|
{
|
2004-01-06 12:27:32 +00:00
|
|
|
memcpy( pBuffer, pAcc->GetScanline( nY ), nScanSize );
|
|
|
|
memcpy( pAcc->GetScanline( nY ), pAcc->GetScanline( nOther ), nScanSize );
|
|
|
|
memcpy( pAcc->GetScanline( nOther ), pBuffer, nScanSize );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
delete[] pBuffer;
|
|
|
|
ReleaseAccess( pAcc );
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( bHorz && bVert )
|
|
|
|
{
|
|
|
|
BitmapWriteAccess* pAcc = AcquireWriteAccess();
|
|
|
|
|
|
|
|
if( pAcc )
|
|
|
|
{
|
|
|
|
const long nWidth = pAcc->Width();
|
|
|
|
const long nWidth1 = nWidth - 1L;
|
|
|
|
const long nHeight = pAcc->Height();
|
|
|
|
long nHeight_2 = nHeight >> 1;
|
|
|
|
|
|
|
|
for( long nY = 0L, nOtherY = nHeight - 1L; nY < nHeight_2; nY++, nOtherY-- )
|
|
|
|
{
|
|
|
|
for( long nX = 0L, nOtherX = nWidth1; nX < nWidth; nX++, nOtherX-- )
|
|
|
|
{
|
|
|
|
const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
|
|
|
|
|
|
|
|
pAcc->SetPixel( nY, nX, pAcc->GetPixel( nOtherY, nOtherX ) );
|
|
|
|
pAcc->SetPixel( nOtherY, nOtherX, aTemp );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ggf. noch mittlere Zeile horizontal spiegeln
|
|
|
|
if( nHeight & 1 )
|
|
|
|
{
|
|
|
|
for( long nX = 0L, nOtherX = nWidth1, nWidth_2 = nWidth >> 1; nX < nWidth_2; nX++, nOtherX-- )
|
|
|
|
{
|
|
|
|
const BitmapColor aTemp( pAcc->GetPixel( nHeight_2, nX ) );
|
|
|
|
pAcc->SetPixel( nHeight_2, nX, pAcc->GetPixel( nHeight_2, nOtherX ) );
|
|
|
|
pAcc->SetPixel( nHeight_2, nOtherX, aTemp );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseAccess( pAcc );
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::Rotate( long nAngle10, const Color& rFillColor )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
nAngle10 %= 3600L;
|
|
|
|
nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
|
|
|
|
|
|
|
|
if( !nAngle10 )
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
else if( 1800L == nAngle10 )
|
|
|
|
bRet = Mirror( BMP_MIRROR_HORZ | BMP_MIRROR_VERT );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BitmapReadAccess* pReadAcc = AcquireReadAccess();
|
|
|
|
Bitmap aRotatedBmp;
|
|
|
|
|
|
|
|
if( pReadAcc )
|
|
|
|
{
|
|
|
|
const Size aSizePix( GetSizePixel() );
|
|
|
|
|
|
|
|
if( ( 900L == nAngle10 ) || ( 2700L == nAngle10 ) )
|
|
|
|
{
|
|
|
|
const Size aNewSizePix( aSizePix.Height(), aSizePix.Width() );
|
|
|
|
Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
|
|
|
|
BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
|
|
|
|
|
|
|
|
if( pWriteAcc )
|
|
|
|
{
|
|
|
|
const long nWidth = aSizePix.Width();
|
|
|
|
const long nWidth1 = nWidth - 1L;
|
|
|
|
const long nHeight = aSizePix.Height();
|
|
|
|
const long nHeight1 = nHeight - 1L;
|
|
|
|
const long nNewWidth = aNewSizePix.Width();
|
|
|
|
const long nNewHeight = aNewSizePix.Height();
|
|
|
|
|
|
|
|
if( 900L == nAngle10 )
|
|
|
|
{
|
|
|
|
for( long nY = 0L, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX-- )
|
|
|
|
for( long nX = 0L, nOtherY = 0L; nX < nNewWidth; nX++ )
|
|
|
|
pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY++, nOtherX ) );
|
|
|
|
}
|
|
|
|
else if( 2700L == nAngle10 )
|
|
|
|
{
|
|
|
|
for( long nY = 0L, nOtherX = 0L; nY < nNewHeight; nY++, nOtherX++ )
|
|
|
|
for( long nX = 0L, nOtherY = nHeight1; nX < nNewWidth; nX++ )
|
|
|
|
pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY--, nOtherX ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
aNewBmp.ReleaseAccess( pWriteAcc );
|
|
|
|
}
|
|
|
|
|
|
|
|
aRotatedBmp = aNewBmp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Point aTmpPoint;
|
|
|
|
Rectangle aTmpRectangle( aTmpPoint, aSizePix );
|
|
|
|
Polygon aPoly( aTmpRectangle );
|
2010-09-29 15:46:40 +08:00
|
|
|
aPoly.Rotate( aTmpPoint, (sal_uInt16) nAngle10 );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
Rectangle aNewBound( aPoly.GetBoundRect() );
|
|
|
|
const Size aNewSizePix( aNewBound.GetSize() );
|
|
|
|
Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
|
|
|
|
BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
|
|
|
|
|
|
|
|
if( pWriteAcc )
|
|
|
|
{
|
|
|
|
const BitmapColor aFillColor( pWriteAcc->GetBestMatchingColor( rFillColor ) );
|
|
|
|
const double fCosAngle = cos( nAngle10 * F_PI1800 );
|
|
|
|
const double fSinAngle = sin( nAngle10 * F_PI1800 );
|
|
|
|
const double fXMin = aNewBound.Left();
|
|
|
|
const double fYMin = aNewBound.Top();
|
|
|
|
const long nWidth = aSizePix.Width();
|
|
|
|
const long nHeight = aSizePix.Height();
|
|
|
|
const long nNewWidth = aNewSizePix.Width();
|
|
|
|
const long nNewHeight = aNewSizePix.Height();
|
|
|
|
long nX;
|
|
|
|
long nY;
|
|
|
|
long nRotX;
|
|
|
|
long nRotY;
|
|
|
|
long nSinY;
|
|
|
|
long nCosY;
|
|
|
|
long* pCosX = new long[ nNewWidth ];
|
|
|
|
long* pSinX = new long[ nNewWidth ];
|
|
|
|
long* pCosY = new long[ nNewHeight ];
|
|
|
|
long* pSinY = new long[ nNewHeight ];
|
|
|
|
|
|
|
|
for ( nX = 0; nX < nNewWidth; nX++ )
|
|
|
|
{
|
|
|
|
const double fTmp = ( fXMin + nX ) * 64.;
|
|
|
|
|
|
|
|
pCosX[ nX ] = FRound( fCosAngle * fTmp );
|
|
|
|
pSinX[ nX ] = FRound( fSinAngle * fTmp );
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( nY = 0; nY < nNewHeight; nY++ )
|
|
|
|
{
|
|
|
|
const double fTmp = ( fYMin + nY ) * 64.;
|
|
|
|
|
|
|
|
pCosY[ nY ] = FRound( fCosAngle * fTmp );
|
|
|
|
pSinY[ nY ] = FRound( fSinAngle * fTmp );
|
|
|
|
}
|
|
|
|
|
|
|
|
for( nY = 0L; nY < nNewHeight; nY++ )
|
|
|
|
{
|
|
|
|
nSinY = pSinY[ nY ];
|
|
|
|
nCosY = pCosY[ nY ];
|
|
|
|
|
|
|
|
for( nX = 0L; nX < nNewWidth; nX++ )
|
|
|
|
{
|
|
|
|
nRotX = ( pCosX[ nX ] - nSinY ) >> 6;
|
|
|
|
nRotY = ( pSinX[ nX ] + nCosY ) >> 6;
|
|
|
|
|
|
|
|
if ( ( nRotX > -1L ) && ( nRotX < nWidth ) && ( nRotY > -1L ) && ( nRotY < nHeight ) )
|
|
|
|
pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nRotY, nRotX ) );
|
|
|
|
else
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aFillColor );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete[] pSinX;
|
|
|
|
delete[] pCosX;
|
|
|
|
delete[] pSinY;
|
|
|
|
delete[] pCosY;
|
|
|
|
|
|
|
|
aNewBmp.ReleaseAccess( pWriteAcc );
|
|
|
|
}
|
|
|
|
|
|
|
|
aRotatedBmp = aNewBmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseAccess( pReadAcc );
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
if( ( bRet = !!aRotatedBmp ) == sal_True )
|
2000-09-18 16:07:07 +00:00
|
|
|
ImplAssignWithSize( aRotatedBmp );
|
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
};
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::Crop( const Rectangle& rRectPixel )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
const Size aSizePix( GetSizePixel() );
|
|
|
|
Rectangle aRect( rRectPixel );
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
aRect.Intersection( Rectangle( Point(), aSizePix ) );
|
|
|
|
|
|
|
|
if( !aRect.IsEmpty() )
|
|
|
|
{
|
|
|
|
BitmapReadAccess* pReadAcc = AcquireReadAccess();
|
|
|
|
|
|
|
|
if( pReadAcc )
|
|
|
|
{
|
|
|
|
Point aTmpPoint;
|
|
|
|
const Rectangle aNewRect( aTmpPoint, aRect.GetSize() );
|
|
|
|
Bitmap aNewBmp( aNewRect.GetSize(), GetBitCount(), &pReadAcc->GetPalette() );
|
|
|
|
BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
|
|
|
|
|
|
|
|
if( pWriteAcc )
|
|
|
|
{
|
|
|
|
const long nOldX = aRect.Left();
|
|
|
|
const long nOldY = aRect.Top();
|
|
|
|
const long nNewWidth = aNewRect.GetWidth();
|
|
|
|
const long nNewHeight = aNewRect.GetHeight();
|
|
|
|
|
|
|
|
for( long nY = 0, nY2 = nOldY; nY < nNewHeight; nY++, nY2++ )
|
|
|
|
for( long nX = 0, nX2 = nOldX; nX < nNewWidth; nX++, nX2++ )
|
|
|
|
pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY2, nX2 ) );
|
|
|
|
|
|
|
|
aNewBmp.ReleaseAccess( pWriteAcc );
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseAccess( pReadAcc );
|
|
|
|
|
|
|
|
if( bRet )
|
|
|
|
ImplAssignWithSize( aNewBmp );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
};
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::CopyPixel( const Rectangle& rRectDst,
|
2000-09-18 16:07:07 +00:00
|
|
|
const Rectangle& rRectSrc, const Bitmap* pBmpSrc )
|
|
|
|
{
|
|
|
|
const Size aSizePix( GetSizePixel() );
|
|
|
|
Rectangle aRectDst( rRectDst );
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
aRectDst.Intersection( Rectangle( Point(), aSizePix ) );
|
|
|
|
|
|
|
|
if( !aRectDst.IsEmpty() )
|
|
|
|
{
|
|
|
|
if( pBmpSrc && ( *pBmpSrc != *this ) )
|
|
|
|
{
|
|
|
|
Bitmap* pSrc = (Bitmap*) pBmpSrc;
|
|
|
|
const Size aCopySizePix( pSrc->GetSizePixel() );
|
|
|
|
Rectangle aRectSrc( rRectSrc );
|
2010-09-29 15:46:40 +08:00
|
|
|
const sal_uInt16 nSrcBitCount = pBmpSrc->GetBitCount();
|
|
|
|
const sal_uInt16 nDstBitCount = GetBitCount();
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( nSrcBitCount > nDstBitCount )
|
|
|
|
{
|
|
|
|
long nNextIndex = 0L;
|
|
|
|
|
|
|
|
if( ( nSrcBitCount == 24 ) && ( nDstBitCount < 24 ) )
|
|
|
|
Convert( BMP_CONVERSION_24BIT );
|
|
|
|
else if( ( nSrcBitCount == 8 ) && ( nDstBitCount < 8 ) )
|
|
|
|
{
|
|
|
|
Convert( BMP_CONVERSION_8BIT_COLORS );
|
|
|
|
nNextIndex = 16;
|
|
|
|
}
|
|
|
|
else if( ( nSrcBitCount == 4 ) && ( nDstBitCount < 4 ) )
|
|
|
|
{
|
|
|
|
Convert( BMP_CONVERSION_4BIT_COLORS );
|
|
|
|
nNextIndex = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( nNextIndex )
|
|
|
|
{
|
|
|
|
BitmapReadAccess* pSrcAcc = pSrc->AcquireReadAccess();
|
|
|
|
BitmapWriteAccess* pDstAcc = AcquireWriteAccess();
|
|
|
|
|
|
|
|
if( pSrcAcc && pDstAcc )
|
|
|
|
{
|
|
|
|
const long nSrcCount = pDstAcc->GetPaletteEntryCount();
|
|
|
|
const long nDstCount = 1 << nDstBitCount;
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bFound;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
for( long i = 0L; ( i < nSrcCount ) && ( nNextIndex < nSrcCount ); i++ )
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
const BitmapColor& rSrcCol = pSrcAcc->GetPaletteColor( (sal_uInt16) i );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
bFound = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
for( long j = 0L; j < nDstCount; j++ )
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
if( rSrcCol == pDstAcc->GetPaletteColor( (sal_uInt16) j ) )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
bFound = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !bFound )
|
2010-09-29 15:46:40 +08:00
|
|
|
pDstAcc->SetPaletteColor( (sal_uInt16) nNextIndex++, rSrcCol );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pSrcAcc )
|
|
|
|
pSrc->ReleaseAccess( pSrcAcc );
|
|
|
|
|
|
|
|
if( pDstAcc )
|
|
|
|
ReleaseAccess( pDstAcc );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
aRectSrc.Intersection( Rectangle( Point(), aCopySizePix ) );
|
|
|
|
|
|
|
|
if( !aRectSrc.IsEmpty() )
|
|
|
|
{
|
|
|
|
BitmapReadAccess* pReadAcc = pSrc->AcquireReadAccess();
|
|
|
|
|
|
|
|
if( pReadAcc )
|
|
|
|
{
|
|
|
|
BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
|
|
|
|
|
|
|
|
if( pWriteAcc )
|
|
|
|
{
|
|
|
|
const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
|
|
|
|
const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
|
|
|
|
const long nSrcEndX = aRectSrc.Left() + nWidth;
|
|
|
|
const long nSrcEndY = aRectSrc.Top() + nHeight;
|
|
|
|
long nDstY = aRectDst.Top();
|
|
|
|
|
|
|
|
if( pReadAcc->HasPalette() && pWriteAcc->HasPalette() )
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
const sal_uInt16 nCount = pReadAcc->GetPaletteEntryCount();
|
|
|
|
sal_uInt8* pMap = new sal_uInt8[ nCount ];
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
// Index-Map fuer Farbtabelle
|
|
|
|
// aufbauen, da das Bild ja (relativ) farbgenau
|
|
|
|
// kopiert werden soll
|
2010-09-29 15:46:40 +08:00
|
|
|
for( sal_uInt16 i = 0; i < nCount; i++ )
|
|
|
|
pMap[ i ] = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( pReadAcc->GetPaletteColor( i ) );
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
|
|
|
|
for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
|
|
|
|
pWriteAcc->SetPixel( nDstY, nDstX, pMap[ pReadAcc->GetPixel( nSrcY, nSrcX ).GetIndex() ] );
|
|
|
|
|
|
|
|
delete[] pMap;
|
|
|
|
}
|
|
|
|
else if( pReadAcc->HasPalette() )
|
|
|
|
{
|
2004-05-21 13:37:38 +00:00
|
|
|
for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
|
|
|
|
for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
|
|
|
|
pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nSrcY, nSrcX ) ) );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
|
|
|
|
for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
|
|
|
|
pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPixel( nSrcY, nSrcX ) );
|
|
|
|
|
|
|
|
ReleaseAccess( pWriteAcc );
|
|
|
|
bRet = ( nWidth > 0L ) && ( nHeight > 0L );
|
|
|
|
}
|
|
|
|
|
|
|
|
pSrc->ReleaseAccess( pReadAcc );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Rectangle aRectSrc( rRectSrc );
|
|
|
|
|
|
|
|
aRectSrc.Intersection( Rectangle( Point(), aSizePix ) );
|
|
|
|
|
|
|
|
if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
|
|
|
|
{
|
|
|
|
BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
|
|
|
|
|
|
|
|
if( pWriteAcc )
|
|
|
|
{
|
|
|
|
const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
|
|
|
|
const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
|
|
|
|
const long nSrcX = aRectSrc.Left();
|
|
|
|
const long nSrcY = aRectSrc.Top();
|
|
|
|
const long nSrcEndX1 = nSrcX + nWidth - 1L;
|
|
|
|
const long nSrcEndY1 = nSrcY + nHeight - 1L;
|
|
|
|
const long nDstX = aRectDst.Left();
|
|
|
|
const long nDstY = aRectDst.Top();
|
|
|
|
const long nDstEndX1 = nDstX + nWidth - 1L;
|
|
|
|
const long nDstEndY1 = nDstY + nHeight - 1L;
|
|
|
|
|
|
|
|
if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
|
|
|
|
{
|
|
|
|
for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
|
|
|
|
for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
|
|
|
|
pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
|
|
|
|
}
|
|
|
|
else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
|
|
|
|
{
|
|
|
|
for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
|
|
|
|
for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
|
|
|
|
pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
|
|
|
|
}
|
|
|
|
else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
|
|
|
|
{
|
|
|
|
for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
|
|
|
|
for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
|
|
|
|
pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
|
|
|
|
for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
|
|
|
|
pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseAccess( pWriteAcc );
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2011-01-12 15:07:10 +01:00
|
|
|
sal_Bool Bitmap::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( nDX || nDY )
|
|
|
|
{
|
|
|
|
const Size aSizePixel( GetSizePixel() );
|
|
|
|
const long nWidth = aSizePixel.Width();
|
|
|
|
const long nHeight = aSizePixel.Height();
|
|
|
|
const Size aNewSize( nWidth + nDX, nHeight + nDY );
|
|
|
|
BitmapReadAccess* pReadAcc = AcquireReadAccess();
|
|
|
|
|
|
|
|
if( pReadAcc )
|
|
|
|
{
|
|
|
|
BitmapPalette aBmpPal( pReadAcc->GetPalette() );
|
|
|
|
Bitmap aNewBmp( aNewSize, GetBitCount(), &aBmpPal );
|
|
|
|
BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
|
|
|
|
|
|
|
|
if( pWriteAcc )
|
|
|
|
{
|
|
|
|
BitmapColor aColor;
|
|
|
|
const long nNewX = nWidth;
|
|
|
|
const long nNewY = nHeight;
|
|
|
|
const long nNewWidth = pWriteAcc->Width();
|
|
|
|
const long nNewHeight = pWriteAcc->Height();
|
|
|
|
long nX;
|
|
|
|
long nY;
|
|
|
|
|
|
|
|
if( pInitColor )
|
|
|
|
aColor = pWriteAcc->GetBestMatchingColor( *pInitColor );
|
|
|
|
|
|
|
|
for( nY = 0L; nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
pWriteAcc->CopyScanline( nY, *pReadAcc );
|
|
|
|
|
|
|
|
if( pInitColor && nDX )
|
|
|
|
for( nX = nNewX; nX < nNewWidth; nX++ )
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aColor );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pInitColor && nDY )
|
|
|
|
for( nY = nNewY; nY < nNewHeight; nY++ )
|
2002-04-24 13:14:26 +00:00
|
|
|
for( nX = 0; nX < nNewWidth; nX++ )
|
2000-09-18 16:07:07 +00:00
|
|
|
pWriteAcc->SetPixel( nY, nX, aColor );
|
|
|
|
|
|
|
|
aNewBmp.ReleaseAccess( pWriteAcc );
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseAccess( pReadAcc );
|
|
|
|
|
|
|
|
if( bRet )
|
|
|
|
ImplAssignWithSize( aNewBmp );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2011-01-12 15:07:10 +01:00
|
|
|
Bitmap Bitmap::CreateMask( const Color& rTransColor, sal_uLong nTol ) const
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
Bitmap aNewBmp( GetSizePixel(), 1 );
|
|
|
|
BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( pWriteAcc )
|
|
|
|
{
|
|
|
|
BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
|
|
|
|
|
|
|
|
if( pReadAcc )
|
|
|
|
{
|
|
|
|
const long nWidth = pReadAcc->Width();
|
|
|
|
const long nHeight = pReadAcc->Height();
|
|
|
|
const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
|
|
|
|
const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
|
|
|
|
|
|
|
|
if( !nTol )
|
|
|
|
{
|
|
|
|
const BitmapColor aTest( pReadAcc->GetBestMatchingColor( rTransColor ) );
|
2011-09-29 17:57:49 +02:00
|
|
|
long nX, nY;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ||
|
|
|
|
pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_LSN_PAL )
|
|
|
|
{
|
|
|
|
// optimized for 4Bit-MSN/LSN source palette
|
2010-09-29 15:46:40 +08:00
|
|
|
const sal_uInt8 cTest = aTest.GetIndex();
|
2000-09-18 16:07:07 +00:00
|
|
|
const long nShiftInit = ( ( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ) ? 4 : 0 );
|
|
|
|
|
|
|
|
if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
|
|
|
|
aWhite.GetIndex() == 1 )
|
|
|
|
{
|
|
|
|
// optimized for 1Bit-MSB destination palette
|
|
|
|
for( nY = 0L; nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
Scanline pSrc = pReadAcc->GetScanline( nY );
|
|
|
|
Scanline pDst = pWriteAcc->GetScanline( nY );
|
2011-09-29 17:57:49 +02:00
|
|
|
long nShift = 0;
|
2000-09-18 16:07:07 +00:00
|
|
|
for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
|
|
|
|
{
|
|
|
|
if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
|
|
|
|
pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
|
|
|
|
else
|
|
|
|
pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( nY = 0L; nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
Scanline pSrc = pReadAcc->GetScanline( nY );
|
2011-09-29 17:57:49 +02:00
|
|
|
long nShift = 0;
|
2000-09-18 16:07:07 +00:00
|
|
|
for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
|
|
|
|
{
|
|
|
|
if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
else
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
|
|
|
|
{
|
|
|
|
// optimized for 8Bit source palette
|
2010-09-29 15:46:40 +08:00
|
|
|
const sal_uInt8 cTest = aTest.GetIndex();
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
|
|
|
|
aWhite.GetIndex() == 1 )
|
|
|
|
{
|
|
|
|
// optimized for 1Bit-MSB destination palette
|
|
|
|
for( nY = 0L; nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
Scanline pSrc = pReadAcc->GetScanline( nY );
|
|
|
|
Scanline pDst = pWriteAcc->GetScanline( nY );
|
|
|
|
for( nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
if( cTest == pSrc[ nX ] )
|
|
|
|
pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
|
|
|
|
else
|
|
|
|
pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( nY = 0L; nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
Scanline pSrc = pReadAcc->GetScanline( nY );
|
|
|
|
for( nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
if( cTest == pSrc[ nX ] )
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
else
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// not optimized
|
|
|
|
for( nY = 0L; nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
for( nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
if( aTest == pReadAcc->GetPixel( nY, nX ) )
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
else
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BitmapColor aCol;
|
|
|
|
long nR, nG, nB;
|
|
|
|
const long nMinR = MinMax( (long) rTransColor.GetRed() - nTol, 0, 255 );
|
|
|
|
const long nMaxR = MinMax( (long) rTransColor.GetRed() + nTol, 0, 255 );
|
|
|
|
const long nMinG = MinMax( (long) rTransColor.GetGreen() - nTol, 0, 255 );
|
|
|
|
const long nMaxG = MinMax( (long) rTransColor.GetGreen() + nTol, 0, 255 );
|
|
|
|
const long nMinB = MinMax( (long) rTransColor.GetBlue() - nTol, 0, 255 );
|
|
|
|
const long nMaxB = MinMax( (long) rTransColor.GetBlue() + nTol, 0, 255 );
|
|
|
|
|
|
|
|
if( pReadAcc->HasPalette() )
|
|
|
|
{
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
aCol = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) );
|
|
|
|
nR = aCol.GetRed();
|
|
|
|
nG = aCol.GetGreen();
|
|
|
|
nB = aCol.GetBlue();
|
|
|
|
|
|
|
|
if( nMinR <= nR && nMaxR >= nR &&
|
|
|
|
nMinG <= nG && nMaxG >= nG &&
|
|
|
|
nMinB <= nB && nMaxB >= nB )
|
|
|
|
{
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
aCol = pReadAcc->GetPixel( nY, nX );
|
|
|
|
nR = aCol.GetRed();
|
|
|
|
nG = aCol.GetGreen();
|
|
|
|
nB = aCol.GetBlue();
|
|
|
|
|
|
|
|
if( nMinR <= nR && nMaxR >= nR &&
|
|
|
|
nMinG <= nG && nMaxG >= nG &&
|
|
|
|
nMinB <= nB && nMaxB >= nB )
|
|
|
|
{
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pWriteAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
( (Bitmap*) this )->ReleaseAccess( pReadAcc );
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
aNewBmp.ReleaseAccess( pWriteAcc );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( bRet )
|
|
|
|
{
|
|
|
|
aNewBmp.maPrefSize = maPrefSize;
|
|
|
|
aNewBmp.maPrefMapMode = maPrefMapMode;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
aNewBmp = Bitmap();
|
|
|
|
|
|
|
|
return aNewBmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
Region Bitmap::CreateRegion( const Color& rColor, const Rectangle& rRect ) const
|
|
|
|
{
|
|
|
|
Region aRegion;
|
|
|
|
Rectangle aRect( rRect );
|
|
|
|
BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
|
|
|
|
|
|
|
|
aRect.Intersection( Rectangle( Point(), GetSizePixel() ) );
|
|
|
|
aRect.Justify();
|
|
|
|
|
|
|
|
if( pReadAcc )
|
|
|
|
{
|
|
|
|
Rectangle aSubRect;
|
|
|
|
const long nLeft = aRect.Left();
|
|
|
|
const long nTop = aRect.Top();
|
|
|
|
const long nRight = aRect.Right();
|
|
|
|
const long nBottom = aRect.Bottom();
|
|
|
|
const BitmapColor aMatch( pReadAcc->GetBestMatchingColor( rColor ) );
|
|
|
|
|
|
|
|
aRegion.ImplBeginAddRect();
|
|
|
|
|
|
|
|
for( long nY = nTop; nY <= nBottom; nY++ )
|
|
|
|
{
|
|
|
|
aSubRect.Top() = aSubRect.Bottom() = nY;
|
|
|
|
|
|
|
|
for( long nX = nLeft; nX <= nRight; )
|
|
|
|
{
|
|
|
|
while( ( nX <= nRight ) && ( aMatch != pReadAcc->GetPixel( nY, nX ) ) )
|
|
|
|
nX++;
|
|
|
|
|
|
|
|
if( nX <= nRight )
|
|
|
|
{
|
|
|
|
aSubRect.Left() = nX;
|
|
|
|
|
|
|
|
while( ( nX <= nRight ) && ( aMatch == pReadAcc->GetPixel( nY, nX ) ) )
|
|
|
|
nX++;
|
|
|
|
|
|
|
|
aSubRect.Right() = nX - 1L;
|
|
|
|
aRegion.ImplAddRect( aSubRect );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
aRegion.ImplEndAddRect();
|
|
|
|
( (Bitmap*) this )->ReleaseAccess( pReadAcc );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
aRegion = aRect;
|
|
|
|
|
|
|
|
return aRegion;
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::Replace( const Bitmap& rMask, const Color& rReplaceColor )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
|
|
|
|
BitmapWriteAccess* pAcc = AcquireWriteAccess();
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( pMaskAcc && pAcc )
|
|
|
|
{
|
|
|
|
const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
|
|
|
|
const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
|
|
|
|
const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
|
|
|
|
BitmapColor aReplace;
|
|
|
|
|
|
|
|
if( pAcc->HasPalette() )
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
const sal_uInt16 nActColors = pAcc->GetPaletteEntryCount();
|
|
|
|
const sal_uInt16 nMaxColors = 1 << pAcc->GetBitCount();
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
// erst einmal naechste Farbe nehmen
|
|
|
|
aReplace = pAcc->GetBestMatchingColor( rReplaceColor );
|
|
|
|
|
|
|
|
// falls Palettenbild, und die zu setzende Farbe ist nicht
|
|
|
|
// in der Palette, suchen wir nach freien Eintraegen (teuer)
|
2010-09-29 15:46:40 +08:00
|
|
|
if( pAcc->GetPaletteColor( (sal_uInt8) aReplace ) != BitmapColor( rReplaceColor ) )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
// erst einmal nachsehen, ob wir unsere ReplaceColor
|
|
|
|
// nicht auf einen freien Platz am Ende der Palette
|
|
|
|
// setzen koennen
|
|
|
|
if( nActColors < nMaxColors )
|
|
|
|
{
|
|
|
|
pAcc->SetPaletteEntryCount( nActColors + 1 );
|
|
|
|
pAcc->SetPaletteColor( nActColors, rReplaceColor );
|
2010-09-29 15:46:40 +08:00
|
|
|
aReplace = BitmapColor( (sal_uInt8) nActColors );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool* pFlags = new sal_Bool[ nMaxColors ];
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
// alle Eintraege auf 0 setzen
|
|
|
|
memset( pFlags, 0, nMaxColors );
|
|
|
|
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ )
|
|
|
|
for( long nX = 0L; nX < nWidth; nX++ )
|
2010-09-29 15:46:40 +08:00
|
|
|
pFlags[ (sal_uInt8) pAcc->GetPixel( nY, nX ) ] = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
for( sal_uInt16 i = 0UL; i < nMaxColors; i++ )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
// Hurra, wir haben einen unbenutzten Eintrag
|
|
|
|
if( !pFlags[ i ] )
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
pAcc->SetPaletteColor( (sal_uInt16) i, rReplaceColor );
|
|
|
|
aReplace = BitmapColor( (sal_uInt8) i );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete[] pFlags;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
aReplace = rReplaceColor;
|
|
|
|
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ )
|
|
|
|
for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite )
|
|
|
|
pAcc->SetPixel( nY, nX, aReplace );
|
2002-10-22 16:25:33 +00:00
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
|
|
|
|
ReleaseAccess( pAcc );
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::Replace( const AlphaMask& rAlpha, const Color& rMergeColor )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
Bitmap aNewBmp( GetSizePixel(), 24 );
|
|
|
|
BitmapReadAccess* pAcc = AcquireReadAccess();
|
|
|
|
BitmapReadAccess* pAlphaAcc = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
|
|
|
|
BitmapWriteAccess* pNewAcc = aNewBmp.AcquireWriteAccess();
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( pAcc && pAlphaAcc && pNewAcc )
|
|
|
|
{
|
|
|
|
BitmapColor aCol;
|
|
|
|
const long nWidth = Min( pAlphaAcc->Width(), pAcc->Width() );
|
|
|
|
const long nHeight = Min( pAlphaAcc->Height(), pAcc->Height() );
|
|
|
|
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
aCol = pAcc->GetColor( nY, nX );
|
2010-09-29 15:46:40 +08:00
|
|
|
pNewAcc->SetPixel( nY, nX, aCol.Merge( rMergeColor, 255 - (sal_uInt8) pAlphaAcc->GetPixel( nY, nX ) ) );
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseAccess( pAcc );
|
|
|
|
( (AlphaMask&) rAlpha ).ReleaseAccess( pAlphaAcc );
|
|
|
|
aNewBmp.ReleaseAccess( pNewAcc );
|
|
|
|
|
|
|
|
if( bRet )
|
|
|
|
{
|
|
|
|
const MapMode aMap( maPrefMapMode );
|
|
|
|
const Size aSize( maPrefSize );
|
|
|
|
|
|
|
|
*this = aNewBmp;
|
|
|
|
|
|
|
|
maPrefMapMode = aMap;
|
|
|
|
maPrefSize = aSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2011-01-12 15:07:10 +01:00
|
|
|
sal_Bool Bitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
// Bitmaps with 1 bit color depth can cause problems
|
|
|
|
// if they have other entries than black/white in their palette
|
|
|
|
if( 1 == GetBitCount() )
|
|
|
|
Convert( BMP_CONVERSION_4BIT_COLORS );
|
|
|
|
|
|
|
|
BitmapWriteAccess* pAcc = AcquireWriteAccess();
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( pAcc )
|
|
|
|
{
|
|
|
|
const long nMinR = MinMax( (long) rSearchColor.GetRed() - nTol, 0, 255 );
|
|
|
|
const long nMaxR = MinMax( (long) rSearchColor.GetRed() + nTol, 0, 255 );
|
|
|
|
const long nMinG = MinMax( (long) rSearchColor.GetGreen() - nTol, 0, 255 );
|
|
|
|
const long nMaxG = MinMax( (long) rSearchColor.GetGreen() + nTol, 0, 255 );
|
|
|
|
const long nMinB = MinMax( (long) rSearchColor.GetBlue() - nTol, 0, 255 );
|
|
|
|
const long nMaxB = MinMax( (long) rSearchColor.GetBlue() + nTol, 0, 255 );
|
|
|
|
|
|
|
|
if( pAcc->HasPalette() )
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
for( sal_uInt16 i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++ )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
const BitmapColor& rCol = pAcc->GetPaletteColor( i );
|
|
|
|
|
|
|
|
if( nMinR <= rCol.GetRed() && nMaxR >= rCol.GetRed() &&
|
|
|
|
nMinG <= rCol.GetGreen() && nMaxG >= rCol.GetGreen() &&
|
|
|
|
nMinB <= rCol.GetBlue() && nMaxB >= rCol.GetBlue() )
|
|
|
|
{
|
|
|
|
pAcc->SetPaletteColor( i, rReplaceColor );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BitmapColor aCol;
|
|
|
|
const BitmapColor aReplace( pAcc->GetBestMatchingColor( rReplaceColor ) );
|
|
|
|
|
|
|
|
for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
aCol = pAcc->GetPixel( nY, nX );
|
|
|
|
|
|
|
|
if( nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() &&
|
|
|
|
nMinG <= aCol.GetGreen() && nMaxG >= aCol.GetGreen() &&
|
|
|
|
nMinB <= aCol.GetBlue() && nMaxB >= aCol.GetBlue() )
|
|
|
|
{
|
|
|
|
pAcc->SetPixel( nY, nX, aReplace );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseAccess( pAcc );
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::Replace( const Color* pSearchColors, const Color* pReplaceColors,
|
2011-01-12 15:07:10 +01:00
|
|
|
sal_uLong nColorCount, sal_uLong* _pTols )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
// Bitmaps with 1 bit color depth can cause problems
|
|
|
|
// if they have other entries than black/white in their palette
|
|
|
|
if( 1 == GetBitCount() )
|
|
|
|
Convert( BMP_CONVERSION_4BIT_COLORS );
|
|
|
|
|
|
|
|
BitmapWriteAccess* pAcc = AcquireWriteAccess();
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( pAcc )
|
|
|
|
{
|
|
|
|
long* pMinR = new long[ nColorCount ];
|
|
|
|
long* pMaxR = new long[ nColorCount ];
|
|
|
|
long* pMinG = new long[ nColorCount ];
|
|
|
|
long* pMaxG = new long[ nColorCount ];
|
|
|
|
long* pMinB = new long[ nColorCount ];
|
|
|
|
long* pMaxB = new long[ nColorCount ];
|
|
|
|
long* pTols;
|
2011-01-12 15:07:10 +01:00
|
|
|
sal_uLong i;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( !_pTols )
|
|
|
|
{
|
|
|
|
pTols = new long[ nColorCount ];
|
|
|
|
memset( pTols, 0, nColorCount * sizeof( long ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pTols = (long*) _pTols;
|
|
|
|
|
|
|
|
for( i = 0UL; i < nColorCount; i++ )
|
|
|
|
{
|
|
|
|
const Color& rCol = pSearchColors[ i ];
|
|
|
|
const long nTol = pTols[ i ];
|
|
|
|
|
|
|
|
pMinR[ i ] = MinMax( (long) rCol.GetRed() - nTol, 0, 255 );
|
|
|
|
pMaxR[ i ] = MinMax( (long) rCol.GetRed() + nTol, 0, 255 );
|
|
|
|
pMinG[ i ] = MinMax( (long) rCol.GetGreen() - nTol, 0, 255 );
|
|
|
|
pMaxG[ i ] = MinMax( (long) rCol.GetGreen() + nTol, 0, 255 );
|
|
|
|
pMinB[ i ] = MinMax( (long) rCol.GetBlue() - nTol, 0, 255 );
|
|
|
|
pMaxB[ i ] = MinMax( (long) rCol.GetBlue() + nTol, 0, 255 );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pAcc->HasPalette() )
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
for( sal_uInt16 nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); nEntry < nPalCount; nEntry++ )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
const BitmapColor& rCol = pAcc->GetPaletteColor( nEntry );
|
|
|
|
|
|
|
|
for( i = 0UL; i < nColorCount; i++ )
|
|
|
|
{
|
|
|
|
if( pMinR[ i ] <= rCol.GetRed() && pMaxR[ i ] >= rCol.GetRed() &&
|
|
|
|
pMinG[ i ] <= rCol.GetGreen() && pMaxG[ i ] >= rCol.GetGreen() &&
|
|
|
|
pMinB[ i ] <= rCol.GetBlue() && pMaxB[ i ] >= rCol.GetBlue() )
|
|
|
|
{
|
2010-09-29 15:46:40 +08:00
|
|
|
pAcc->SetPaletteColor( (sal_uInt16)nEntry, pReplaceColors[ i ] );
|
2000-09-18 16:07:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BitmapColor aCol;
|
|
|
|
BitmapColor* pReplaces = new BitmapColor[ nColorCount ];
|
|
|
|
|
|
|
|
for( i = 0UL; i < nColorCount; i++ )
|
|
|
|
pReplaces[ i ] = pAcc->GetBestMatchingColor( pReplaceColors[ i ] );
|
|
|
|
|
|
|
|
for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
|
|
|
|
{
|
|
|
|
for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
aCol = pAcc->GetPixel( nY, nX );
|
|
|
|
|
|
|
|
for( i = 0UL; i < nColorCount; i++ )
|
|
|
|
{
|
|
|
|
if( pMinR[ i ] <= aCol.GetRed() && pMaxR[ i ] >= aCol.GetRed() &&
|
|
|
|
pMinG[ i ] <= aCol.GetGreen() && pMaxG[ i ] >= aCol.GetGreen() &&
|
|
|
|
pMinB[ i ] <= aCol.GetBlue() && pMaxB[ i ] >= aCol.GetBlue() )
|
|
|
|
{
|
|
|
|
pAcc->SetPixel( nY, nX, pReplaces[ i ] );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete[] pReplaces;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !_pTols )
|
|
|
|
delete[] pTols;
|
|
|
|
|
|
|
|
delete[] pMinR;
|
|
|
|
delete[] pMaxR;
|
|
|
|
delete[] pMinG;
|
|
|
|
delete[] pMaxG;
|
|
|
|
delete[] pMinB;
|
|
|
|
delete[] pMaxB;
|
|
|
|
ReleaseAccess( pAcc );
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay )
|
|
|
|
{
|
|
|
|
Bitmap aDispBmp( *this );
|
|
|
|
|
|
|
|
if( mpImpBmp && ( pDisplay->mpGraphics || pDisplay->ImplGetGraphics() ) )
|
|
|
|
{
|
|
|
|
ImpBitmap* pImpDispBmp = new ImpBitmap;
|
|
|
|
|
|
|
|
if( pImpDispBmp->ImplCreate( *mpImpBmp, pDisplay->mpGraphics ) )
|
|
|
|
aDispBmp.ImplSetImpBitmap( pImpDispBmp );
|
|
|
|
else
|
|
|
|
delete pImpDispBmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return aDispBmp;
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::CombineSimple( const Bitmap& rMask, BmpCombine eCombine )
|
2000-09-18 16:07:07 +00:00
|
|
|
{
|
|
|
|
BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
|
|
|
|
BitmapWriteAccess* pAcc = AcquireWriteAccess();
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2000-09-18 16:07:07 +00:00
|
|
|
|
|
|
|
if( pMaskAcc && pAcc )
|
|
|
|
{
|
|
|
|
const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
|
|
|
|
const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
|
|
|
|
const Color aColBlack( COL_BLACK );
|
|
|
|
BitmapColor aPixel;
|
|
|
|
BitmapColor aMaskPixel;
|
|
|
|
const BitmapColor aWhite( pAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
|
|
|
|
const BitmapColor aBlack( pAcc->GetBestMatchingColor( aColBlack ) );
|
|
|
|
const BitmapColor aMaskBlack( pMaskAcc->GetBestMatchingColor( aColBlack ) );
|
|
|
|
|
|
|
|
switch( eCombine )
|
|
|
|
{
|
|
|
|
case( BMP_COMBINE_COPY ):
|
|
|
|
{
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
if( pMaskAcc->GetPixel( nY, nX ) == aMaskBlack )
|
|
|
|
pAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
else
|
|
|
|
pAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case( BMP_COMBINE_INVERT ):
|
|
|
|
{
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
if( pAcc->GetPixel( nY, nX ) == aBlack )
|
|
|
|
pAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
else
|
|
|
|
pAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case( BMP_COMBINE_AND ):
|
|
|
|
{
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
|
|
|
|
pAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
else
|
|
|
|
pAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case( BMP_COMBINE_NAND ):
|
|
|
|
{
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
|
|
|
|
pAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
else
|
|
|
|
pAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case( BMP_COMBINE_OR ):
|
|
|
|
{
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
|
|
|
|
pAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
else
|
|
|
|
pAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case( BMP_COMBINE_NOR ):
|
|
|
|
{
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
|
|
|
|
pAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
else
|
|
|
|
pAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case( BMP_COMBINE_XOR ):
|
|
|
|
{
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
aPixel = pAcc->GetPixel( nY, nX );
|
|
|
|
aMaskPixel = pMaskAcc->GetPixel( nY, nX );
|
|
|
|
|
|
|
|
if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
|
|
|
|
( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
|
|
|
|
{
|
|
|
|
pAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case( BMP_COMBINE_NXOR ):
|
|
|
|
{
|
|
|
|
for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
|
|
|
|
{
|
|
|
|
aPixel = pAcc->GetPixel( nY, nX );
|
|
|
|
aMaskPixel = pMaskAcc->GetPixel( nY, nX );
|
|
|
|
|
|
|
|
if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
|
|
|
|
( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
|
|
|
|
{
|
|
|
|
pAcc->SetPixel( nY, nX, aBlack );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pAcc->SetPixel( nY, nX, aWhite );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2002-10-22 16:25:33 +00:00
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2000-09-18 16:07:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
|
|
|
|
ReleaseAccess( pAcc );
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::Blend( const AlphaMask& rAlpha, const Color& rBackgroundColor )
|
2003-04-24 13:56:22 +00:00
|
|
|
{
|
|
|
|
// TODO: Have a look at OutputDevice::ImplDrawAlpha() for some
|
|
|
|
// optimizations. Might even consolidate the code here and there.
|
|
|
|
|
|
|
|
// convert to a truecolor bitmap, if we're a paletted one. There's
|
|
|
|
// room for tradeoff decision here, maybe later for an overload (or a flag)
|
|
|
|
if( GetBitCount() <= 8 )
|
|
|
|
Convert( BMP_CONVERSION_24BIT );
|
|
|
|
|
|
|
|
BitmapReadAccess* pAlphaAcc = const_cast<AlphaMask&>(rAlpha).AcquireReadAccess();
|
|
|
|
BitmapWriteAccess* pAcc = AcquireWriteAccess();
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool bRet = sal_False;
|
2003-04-24 13:56:22 +00:00
|
|
|
|
|
|
|
if( pAlphaAcc && pAcc )
|
|
|
|
{
|
|
|
|
const long nWidth = Min( pAlphaAcc->Width(), pAcc->Width() );
|
|
|
|
const long nHeight = Min( pAlphaAcc->Height(), pAcc->Height() );
|
|
|
|
|
|
|
|
for( long nY = 0L; nY < nHeight; ++nY )
|
|
|
|
for( long nX = 0L; nX < nWidth; ++nX )
|
|
|
|
pAcc->SetPixel( nY, nX,
|
|
|
|
pAcc->GetPixel( nY, nX ).Merge( rBackgroundColor,
|
|
|
|
255 - pAlphaAcc->GetPixel( nY, nX ) ) );
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
bRet = sal_True;
|
2003-04-24 13:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const_cast<AlphaMask&>(rAlpha).ReleaseAccess( pAlphaAcc );
|
|
|
|
ReleaseAccess( pAcc );
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2010-09-29 15:46:40 +08:00
|
|
|
sal_Bool Bitmap::MakeMono( sal_uInt8 cThreshold )
|
2003-03-27 16:59:30 +00:00
|
|
|
{
|
|
|
|
return ImplMakeMono( cThreshold );
|
|
|
|
}
|
2005-03-10 12:15:37 +00:00
|
|
|
|
|
|
|
bool Bitmap::GetSystemData( BitmapSystemData& rData ) const
|
|
|
|
{
|
|
|
|
bool bRet = false;
|
|
|
|
if( mpImpBmp )
|
|
|
|
{
|
|
|
|
SalBitmap* pSalBitmap = mpImpBmp->ImplGetSalBitmap();
|
|
|
|
if( pSalBitmap )
|
|
|
|
bRet = pSalBitmap->GetSystemData( rData );
|
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
2010-10-14 08:27:31 +02:00
|
|
|
|
2013-03-14 09:36:43 +01:00
|
|
|
bool Bitmap::HasAlpha()
|
|
|
|
{
|
|
|
|
bool bRet = false;
|
|
|
|
if( mpImpBmp )
|
|
|
|
{
|
|
|
|
SalBitmap* pSalBitmap = mpImpBmp->ImplGetSalBitmap();
|
|
|
|
if( pSalBitmap )
|
|
|
|
bRet = pSalBitmap->HasAlpha();
|
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2010-10-14 08:27:31 +02:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|