1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <vcl/graph.hxx>
22 #include <vcl/BitmapTools.hxx>
23 #include <sal/log.hxx>
24 #include <tools/stream.hxx>
25 #include <filter/RasReader.hxx>
27 class FilterConfigItem
;
29 #define RAS_TYPE_OLD 0x00000000 // supported formats by this filter
30 #define RAS_TYPE_STANDARD 0x00000001
31 #define RAS_TYPE_BYTE_ENCODED 0x00000002
32 #define RAS_TYPE_RGB_FORMAT 0x00000003
34 #define RAS_COLOR_NO_MAP 0x00000000
35 #define RAS_COLOR_RGB_MAP 0x00000001
36 #define RAS_COLOR_RAW_MAP 0x00000002
38 #define SUNRASTER_MAGICNUMBER 0x59a66a95
40 //============================ RASReader ==================================
48 SvStream
& m_rRAS
; // the RAS file to be read in
51 sal_Int32 mnWidth
, mnHeight
; // image dimensions in pixels
52 sal_uInt16 mnDstBitsPerPix
;
53 sal_uInt16 mnDstColors
;
54 sal_Int32 mnDepth
, mnImageDatSize
, mnType
;
55 sal_Int32 mnColorMapType
, mnColorMapSize
;
56 sal_uInt8 mnRepCount
, mnRepVal
; // RLE Decoding
58 bool ImplReadBody(vcl::bitmap::RawBitmap
&, std::vector
<Color
> const & rvPalette
);
59 bool ImplReadHeader();
60 sal_uInt8
ImplGetByte();
63 explicit RASReader(SvStream
&rRAS
);
64 bool ReadRAS(Graphic
& rGraphic
);
69 //=================== Methods of RASReader ==============================
71 RASReader::RASReader(SvStream
&rRAS
)
88 bool RASReader::ReadRAS(Graphic
& rGraphic
)
90 sal_uInt32 nMagicNumber
;
92 if ( m_rRAS
.GetError() )
95 m_rRAS
.SetEndian( SvStreamEndian::BIG
);
96 m_rRAS
.ReadUInt32( nMagicNumber
);
97 if (!m_rRAS
.good() || nMagicNumber
!= SUNRASTER_MAGICNUMBER
)
102 mbStatus
= ImplReadHeader();
106 std::vector
<Color
> aPalette
;
109 if ( mnDstBitsPerPix
<= 8 ) // pallets pictures
111 bool bPalette(false);
113 if ( mnColorMapType
== RAS_COLOR_RAW_MAP
) // RAW color map is skipped
115 sal_uInt64 nCurPos
= m_rRAS
.Tell();
116 bOk
= checkSeek(m_rRAS
, nCurPos
+ mnColorMapSize
);
118 else if ( mnColorMapType
== RAS_COLOR_RGB_MAP
) // we can read out the RGB
120 mnDstColors
= static_cast<sal_uInt16
>( mnColorMapSize
/ 3 );
122 if ( ( 1 << mnDstBitsPerPix
) < mnDstColors
)
125 if ( ( mnDstColors
>= 2 ) && ( ( mnColorMapSize
% 3 ) == 0 ) )
127 aPalette
.resize(mnDstColors
);
129 sal_uInt8 nRed
[256], nGreen
[256], nBlue
[256];
130 for ( i
= 0; i
< mnDstColors
; i
++ ) m_rRAS
.ReadUChar( nRed
[ i
] );
131 for ( i
= 0; i
< mnDstColors
; i
++ ) m_rRAS
.ReadUChar( nGreen
[ i
] );
132 for ( i
= 0; i
< mnDstColors
; i
++ ) m_rRAS
.ReadUChar( nBlue
[ i
] );
133 for ( i
= 0; i
< mnDstColors
; i
++ )
135 aPalette
[i
] = Color(nRed
[ i
], nGreen
[ i
], nBlue
[ i
]);
143 else if ( mnColorMapType
!= RAS_COLOR_NO_MAP
) // everything else is not standard
148 mnDstColors
= 1 << mnDstBitsPerPix
;
149 aPalette
.resize(mnDstColors
);
150 for ( sal_uInt16 i
= 0; i
< mnDstColors
; i
++ )
152 sal_uInt8 nCount
= 255 - ( 255 * i
/ ( mnDstColors
- 1 ) );
153 aPalette
[i
] = Color(nCount
, nCount
, nCount
);
159 if ( mnColorMapType
!= RAS_COLOR_NO_MAP
) // when graphic has more than 256 colors and a color map we skip
161 sal_uInt64 nCurPos
= m_rRAS
.Tell();
162 bOk
= checkSeek(m_rRAS
, nCurPos
+ mnColorMapSize
);
169 //The RLE packets are typically three bytes in size:
170 //The first byte is a Flag Value indicating the type of RLE packet.
171 //The second byte is the Run Count.
172 //The third byte is the Run Value.
174 //for the sake of simplicity we'll assume that RAS_TYPE_BYTE_ENCODED can
175 //describe data 255 times larger than the data stored
176 size_t nMaxCompression
= mnType
!= RAS_TYPE_BYTE_ENCODED
? 1 : 255;
178 if (o3tl::checked_multiply
<sal_Int32
>(mnWidth
, mnHeight
, nBitSize
) || o3tl::checked_multiply
<sal_Int32
>(nBitSize
, mnDepth
, nBitSize
))
180 if (m_rRAS
.remainingSize() * nMaxCompression
< static_cast<sal_uInt32
>(nBitSize
) / 8)
183 vcl::bitmap::RawBitmap
aBmp(Size(mnWidth
, mnHeight
), 24);
185 // read in the bitmap data
186 mbStatus
= ImplReadBody(aBmp
, aPalette
);
189 rGraphic
= vcl::bitmap::CreateFromData(std::move(aBmp
));
194 bool RASReader::ImplReadHeader()
196 m_rRAS
.ReadInt32(mnWidth
).ReadInt32(mnHeight
).ReadInt32(mnDepth
).ReadInt32(mnImageDatSize
).ReadInt32(mnType
).ReadInt32(mnColorMapType
).ReadInt32(mnColorMapSize
);
198 if (!m_rRAS
.good() || mnWidth
<= 0 || mnHeight
<= 0 || mnImageDatSize
<= 0)
206 mnDstBitsPerPix
= static_cast<sal_uInt16
>(mnDepth
);
209 mnDstBitsPerPix
= 24;
219 case RAS_TYPE_STANDARD
:
220 case RAS_TYPE_RGB_FORMAT
:
221 case RAS_TYPE_BYTE_ENCODED
: // this type will be supported later
232 const Color
& SanitizePaletteIndex(std::vector
<Color
> const & rvPalette
, sal_uInt8 nIndex
)
234 if (nIndex
>= rvPalette
.size())
236 auto nSanitizedIndex
= nIndex
% rvPalette
.size();
237 SAL_WARN_IF(nIndex
!= nSanitizedIndex
, "filter.ras", "invalid colormap index: "
238 << static_cast<unsigned int>(nIndex
) << ", colormap len is: "
239 << rvPalette
.size());
240 nIndex
= nSanitizedIndex
;
242 return rvPalette
[nIndex
];
246 bool RASReader::ImplReadBody(vcl::bitmap::RawBitmap
& rBitmap
, std::vector
<Color
> const & rvPalette
)
249 sal_uInt8 nRed
, nGreen
, nBlue
;
250 switch ( mnDstBitsPerPix
)
255 for (y
= 0; y
< mnHeight
&& mbStatus
; ++y
)
257 for (x
= 0; x
< mnWidth
&& mbStatus
; ++x
)
261 nDat
= ImplGetByte();
265 rBitmap
.SetPixel(y
, x
, SanitizePaletteIndex(rvPalette
,
266 sal::static_int_cast
< sal_uInt8
>(
267 nDat
>> ( ( x
& 7 ) ^ 7 ))));
269 if (!( ( x
- 1 ) & 0x8 ) )
271 ImplGetByte(); // WORD ALIGNMENT ???
280 for (y
= 0; y
< mnHeight
&& mbStatus
; ++y
)
282 for (x
= 0; x
< mnWidth
&& mbStatus
; ++x
)
284 sal_uInt8 nDat
= ImplGetByte();
285 rBitmap
.SetPixel(y
, x
, SanitizePaletteIndex(rvPalette
, nDat
));
291 ImplGetByte(); // WORD ALIGNMENT ???
303 for (y
= 0; y
< mnHeight
&& mbStatus
; ++y
)
305 for (x
= 0; x
< mnWidth
&& mbStatus
; ++x
)
307 if ( mnType
== RAS_TYPE_RGB_FORMAT
)
309 nRed
= ImplGetByte();
310 nGreen
= ImplGetByte();
311 nBlue
= ImplGetByte();
315 nBlue
= ImplGetByte();
316 nGreen
= ImplGetByte();
317 nRed
= ImplGetByte();
319 rBitmap
.SetPixel(y
, x
, Color(nRed
, nGreen
, nBlue
));
325 ImplGetByte(); // WORD ALIGNMENT ???
333 for (y
= 0; y
< mnHeight
&& mbStatus
; ++y
)
335 for (x
= 0; x
< mnWidth
&& mbStatus
; ++x
)
337 ImplGetByte(); // pad byte > nil
338 if ( mnType
== RAS_TYPE_RGB_FORMAT
)
340 nRed
= ImplGetByte();
341 nGreen
= ImplGetByte();
342 nBlue
= ImplGetByte();
346 nBlue
= ImplGetByte();
347 nGreen
= ImplGetByte();
348 nRed
= ImplGetByte();
350 rBitmap
.SetPixel(y
, x
, Color(nRed
, nGreen
, nBlue
));
366 sal_uInt8
RASReader::ImplGetByte()
368 sal_uInt8
nRetVal(0);
369 if ( mnType
!= RAS_TYPE_BYTE_ENCODED
)
371 m_rRAS
.ReadUChar( nRetVal
);
383 m_rRAS
.ReadUChar( nRetVal
);
384 if ( nRetVal
!= 0x80 )
386 m_rRAS
.ReadUChar( nRetVal
);
389 mnRepCount
= nRetVal
;
390 m_rRAS
.ReadUChar( mnRepVal
);
396 //================== GraphicImport - the exported function ================
398 bool ImportRasGraphic( SvStream
& rStream
, Graphic
& rGraphic
)
404 RASReader
aRASReader(rStream
);
405 bRet
= aRASReader
.ReadRAS(rGraphic
);
414 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */