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

KImgIO

  • sources
  • kde-4.12
  • kdelibs
  • kimgio
pic_read.cpp
Go to the documentation of this file.
1 
21 /* This code is based on the GIMP-PIC plugin by Halfdan Ingvarsson,
22  * and relicensed from GPL to LGPL to accomodate the KDE licensing policy
23  * with his permission.
24  * These is the original copyright:
25  * Copyright (C) 1998 Halfdan Ingvarsson
26  */
27 
28 #include "pic_rw.h"
29 #include <netinet/in.h>
30 #include <iostream>
31 #include <qimage.h>
32 #include <algorithm>
33 
41 bool picReadHeader(QIODevice *dev, PICHeader *hdr, bool peek) {
42  int result = 0;
43  if (peek) {
44  result = dev->peek((char*) hdr, HEADER_SIZE);
45  } else {
46  result = dev->read((char*) hdr, HEADER_SIZE);
47  }
48 
49  hdr->magic = ntohl(hdr->magic);
50  hdr->width = ntohs(hdr->width);
51  hdr->height = ntohs(hdr->height);
52  hdr->fields = ntohs(hdr->fields);
53 
54  if (hdr->magic != PIC_MAGIC_NUMBER || strncmp(hdr->id, "PICT", 4)) {
55  return false;
56  }
57 
58  return result == HEADER_SIZE;
59 }
60 
61 #define CHANNEL_BYTE(ch, mask) (( ch & mask) ? 1 : 0)
62 
68 static int channels2bpp(char channels) {
69  return CHANNEL_BYTE(channels, RED)
70  + CHANNEL_BYTE(channels, GREEN)
71  + CHANNEL_BYTE(channels, BLUE)
72  + CHANNEL_BYTE(channels, ALPHA);
73 }
74 
81 static bool readChannels(QIODevice *dev, PICChannel *channels, int &bpp) {
82  int c = 0;
83  memset(channels, 0, sizeof ( PICChannel) *8);
84  do {
85  int result = dev->read((char*) & channels[c], CHANNEL_SIZE);
86  if (result != CHANNEL_SIZE) {
87  return false;
88  } else {
89  bpp += channels2bpp(channels[c].channel);
90  c++;
91  }
92  } while (channels[c - 1].chained);
93  return true;
94 }
95 
101 inline static void makeComponentMap(unsigned channel, unsigned char *cmap) {
102  std::fill(cmap, cmap + 8, 0);
103 
104  unsigned compos[] = {ALPHA, BLUE, GREEN, RED};
105  unsigned rgba[] = {3, 2, 1, 0};
106  unsigned pos = 0;
107  for (unsigned compo = 0; compo < 4; compo++) {
108  if (CHANNEL_BYTE(channel, compos[compo])) {
109  cmap[pos++] = rgba[compo];
110  }
111  }
112 }
113 
121 inline static void pic2RGBA(unsigned char *src_pixel, unsigned char *target_pixel, unsigned char *cmap, unsigned components) {
122  for (unsigned i = 0; i < components; i++) {
123  target_pixel[cmap[i]] = src_pixel[i];
124  }
125 }
126 
132 inline static unsigned getNumChannels(PICChannel *channels) {
133  unsigned result = 0;
134  for (unsigned i = 0; i < 8; i++) {
135  if (channels[i].channel != 0) {
136  result++;
137  } else {
138  return result;
139  }
140  }
141  return result;
142 }
143 
152 static int decodeRLE(QIODevice *dev, void *row, unsigned max, unsigned bpp, unsigned channels) {
153  unsigned char buf[512];
154  unsigned *ptr = (unsigned *) row;
155  unsigned char component_map[8];
156  unsigned len = 0;
157 
158  makeComponentMap(channels, component_map);
159 
160  if (dev->read((char*) buf, 1) != 1) {
161  return -1;
162  }
163 
164  /* If last bit is 1, then it is 2 to 127 repetitions */
165  if (buf[0] > 128) {
166  len = buf[0] - 127;
167  if (len > max) {
168  return -1;
169  }
170  unsigned count = dev->read((char*) buf, bpp);
171  if (count != bpp) {
172  return -1;
173  }
174  for (unsigned i = 0; i < len; i++) {
175  pic2RGBA(buf, (unsigned char*) (ptr + i), component_map, bpp);
176  }
177  } /* If the value is exactly 10000000, it means that it is more than 127 repetitions */
178  else if (buf[0] == 128) {
179  unsigned count = dev->read((char*) buf, bpp + 2);
180  if (count != bpp + 2) {
181  return -1;
182  }
183  len = (buf[0] << 8) | buf[1];
184  if (len > max) {
185  return -1;
186  }
187  for (unsigned i = 0; i < len; i++) {
188  pic2RGBA(buf + 2, (unsigned char*) (ptr + i), component_map, bpp);
189  }
190  }
191  else {
192  len = buf[0] + 1;
193  if (len > max) {
194  return -1;
195  }
196  unsigned count = dev->read((char*) buf, len * bpp);
197  if (count != len * bpp) {
198  return -1;
199  }
200  for (unsigned i = 0; i < len; i++) {
201  pic2RGBA(buf + (i * bpp), (unsigned char*) (ptr + i), component_map, bpp);
202  }
203  }
204  return len;
205 }
206 
215 static bool readRow(QIODevice *dev, unsigned *row, unsigned width, PICChannel *channels) {
216  for (int c = 0; channels[c].channel != 0; c++) {
217  unsigned remain = width;
218  unsigned bpp = channels2bpp(channels[c].channel);
219  if (channels[c].type == (int) RLE) {
220  unsigned *rowpos = row;
221  while (remain > 0) {
222  int readed = decodeRLE(dev, rowpos, remain, bpp, channels[c].channel);
223  if (readed < 0) {
224  return false;
225  }
226  remain -= readed;
227  rowpos += readed;
228  }
229  } else {
230  unsigned char component_map[8];
231  unsigned count = dev->read((char*) row, width * bpp);
232  if (count != width * bpp) {
233  return false;
234  }
235 
236  makeComponentMap(channels[c].channel, component_map);
237  for (unsigned i = 0; i < width; i++) {
238  pic2RGBA(((unsigned char*) row) + (i * bpp), (unsigned char*) (row + i), component_map, bpp);
239  }
240  }
241  }
242  return true;
243 }
244 
245 #define FAIL() { \
246  std::cout << "ERROR Reading PIC!" << std::endl; \
247  return; \
248 }
249 
250 bool hasAlpha(PICChannel *channels) {
251  int channel = 0;
252  do {
253  if (CHANNEL_BYTE(channels[channel].channel, ALPHA)) {
254  return true;
255  }
256  channel++;
257  } while (channels[channel - 1].chained);
258  return false;
259 }
260 
264 void pic_read(QIODevice *dev, QImage *result) {
265  PICHeader header;
266  PICChannel channels[8];
267  int bpp = 0;
268  if (!picReadHeader(dev, &header) || !readChannels(dev, channels, bpp)) {
269  FAIL();
270  }
271  QImage img(header.width, header.height, QImage::Format_ARGB32);
272 
273  for (int r = 0; r < header.height; r++) {
274  unsigned *row = (unsigned*) img.scanLine(r);
275  std::fill(row, row + header.width, 0);
276  if (!readRow(dev, row, header.width, channels)) {
277  FAIL();
278  }
279  }
280  // img->setAlphaBuffer(hasAlpha(channels));
281  *result = img;
282 }
pic2RGBA
static void pic2RGBA(unsigned char *src_pixel, unsigned char *target_pixel, unsigned char *cmap, unsigned components)
Converts a PIC pixel to 32bits RGBA.
Definition: pic_read.cpp:121
pic_rw.h
FAIL
#define FAIL()
Definition: pic_read.cpp:245
picReadHeader
bool picReadHeader(QIODevice *dev, PICHeader *hdr, bool peek)
PIC_RW - Qt PIC Support Copyright (C) 2007 Ruben Lopez r.lopez@bren.es
Definition: pic_read.cpp:41
PICChannel
PIC channel header.
Definition: pic_rw.h:83
channels2bpp
static int channels2bpp(char channels)
Gets the channels definition and returns the number of bytes per pixel.
Definition: pic_read.cpp:68
PICHeader
PIC format header.
Definition: pic_rw.h:68
PICHeader::magic
qint32 magic
Definition: pic_rw.h:69
readRow
static bool readRow(QIODevice *dev, unsigned *row, unsigned width, PICChannel *channels)
Reads a row from the file.
Definition: pic_read.cpp:215
hasAlpha
bool hasAlpha(PICChannel *channels)
Definition: pic_read.cpp:250
makeComponentMap
static void makeComponentMap(unsigned channel, unsigned char *cmap)
Makes a component map based on the channels info.
Definition: pic_read.cpp:101
PIC_MAGIC_NUMBER
#define PIC_MAGIC_NUMBER
PIC_RW - Qt PIC Support Copyright (C) 2007 Ruben Lopez r.lopez@bren.es
Definition: pic_rw.h:31
pic_read
void pic_read(QIODevice *dev, QImage *result)
KDE image reading function.
Definition: pic_read.cpp:264
PICChannel::channel
char channel
Definition: pic_rw.h:87
PICHeader::id
char id[4]
Definition: pic_rw.h:72
RLE
Definition: pic_rw.h:52
HEADER_SIZE
#define HEADER_SIZE
Definition: pic_rw.h:90
PICHeader::fields
qint16 fields
Definition: pic_rw.h:76
readChannels
static bool readChannels(QIODevice *dev, PICChannel *channels, int &bpp)
Reads the channels info.
Definition: pic_read.cpp:81
BLUE
Definition: pic_rw.h:61
CHANNEL_SIZE
#define CHANNEL_SIZE
Definition: pic_rw.h:91
GREEN
Definition: pic_rw.h:60
PICHeader::height
qint16 height
Definition: pic_rw.h:74
getNumChannels
static unsigned getNumChannels(PICChannel *channels)
Counts the number of channels in the PICChannel header.
Definition: pic_read.cpp:132
CHANNEL_BYTE
#define CHANNEL_BYTE(ch, mask)
Definition: pic_read.cpp:61
ALPHA
Definition: pic_rw.h:62
RED
Definition: pic_rw.h:59
decodeRLE
static int decodeRLE(QIODevice *dev, void *row, unsigned max, unsigned bpp, unsigned channels)
Decodes a Run-lenght encoded chunk.
Definition: pic_read.cpp:152
PICHeader::width
qint16 width
Definition: pic_rw.h:73
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:47:50 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
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • 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