2 * Copyright 2002-2011, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
11 #include <BitmapStream.h>
21 // Initializes this object to either use the BBitmap passed to
22 // it as the object to read/write to or to create a BBitmap
23 // when data is written to this object.
24 BBitmapStream::BBitmapStream(BBitmap
* bitmap
)
30 fBigEndianHeader
= new (std::nothrow
) TranslatorBitmap
;
31 if (fBigEndianHeader
== NULL
) {
36 // Extract header information if bitmap is available
37 if (fBitmap
!= NULL
&& fBitmap
->InitCheck() == B_OK
) {
38 fHeader
.magic
= B_TRANSLATOR_BITMAP
;
39 fHeader
.bounds
= fBitmap
->Bounds();
40 fHeader
.rowBytes
= fBitmap
->BytesPerRow();
41 fHeader
.colors
= fBitmap
->ColorSpace();
42 fHeader
.dataSize
= static_cast<uint32
>
43 ((fHeader
.bounds
.Height() + 1) * fHeader
.rowBytes
);
44 fSize
= sizeof(TranslatorBitmap
) + fHeader
.dataSize
;
46 if (B_HOST_IS_BENDIAN
)
47 memcpy(fBigEndianHeader
, &fHeader
, sizeof(TranslatorBitmap
));
49 SwapHeader(&fHeader
, fBigEndianHeader
);
55 BBitmapStream::~BBitmapStream()
60 delete fBigEndianHeader
;
64 // Reads data from the stream at a specific position and size.
66 BBitmapStream::ReadAt(off_t pos
, void* buffer
, size_t size
)
72 if (pos
>= (off_t
)fSize
|| pos
< 0 || buffer
== NULL
)
78 if (pos
< (off_t
)sizeof(TranslatorBitmap
)) {
79 toRead
= sizeof(TranslatorBitmap
) - pos
;
80 source
= (reinterpret_cast<uint8
*>(fBigEndianHeader
)) + pos
;
83 source
= (reinterpret_cast<uint8
*>(fBitmap
->Bits())) + pos
-
84 sizeof(TranslatorBitmap
);
86 if (toRead
> (ssize_t
)size
)
87 toRead
= (ssize_t
)size
;
89 memcpy(buffer
, source
, toRead
);
94 // Writes data to the bitmap starting at a specific position and size.
96 BBitmapStream::WriteAt(off_t pos
, const void* data
, size_t size
)
100 if (!data
|| pos
< 0 || pos
> (off_t
)fSize
)
107 // We depend on writing the header separately in detecting
109 if (pos
< (off_t
)sizeof(TranslatorBitmap
)) {
110 toWrite
= sizeof(TranslatorBitmap
) - pos
;
111 dest
= (reinterpret_cast<uint8
*> (&fHeader
)) + pos
;
113 if (fBitmap
== NULL
|| !fBitmap
->IsValid())
116 toWrite
= fHeader
.dataSize
- pos
+ sizeof(TranslatorBitmap
);
117 dest
= (reinterpret_cast<uint8
*> (fBitmap
->Bits())) +
118 pos
- sizeof(TranslatorBitmap
);
122 if (!toWrite
&& size
)
123 // i.e. we've been told to write too much
126 memcpy(dest
, data
, toWrite
);
129 data
= (reinterpret_cast<const uint8
*> (data
)) + toWrite
;
131 if (pos
> (off_t
)fSize
)
133 // If we change the header, the rest needs to be reset
134 if (pos
== sizeof(TranslatorBitmap
)) {
135 // Setup both host and Big Endian byte order bitmap headers
136 memcpy(fBigEndianHeader
, &fHeader
, sizeof(TranslatorBitmap
));
137 if (B_HOST_IS_LENDIAN
)
138 SwapHeader(fBigEndianHeader
, &fHeader
);
141 && (fBitmap
->Bounds() != fHeader
.bounds
142 || fBitmap
->ColorSpace() != fHeader
.colors
143 || (uint32
)fBitmap
->BytesPerRow() != fHeader
.rowBytes
)) {
145 // if someone detached, we don't delete
149 if (fBitmap
== NULL
) {
150 if (fHeader
.bounds
.left
> 0.0 || fHeader
.bounds
.top
> 0.0)
151 DEBUGGER("non-origin bounds!");
152 fBitmap
= new (std::nothrow
)BBitmap(fHeader
.bounds
,
156 if (!fBitmap
->IsValid()) {
157 status_t error
= fBitmap
->InitCheck();
162 if ((uint32
)fBitmap
->BytesPerRow() != fHeader
.rowBytes
) {
163 fprintf(stderr
, "BitmapStream %" B_PRId32
" %" B_PRId32
"\n",
164 fBitmap
->BytesPerRow(), fHeader
.rowBytes
);
165 return B_MISMATCHED_VALUES
;
169 fSize
= sizeof(TranslatorBitmap
) + fBitmap
->BitsLength();
176 // Changes the current stream position.
178 BBitmapStream::Seek(off_t position
, uint32 seekMode
)
180 // When whence == SEEK_SET, it just falls through to
181 // fPosition = position
182 if (seekMode
== SEEK_CUR
)
183 position
+= fPosition
;
184 else if (seekMode
== SEEK_END
)
187 if (position
< 0 || position
> (off_t
)fSize
)
190 fPosition
= position
;
195 // Returns the current stream position
197 BBitmapStream::Position() const
204 // Returns the current stream size
206 BBitmapStream::Size() const
212 // Sets the size of the data.
213 // I'm not sure if this method has any real purpose.
215 BBitmapStream::SetSize(off_t size
)
219 if (fBitmap
&& (size
> (off_t
)(fHeader
.dataSize
+ sizeof(TranslatorBitmap
))))
222 // What if someone calls SetSize() before writing the header,
223 // so we don't know what bitmap to create?
225 // We assume people will write the header before any data,
226 // so SetSize() is really not going to do anything.
234 // Sets _bitmap to point to the internal bitmap object.
236 BBitmapStream::DetachBitmap(BBitmap
** _bitmap
)
240 if (!fBitmap
|| fDetached
)
250 // Swaps the byte order of source, no matter the byte order, and
251 // copies the result to destination.
253 BBitmapStream::SwapHeader(const TranslatorBitmap
* source
,
254 TranslatorBitmap
* destination
)
256 if (source
== NULL
|| destination
== NULL
)
259 memcpy(destination
, source
, sizeof(TranslatorBitmap
));
260 swap_data(B_UINT32_TYPE
, destination
, sizeof(TranslatorBitmap
),
265 void BBitmapStream::_ReservedBitmapStream1() {}
266 void BBitmapStream::_ReservedBitmapStream2() {}