tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / vcl / source / filter / iras / iras.cxx
blob49cfe2bef2cc65206bf7a4dd81c0ffd4888e3d35
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 ==================================
42 namespace {
44 class RASReader {
46 private:
48 SvStream& m_rRAS; // the RAS file to be read in
50 bool mbStatus;
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();
62 public:
63 explicit RASReader(SvStream &rRAS);
64 bool ReadRAS(Graphic & rGraphic);
69 //=================== Methods of RASReader ==============================
71 RASReader::RASReader(SvStream &rRAS)
72 : m_rRAS(rRAS)
73 , mbStatus(true)
74 , mnWidth(0)
75 , mnHeight(0)
76 , mnDstBitsPerPix(0)
77 , mnDstColors(0)
78 , mnDepth(0)
79 , mnImageDatSize(0)
80 , mnType(0)
81 , mnColorMapType(0)
82 , mnColorMapSize(0)
83 , mnRepCount(0)
84 , mnRepVal(0)
88 bool RASReader::ReadRAS(Graphic & rGraphic)
90 sal_uInt32 nMagicNumber;
92 if ( m_rRAS.GetError() )
93 return false;
95 m_rRAS.SetEndian( SvStreamEndian::BIG );
96 m_rRAS.ReadUInt32( nMagicNumber );
97 if (!m_rRAS.good() || nMagicNumber != SUNRASTER_MAGICNUMBER)
98 return false;
100 // Kopf einlesen:
102 mbStatus = ImplReadHeader();
103 if ( !mbStatus )
104 return false;
106 std::vector<Color> aPalette;
107 bool bOk = true;
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 )
123 return false;
125 if ( ( mnDstColors >= 2 ) && ( ( mnColorMapSize % 3 ) == 0 ) )
127 aPalette.resize(mnDstColors);
128 sal_uInt16 i;
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 ]);
137 bPalette = true;
139 else
140 return false;
143 else if ( mnColorMapType != RAS_COLOR_NO_MAP ) // everything else is not standard
144 return false;
146 if (!bPalette)
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);
157 else
159 if ( mnColorMapType != RAS_COLOR_NO_MAP ) // when graphic has more than 256 colors and a color map we skip
160 { // the colormap
161 sal_uInt64 nCurPos = m_rRAS.Tell();
162 bOk = checkSeek(m_rRAS, nCurPos + mnColorMapSize);
166 if (!bOk)
167 return false;
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;
177 sal_Int32 nBitSize;
178 if (o3tl::checked_multiply<sal_Int32>(mnWidth, mnHeight, nBitSize) || o3tl::checked_multiply<sal_Int32>(nBitSize, mnDepth, nBitSize))
179 return false;
180 if (m_rRAS.remainingSize() * nMaxCompression < static_cast<sal_uInt32>(nBitSize) / 8)
181 return false;
183 vcl::bitmap::RawBitmap aBmp(Size(mnWidth, mnHeight), 24);
185 // read in the bitmap data
186 mbStatus = ImplReadBody(aBmp, aPalette);
188 if ( mbStatus )
189 rGraphic = vcl::bitmap::CreateFromData(std::move(aBmp));
191 return mbStatus;
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)
199 mbStatus = false;
201 switch ( mnDepth )
203 case 24 :
204 case 8 :
205 case 1 :
206 mnDstBitsPerPix = static_cast<sal_uInt16>(mnDepth);
207 break;
208 case 32 :
209 mnDstBitsPerPix = 24;
210 break;
212 default :
213 mbStatus = false;
216 switch ( mnType )
218 case RAS_TYPE_OLD :
219 case RAS_TYPE_STANDARD :
220 case RAS_TYPE_RGB_FORMAT :
221 case RAS_TYPE_BYTE_ENCODED : // this type will be supported later
222 break;
224 default:
225 mbStatus = false;
227 return mbStatus;
230 namespace
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)
248 sal_Int32 x, y;
249 sal_uInt8 nRed, nGreen, nBlue;
250 switch ( mnDstBitsPerPix )
252 case 1 :
254 sal_uInt8 nDat = 0;
255 for (y = 0; y < mnHeight && mbStatus; ++y)
257 for (x = 0; x < mnWidth && mbStatus; ++x)
259 if (!(x & 7))
261 nDat = ImplGetByte();
262 if (!m_rRAS.good())
263 mbStatus = false;
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 ???
272 if (!m_rRAS.good())
273 mbStatus = false;
276 break;
279 case 8 :
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));
286 if (!m_rRAS.good())
287 mbStatus = false;
289 if ( x & 1 )
291 ImplGetByte(); // WORD ALIGNMENT ???
292 if (!m_rRAS.good())
293 mbStatus = false;
296 break;
298 case 24 :
299 switch ( mnDepth )
302 case 24 :
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();
313 else
315 nBlue = ImplGetByte();
316 nGreen = ImplGetByte();
317 nRed = ImplGetByte();
319 rBitmap.SetPixel(y, x, Color(nRed, nGreen, nBlue));
320 if (!m_rRAS.good())
321 mbStatus = false;
323 if ( x & 1 )
325 ImplGetByte(); // WORD ALIGNMENT ???
326 if (!m_rRAS.good())
327 mbStatus = false;
330 break;
332 case 32 :
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();
344 else
346 nBlue = ImplGetByte();
347 nGreen = ImplGetByte();
348 nRed = ImplGetByte();
350 rBitmap.SetPixel(y, x, Color(nRed, nGreen, nBlue));
351 if (!m_rRAS.good())
352 mbStatus = false;
355 break;
357 break;
359 default:
360 mbStatus = false;
361 break;
363 return mbStatus;
366 sal_uInt8 RASReader::ImplGetByte()
368 sal_uInt8 nRetVal(0);
369 if ( mnType != RAS_TYPE_BYTE_ENCODED )
371 m_rRAS.ReadUChar( nRetVal );
372 return nRetVal;
374 else
376 if ( mnRepCount )
378 mnRepCount--;
379 return mnRepVal;
381 else
383 m_rRAS.ReadUChar( nRetVal );
384 if ( nRetVal != 0x80 )
385 return nRetVal;
386 m_rRAS.ReadUChar( nRetVal );
387 if ( nRetVal == 0 )
388 return 0x80;
389 mnRepCount = nRetVal ;
390 m_rRAS.ReadUChar( mnRepVal );
391 return mnRepVal;
396 //================== GraphicImport - the exported function ================
398 bool ImportRasGraphic( SvStream & rStream, Graphic & rGraphic)
400 bool bRet = false;
404 RASReader aRASReader(rStream);
405 bRet = aRASReader.ReadRAS(rGraphic );
407 catch (...)
411 return bRet;
414 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */