1
// --------------------------------------------------------------------
3
// --------------------------------------------------------------------
6
This file is part of the extensible drawing editor Ipe.
7
Copyright (C) 1993-2004 Otfried Cheong
9
Ipe is free software; you can redistribute it and/or modify it
10
under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
14
As a special exception, you have permission to link Ipe with the
15
CGAL library and distribute executables, as long as you follow the
16
requirements of the Gnu General Public License in regard to all of
17
the software in the executable aside from CGAL.
19
Ipe is distributed in the hope that it will be useful, but WITHOUT
20
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
22
License for more details.
24
You should have received a copy of the GNU General Public License
25
along with Ipe; if not, you can find it at
26
"http://www.gnu.org/copyleft/gpl.html", or write to the Free
27
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31
#include "ipebitmap.h"
33
// --------------------------------------------------------------------
39
Bitmaps are explicitely shared using reference-counting. Copying is
40
cheap, so IpeBitmap objects are meant to be passed by value.
42
The bitmap can cache data to speed up rendering. This data can be
43
set only once (as the bitmap is conceptually immutable).
45
The bitmap also provides a slot for short-term storage of an "object
46
number". The PDF embedder, for instance, sets it to the PDF object
47
number when embedding the bitmap, and can reuse it when "drawing"
51
//! Default constructor constructs null bitmap.
52
IpeBitmap::IpeBitmap()
57
//! Create from XML stream.
58
IpeBitmap::IpeBitmap(const IpeXmlAttributes &attr, IpeString data,
63
iImp->iObjNum = IpeLex(attr["id"]).GetInt();
65
iImp->iWidth = IpeLex(attr["width"]).GetInt();
66
iImp->iHeight = IpeLex(attr["height"]).GetInt();
67
int length = IpeLex(attr["length"]).GetInt();
68
assert(iImp->iWidth > 0 && iImp->iHeight > 0);
69
IpeString cs = attr["ColorSpace"];
70
if (cs == "DeviceGray") {
71
iImp->iComponents = 1;
72
iImp->iColorSpace = EDeviceGray;
73
} else if (cs == "DeviceCMYK") {
74
iImp->iComponents = 4;
75
iImp->iColorSpace = EDeviceCMYK;
77
iImp->iComponents = 3;
78
iImp->iColorSpace = EDeviceRGB;
80
IpeString fi = attr["Filter"];
81
if (fi == "DCTDecode")
82
iImp->iFilter = EDCTDecode;
83
else if (fi == "FlateDecode")
84
iImp->iFilter = EFlateDecode;
86
iImp->iFilter = EDirect;
87
iImp->iBitsPerComponent = IpeLex(attr["BitsPerComponent"]).GetInt();
89
assert(iImp->iFilter == EDirect);
90
int bitsPerRow = Width() * Components() * BitsPerComponent();
91
int bytesPerRow = (bitsPerRow + 7) / 8;
92
length = Height() * bytesPerRow;
95
assert(length == data.size());
96
iImp->iData = IpeBuffer(data.data(), length);
99
iImp->iData = IpeBuffer(length);
100
char *p = iImp->iData.data();
101
IpeLex datalex(data);
103
*p++ = char(datalex.GetHexByte());
108
//! Create a new image
109
IpeBitmap::IpeBitmap(int width, int height,
110
TColorSpace colorSpace, int bitsPerComponent,
111
IpeBuffer data, TFilter filter)
117
iImp->iWidth = width;
118
iImp->iHeight = height;
119
assert(iImp->iWidth > 0 && iImp->iHeight > 0);
120
iImp->iColorSpace = colorSpace;
121
switch (colorSpace) {
123
iImp->iComponents = 1;
126
iImp->iComponents = 3;
129
iImp->iComponents = 4;
132
iImp->iFilter = filter;
133
iImp->iBitsPerComponent = bitsPerComponent;
138
//! Copy constructor.
139
IpeBitmap::IpeBitmap(const IpeBitmap &rhs)
147
IpeBitmap::~IpeBitmap()
149
if (iImp && --iImp->iRefCount == 0)
153
//! Assignment operator (takes care of reference counting).
154
IpeBitmap &IpeBitmap::operator=(const IpeBitmap &rhs)
157
if (iImp && --iImp->iRefCount == 0)
166
//! Save bitmap in XML stream.
167
void IpeBitmap::SaveAsXml(IpeStream &stream, int id, int pdfObjNum) const
171
stream << " id=\"" << id << "\"";
172
stream << " width=\"" << Width() << "\"";
173
stream << " height=\"" << Height() << "\"";
174
stream << " length=\"" << Size() << "\"";
175
switch (ColorSpace()) {
177
stream << " ColorSpace=\"DeviceGray\"";
180
stream << " ColorSpace=\"DeviceRGB\"";
183
stream << " ColorSpace=\"DeviceCMYK\"";
188
stream << " Filter=\"FlateDecode\"";
191
stream << " Filter=\"DCTDecode\"";
197
stream << " BitsPerComponent=\"" << BitsPerComponent() << "\"";
199
if (pdfObjNum >= 0) {
200
stream << " pdfObject=\"" << pdfObjNum << "\"/>\n";
204
const char *data = Data();
205
const char *fin = data + Size();
207
while (data != fin) {
208
stream.PutHexByte(*data++);
216
stream << "</bitmap>\n";
220
//! Set a cached bitmap for fast rendering.
221
void IpeBitmap::SetRenderData(void *data) const
223
assert(iImp && iImp->iRender == 0);
224
iImp->iRender = data;
227
bool IpeBitmap::Equal(IpeBitmap rhs) const
229
if (iImp == rhs.iImp)
231
if (!iImp || !rhs.iImp)
234
if (iImp->iColorSpace != rhs.iImp->iColorSpace ||
235
iImp->iBitsPerComponent != rhs.iImp->iBitsPerComponent ||
236
iImp->iWidth != rhs.iImp->iWidth ||
237
iImp->iHeight != rhs.iImp->iHeight ||
238
iImp->iComponents != rhs.iImp->iComponents ||
239
iImp->iFilter != rhs.iImp->iFilter ||
240
iImp->iChecksum != rhs.iImp->iChecksum ||
241
iImp->iData.size() != rhs.iImp->iData.size())
244
int len = iImp->iData.size();
245
char *p = iImp->iData.data();
246
char *q = rhs.iImp->iData.data();
254
void IpeBitmap::ComputeChecksum()
257
int len = iImp->iData.size();
258
char *p = iImp->iData.data();
260
s = (s & 0x0fffffff) << 3;
266
// --------------------------------------------------------------------