static bool read_xpm_header( QIODevice *device, const char * const * source, int& index, QByteArray &state, int *cpp, int *ncols, int *w, int *h) { QByteArray buf(200, 0); if (!read_xpm_string(buf, device, source, index, state)) return false; if (sscanf(buf, "%d %d %d %d", w, h, ncols, cpp) < 4) return false; // < 4 numbers parsed return true; }
static bool read_xpm_header( QIODevice *device, const char * const * source, int& index, QByteArray &state, int *cpp, int *ncols, int *w, int *h) { QByteArray buf(200, 0); if (!read_xpm_string(buf, device, source, index, state)) return false; #if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_OS_WINCE) if (sscanf_s(buf, "%d %d %d %d", w, h, ncols, cpp) < 4) #else if (sscanf(buf, "%d %d %d %d", w, h, ncols, cpp) < 4) #endif return false; // < 4 numbers parsed return true; }
static bool read_xpm_body( QIODevice *device, const char * const * source, int& index, QByteArray& state, int cpp, int ncols, int w, int h, QImage& image) { QByteArray buf(200, 0); int i; if (cpp < 0 || cpp > 15) return false; // For > 256 colors, we delay creation of the image until // after we have read the color specifications, so that we can // create it in correct format (Format_RGB32 vs Format_ARGB32, // depending on absence or presence of "c none", respectively) if (ncols <= 256) { if (image.size() != QSize(w, h) || image.format() != QImage::Format_Indexed8) { image = QImage(w, h, QImage::Format_Indexed8); if (image.isNull()) return false; } image.setColorCount(ncols); } QMap<quint64, int> colorMap; int currentColor; bool hasTransparency = false; for(currentColor=0; currentColor < ncols; ++currentColor) { if (!read_xpm_string(buf, device, source, index, state)) { qWarning("QImage: XPM color specification missing"); return false; } QByteArray index; index = buf.left(cpp); buf = buf.mid(cpp).simplified().trimmed().toLower(); QList<QByteArray> tokens = buf.split(' '); i = tokens.indexOf("c"); if (i < 0) i = tokens.indexOf("g"); if (i < 0) i = tokens.indexOf("g4"); if (i < 0) i = tokens.indexOf("m"); if (i < 0) { qWarning("QImage: XPM color specification is missing: %s", buf.constData()); return false; // no c/g/g4/m specification at all } QByteArray color; while ((++i < tokens.size()) && !is_xpm_color_spec_prefix(tokens.at(i))) { color.append(tokens.at(i)); } if (color.isEmpty()) { qWarning("QImage: XPM color value is missing from specification: %s", buf.constData()); return false; // no color value } buf = color; if (buf == "none") { hasTransparency = true; int transparentColor = currentColor; if (ncols <= 256) { image.setColor(transparentColor, 0); colorMap.insert(xpmHash(QLatin1String(index.constData())), transparentColor); } else { colorMap.insert(xpmHash(QLatin1String(index.constData())), 0); } } else { QRgb c_rgb; if (((buf.length()-1) % 3) && (buf[0] == '#')) { buf.truncate(((buf.length()-1) / 4 * 3) + 1); // remove alpha channel left by imagemagick } if (buf[0] == '#') { qt_get_hex_rgb(buf, &c_rgb); } else { qt_get_named_xpm_rgb(buf, &c_rgb); } if (ncols <= 256) { image.setColor(currentColor, 0xff000000 | c_rgb); colorMap.insert(xpmHash(QLatin1String(index.constData())), currentColor); } else { colorMap.insert(xpmHash(QLatin1String(index.constData())), 0xff000000 | c_rgb); } } } if (ncols > 256) { // Now we can create 32-bit image of appropriate format QImage::Format format = hasTransparency ? QImage::Format_ARGB32 : QImage::Format_RGB32; if (image.size() != QSize(w, h) || image.format() != format) { image = QImage(w, h, format); if (image.isNull()) return false; } } // Read pixels for(int y=0; y<h; y++) { if (!read_xpm_string(buf, device, source, index, state)) { qWarning("QImage: XPM pixels missing on image line %d", y); return false; } if (image.depth() == 8) { uchar *p = image.scanLine(y); uchar *d = (uchar *)buf.data(); uchar *end = d + buf.length(); int x; if (cpp == 1) { char b[2]; b[1] = '\0'; for (x=0; x<w && d<end; x++) { b[0] = *d++; *p++ = (uchar)colorMap[xpmHash(b)]; } } else { char b[16]; b[cpp] = '\0'; for (x=0; x<w && d<end; x++) { memcpy(b, (char *)d, cpp); *p++ = (uchar)colorMap[xpmHash(b)]; d += cpp; } } // avoid uninitialized memory for malformed xpms if (x < w) { qWarning("QImage: XPM pixels missing on image line %d (possibly a C++ trigraph).", y); memset(p, 0, w - x); } } else { QRgb *p = (QRgb*)image.scanLine(y); uchar *d = (uchar *)buf.data(); uchar *end = d + buf.length(); int x; char b[16]; b[cpp] = '\0'; for (x=0; x<w && d<end; x++) { memcpy(b, (char *)d, cpp); *p++ = (QRgb)colorMap[xpmHash(b)]; d += cpp; } // avoid uninitialized memory for malformed xpms if (x < w) { qWarning("QImage: XPM pixels missing on image line %d (possibly a C++ trigraph).", y); memset(p, 0, (w - x)*4); } } } if (device) { // Rewind unused characters, and skip to the end of the XPM struct. for (int i = state.size() - 1; i >= 0; --i) device->ungetChar(state[i]); char c; while (device->getChar(&c) && c != ';') {} while (device->getChar(&c) && c != '\n') {} } return true; }