• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KImgIO

  • sources
  • kde-4.14
  • kdelibs
  • kimgio
ras.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE project
2  Copyright (C) 2003 Dominik Seichter <domseichter@web.de>
3  Copyright (C) 2004 Ignacio CastaƱo <castano@ludicon.com>
4  Copyright (C) 2010 Troy Unrau <troy@kde.org>
5 
6  This program is free software; you can redistribute it and/or
7  modify it under the terms of the Lesser GNU General Public
8  License as published by the Free Software Foundation; either
9  version 2 of the License, or (at your option) any later version.
10 */
11 
12 #include "ras.h"
13 
14 #include <QtGui/QImage>
15 #include <QtCore/QDataStream>
16 
17 #include <kdebug.h>
18 
19 namespace { // Private.
20  // format info from http://www.fileformat.info/format/sunraster/egff.htm
21 
22  // Header format of saved files.
23  quint32 rasMagicBigEndian = 0x59a66a95;
24  // quint32 rasMagicLittleEndian = 0x956aa659; # used to support wrong encoded files
25 
26  enum RASType {
27  RAS_TYPE_OLD = 0x0,
28  RAS_TYPE_STANDARD = 0x1,
29  RAS_TYPE_BYTE_ENCODED = 0x2,
30  RAS_TYPE_RGB_FORMAT = 0x3,
31  RAS_TYPE_TIFF_FORMAT = 0x4,
32  RAS_TYPE_IFF_FORMAT = 0x5,
33  RAS_TYPE_EXPERIMENTAL = 0xFFFF
34  };
35 
36  enum RASColorMapType {
37  RAS_COLOR_MAP_TYPE_NONE = 0x0,
38  RAS_COLOR_MAP_TYPE_RGB = 0x1,
39  RAS_COLOR_MAP_TYPE_RAW = 0x2
40  };
41 
42  struct RasHeader {
43  quint32 MagicNumber;
44  quint32 Width;
45  quint32 Height;
46  quint32 Depth;
47  quint32 Length;
48  quint32 Type;
49  quint32 ColorMapType;
50  quint32 ColorMapLength;
51  enum { SIZE = 32 }; // 8 fields of four bytes each
52  };
53 
54  static QDataStream & operator>> ( QDataStream & s, RasHeader & head )
55  {
56  s >> head.MagicNumber;
57  s >> head.Width;
58  s >> head.Height;
59  s >> head.Depth;
60  s >> head.Length;
61  s >> head.Type;
62  s >> head.ColorMapType;
63  s >> head.ColorMapLength;
64  /*qDebug() << "MagicNumber: " << head.MagicNumber
65  << "Width: " << head.Width
66  << "Height: " << head.Height
67  << "Depth: " << head.Depth
68  << "Length: " << head.Length
69  << "Type: " << head.Type
70  << "ColorMapType: " << head.ColorMapType
71  << "ColorMapLength: " << head.ColorMapLength;*/
72  return s;
73  }
74 
75  static bool IsSupported( const RasHeader & head )
76  {
77  // check magic number
78  if ( head.MagicNumber != rasMagicBigEndian) {
79  return false;
80  }
81  // check for an appropriate depth
82  // we support 8bit+palette, 24bit and 32bit ONLY!
83  // TODO: add support for 1bit
84  if ( ! ((head.Depth == 8 && head.ColorMapType == 1)
85  || head.Depth == 24 || head.Depth == 32) ){
86  return false;
87  }
88  // the Type field adds support for RLE(BGR), RGB and other encodings
89  // we support Type 1: Normal(BGR) and Type 3: Normal(RGB) ONLY!
90  // TODO: add support for Type 2: RLE(BGR) & Type 4,5: TIFF/IFF
91  if ( ! (head.Type == 1 || head.Type == 3) ){
92  return false;
93  }
94  // Old files didn't have Length set - reject them for now
95  // TODO: add length recalculation to support old files
96  if ( !head.Length ) {
97  return false;
98  }
99  return true;
100  }
101 
102  static bool LoadRAS( QDataStream & s, const RasHeader & ras, QImage &img )
103  {
104  s.device()->seek(RasHeader::SIZE);
105  // Read palette if needed.
106  QVector<quint8> palette(ras.ColorMapLength);
107  if ( ras.ColorMapType == 1 ) {
108  for (quint32 i = 0; i < ras.ColorMapLength; ++i) { s >> palette[i]; }
109  }
110 
111  // each line must be a factor of 16 bits, so they may contain padding
112  // this will be 1 if padding required, 0 otherwise
113  int paddingrequired = (ras.Width*(ras.Depth/8) % 2);
114 
115  // qDebug() << "paddingrequired: " << paddingrequired;
116  // don't trust ras.Length
117  QVector<quint8> input(ras.Length);
118 
119  int i = 0;
120  while ( ! s.atEnd()) {
121  s >> input[i];
122  // I guess we need to find out if we're at the end of a line
123  if ( paddingrequired && i != 0 && !(i % (ras.Width*(ras.Depth/8))) ) {
124  s >> input[i];
125  }
126  i++;
127  }
128 
129  // Allocate image
130  img = QImage(ras.Width, ras.Height, QImage::Format_ARGB32);
131 
132  // Reconstruct image from RGB palette if we have a palette
133  // TODO: make generic so it works with 24bit or 32bit palettes
134  if ( ras.ColorMapType == 1 && ras.Depth == 8) {
135  quint8 red, green, blue;
136  for ( quint32 y = 0; y < ras.Height; y++ ){
137  for ( quint32 x = 0; x < ras.Width; x++ ) {
138  red = palette[(int)input[y*ras.Width + x]];
139  green = palette[(int)input[y*ras.Width + x] + (ras.ColorMapLength/3)];
140  blue = palette[(int)input[y*ras.Width + x] + 2*(ras.ColorMapLength/3)];
141  img.setPixel(x, y, qRgb(red, green, blue));
142  }
143  }
144 
145  }
146 
147  if ( ras.ColorMapType == 0 && ras.Depth == 24 && (ras.Type == 1 || ras.Type == 2)) {
148  quint8 red, green, blue;
149  for ( quint32 y = 0; y < ras.Height; y++ ){
150  for ( quint32 x = 0; x < ras.Width; x++ ) {
151  red = input[y*3*ras.Width + x*3 + 2];
152  green = input[y*3*ras.Width + x*3 + 1];
153  blue = input[y*3*ras.Width + x*3];
154  img.setPixel(x, y, qRgb(red, green, blue));
155  }
156  }
157  }
158 
159  if ( ras.ColorMapType == 0 && ras.Depth == 24 && ras.Type == 3) {
160  quint8 red, green, blue;
161  for ( quint32 y = 0; y < ras.Height; y++ ){
162  for ( quint32 x = 0; x < ras.Width; x++ ) {
163  red = input[y*3*ras.Width + x*3];
164  green = input[y*3*ras.Width + x*3 + 1];
165  blue = input[y*3*ras.Width + x*3 + 2];
166  img.setPixel(x, y, qRgb(red, green, blue));
167  }
168  }
169  }
170 
171  if ( ras.ColorMapType == 0 && ras.Depth == 32 && (ras.Type == 1 || ras.Type == 2)) {
172  quint8 red, green, blue;
173  for ( quint32 y = 0; y < ras.Height; y++ ){
174  for ( quint32 x = 0; x < ras.Width; x++ ) {
175  red = input[y*4*ras.Width + x*4 + 3];
176  green = input[y*4*ras.Width + x*4 + 2];
177  blue = input[y*4*ras.Width + x*4 + 1];
178  img.setPixel(x, y, qRgb(red, green, blue));
179  }
180  }
181  }
182 
183  if ( ras.ColorMapType == 0 && ras.Depth == 32 && ras.Type == 3 ) {
184  quint8 red, green, blue;
185  for ( quint32 y = 0; y < ras.Height; y++ ){
186  for ( quint32 x = 0; x < ras.Width; x++ ) {
187  red = input[y*4*ras.Width + x*4 + 1];
188  green = input[y*4*ras.Width + x*4 + 2];
189  blue = input[y*4*ras.Width + x*4 + 3];
190  img.setPixel(x, y, qRgb(red, green, blue));
191  }
192  }
193  }
194 
195  return true;
196  }
197 } // namespace
198 
199 RASHandler::RASHandler()
200 {
201 }
202 
203 QByteArray RASHandler::name() const
204 {
205  return "ras";
206 }
207 
208 bool RASHandler::canRead() const
209 {
210  if (canRead(device())) {
211  setFormat("ras");
212  return true;
213  }
214  return false;
215 }
216 
217 bool RASHandler::canRead(QIODevice *device)
218 {
219  if (!device) {
220  qWarning("RASHandler::canRead() called with no device");
221  return false;
222  }
223 
224  if (device->isSequential()) {
225  qWarning("Reading ras files from sequential devices not supported");
226  return false;
227  }
228 
229  qint64 oldPos = device->pos();
230  QByteArray head = device->read(RasHeader::SIZE); // header is exactly 32 bytes, always FIXME
231  int readBytes = head.size(); // this should always be 32 bytes
232 
233  device->seek(oldPos);
234 
235  if (readBytes < RasHeader::SIZE) {
236  return false;
237  }
238 
239  QDataStream stream(head);
240  stream.setByteOrder(QDataStream::BigEndian);
241  RasHeader ras;
242  stream >> ras;
243  return IsSupported(ras);
244 }
245 
246 bool RASHandler::read(QImage *outImage)
247 {
248  QDataStream s( device() );
249  s.setByteOrder( QDataStream::BigEndian );
250 
251  // Read image header.
252  RasHeader ras;
253  s >> ras;
254  // TODO: add support for old versions of RAS where Length may be zero in header
255  s.device()->seek( RasHeader::SIZE + ras.Length + ras.ColorMapLength );
256 
257  // Check image file format. Type 2 is RLE, which causing seeking to be silly.
258  if( !s.atEnd() && ras.Type != 2) {
259  kDebug(399) << "This RAS file is not valid, or an older version of the format.";
260  return false;
261  }
262 
263  // Check supported file types.
264  if( !IsSupported(ras) ) {
265  kDebug(399) << "This RAS file is not supported.";
266  return false;
267  }
268 
269  QImage img;
270  bool result = LoadRAS(s, ras, img);
271 
272  if( result == false ) {
273  kDebug(399) << "Error loading RAS file.";
274  return false;
275  }
276 
277  *outImage = img;
278  return true;
279 }
280 /*
281 bool RASHandler::write(const QImage &image){
282  return false;
283 }*/
284 
285 class RASPlugin : public QImageIOPlugin
286 {
287 public:
288  QStringList keys() const;
289  Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
290  QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
291 };
292 
293 QStringList RASPlugin::keys() const
294 {
295  return QStringList() << "ras" << "RAS";
296 }
297 
298 QImageIOPlugin::Capabilities RASPlugin::capabilities(QIODevice *device, const QByteArray &format) const
299 {
300 
301  if (format == "ras" || format == "RAS")
302  return Capabilities(CanRead);
303 // return Capabilities(CanRead | CanWrite);
304  if (!format.isEmpty())
305  return 0;
306  if (!device->isOpen())
307  return 0;
308 
309  Capabilities cap;
310  if (device->isReadable() && RASHandler::canRead(device))
311  cap |= CanRead;
312  if (device->isWritable())
313  cap |= CanWrite;
314  return cap;
315 }
316 
317 QImageIOHandler *RASPlugin::create(QIODevice *device, const QByteArray &format) const
318 {
319  QImageIOHandler *handler = new RASHandler;
320  handler->setDevice(device);
321  handler->setFormat(format);
322  return handler;
323 }
324 
325 
326 Q_EXPORT_STATIC_PLUGIN(RASPlugin)
327 Q_EXPORT_PLUGIN2(ras, RASPlugin)
QIODevice
QImageIOPlugin::Capabilities
typedef Capabilities
RASType
RASType
Definition: ras.cpp:26
QIODevice::isWritable
bool isWritable() const
QImageIOPlugin::create
virtual QImageIOHandler * create(QIODevice *device, const QByteArray &format) const =0
QImageIOHandler::device
QIODevice * device() const
QIODevice::seek
virtual bool seek(qint64 pos)
QByteArray
QDataStream
QImage::setPixel
void setPixel(int x, int y, uint index_or_rgb)
QByteArray::isEmpty
bool isEmpty() const
RASHandler::name
QByteArray name() const
Definition: ras.cpp:203
QIODevice::isReadable
bool isReadable() const
QIODevice::isSequential
virtual bool isSequential() const
QIODevice::pos
virtual qint64 pos() const
RASHandler::read
bool read(QImage *image)
Definition: ras.cpp:246
operator>>
static QDataStream & operator>>(QDataStream &s, DDSPixelFormat &pf)
Definition: dds.cpp:144
ras.h
RASColorMapType
RASColorMapType
Definition: ras.cpp:36
QImageIOHandler::setDevice
void setDevice(QIODevice *device)
QIODevice::read
qint64 read(char *data, qint64 maxSize)
QIODevice::isOpen
bool isOpen() const
RASHandler::canRead
bool canRead() const
Definition: ras.cpp:208
QImageIOPlugin::capabilities
virtual Capabilities capabilities(QIODevice *device, const QByteArray &format) const =0
QDataStream::atEnd
bool atEnd() const
QImageIOPlugin
QStringList
QImageIOHandler
IsSupported
static bool IsSupported(const DDSHeader &header)
Definition: dds.cpp:276
QImage
QDataStream::setByteOrder
void setByteOrder(ByteOrder bo)
QVector
QImageIOPlugin::keys
virtual QStringList keys() const =0
QImageIOHandler::setFormat
void setFormat(const QByteArray &format)
RASHandler
Definition: ras.h:16
QDataStream::device
QIODevice * device() const
RASHandler::RASHandler
RASHandler()
Definition: ras.cpp:199
QByteArray::size
int size() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:49 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KImgIO

Skip menu "KImgIO"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal