📄 qxpmhandler.cpp
字号:
{ QByteArray buf(200, 0); if (!read_xpm_string(buf, device, source, index, state)) return false;#if defined(_MSC_VER) && _MSC_VER >= 1400 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;}// Reads XPM body (color information & pixels).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 > 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.setNumColors(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; } } } 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; } } } 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;}//// INTERNAL//// Reads an .xpm from either the QImageIO or from the QString *.// One of the two HAS to be 0, the other one is used.//bool qt_read_xpm_image_or_array(QIODevice *device, const char * const * source, QImage &image){ if (!source) return true; QByteArray buf(200, 0); QByteArray state; int cpp, ncols, w, h, index = 0; if (device) { // "/* XPM */" int readBytes; if ((readBytes = device->readLine(buf.data(), buf.size())) < 0) return false; if (buf.indexOf("/* XPM") != 0) { while (readBytes > 0) { device->ungetChar(buf.at(readBytes - 1)); --readBytes; } return false; }// bad magic } if (!read_xpm_header(device, source, index, state, &cpp, &ncols, &w, &h)) return false; return read_xpm_body(device, source, index, state, cpp, ncols, w, h, image);}static const char* xpm_color_name(int cpp, int index){ static char returnable[5]; static const char code[] = ".#abcdefghijklmnopqrstuvwxyzABCD" "EFGHIJKLMNOPQRSTUVWXYZ0123456789"; // cpp is limited to 4 and index is limited to 64^cpp if (cpp > 1) { if (cpp > 2) { if (cpp > 3) { returnable[3] = code[index % 64]; index /= 64; } else returnable[3] = '\0'; returnable[2] = code[index % 64]; index /= 64; } else returnable[2] = '\0'; // the following 4 lines are a joke! if (index == 0) index = 64*44+21; else if (index == 64*44+21) index = 0; returnable[1] = code[index % 64]; index /= 64; } else returnable[1] = '\0'; returnable[0] = code[index]; return returnable;}// write XPM image datastatic bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const QString &fileName){ if (!device->isWritable()) return false; QImage image; if (sourceImage.depth() != 32) image = sourceImage.convertToFormat(QImage::Format_RGB32); else image = sourceImage; QMap<QRgb, int> colorMap; int w = image.width(), h = image.height(), ncolors = 0; int x, y; // build color table for(y=0; y<h; y++) { QRgb * yp = (QRgb *)image.scanLine(y); for(x=0; x<w; x++) { QRgb color = *(yp + x); if (!colorMap.contains(color)) colorMap.insert(color, ncolors++); } } // number of 64-bit characters per pixel needed to encode all colors int cpp = 1; for (int k = 64; ncolors > k; k *= 64) { ++cpp; // limit to 4 characters per pixel // 64^4 colors is enough for a 4096x4096 image if (cpp > 4) break; } QString line; // write header QTextStream s(device); s << "/* XPM */" << endl << "static char *" << fbname(fileName) << "[]={" << endl << "\"" << w << " " << h << " " << ncolors << " " << cpp << "\""; // write palette QMap<QRgb, int>::Iterator c = colorMap.begin(); while (c != colorMap.end()) { QRgb color = c.key(); if (image.format() != QImage::Format_RGB32 && !qAlpha(color)) line.sprintf("\"%s c None\"", xpm_color_name(cpp, *c)); else line.sprintf("\"%s c #%02x%02x%02x\"", xpm_color_name(cpp, *c), qRed(color), qGreen(color), qBlue(color)); ++c; s << "," << endl << line; } // write pixels, limit to 4 characters per pixel line.truncate(cpp*w); for(y=0; y<h; y++) { QRgb * yp = (QRgb *) image.scanLine(y); int cc = 0; for(x=0; x<w; x++) { int color = (int)(*(yp + x)); QByteArray chars(xpm_color_name(cpp, colorMap[color])); line[cc++] = QLatin1Char(chars[0]); if (cpp > 1) { line[cc++] = QLatin1Char(chars[1]); if (cpp > 2) { line[cc++] = QLatin1Char(chars[2]); if (cpp > 3) { line[cc++] = QLatin1Char(chars[3]); } } } } s << "," << endl << "\"" << line << "\""; } s << "};" << endl; return (s.status() == QTextStream::Ok);}QXpmHandler::QXpmHandler() : state(Ready), index(0){}bool QXpmHandler::readHeader(){ state = Error; if (!read_xpm_header(device(), 0, index, buffer, &cpp, &ncols, &width, &height)) return false; state = ReadHeader; return true;}bool QXpmHandler::readImage(QImage *image){ if (state == Error) return false; if (state == Ready && !readHeader()) { state = Error; return false; } if (!read_xpm_body(device(), 0, index, buffer, cpp, ncols, width, height, *image)) { state = Error; return false; } state = Ready; return true;}bool QXpmHandler::canRead() const{ if (state == Ready && canRead(device())) { setFormat("xpm"); return true; } return state != Error;}bool QXpmHandler::canRead(QIODevice *device){ if (!device) { qWarning("QXpmHandler::canRead() called with no device"); return false; } char head[6]; if (device->peek(head, sizeof(head)) != sizeof(head)) return false; return qstrncmp(head, "/* XPM", 6) == 0;}bool QXpmHandler::read(QImage *image){ if (!canRead()) return false; return readImage(image);}bool QXpmHandler::write(const QImage &image){ return write_xpm_image(image, device(), fileName);}bool QXpmHandler::supportsOption(ImageOption option) const{ return option == Name || option == Size;}QVariant QXpmHandler::option(ImageOption option) const{ if (option == Name) { return fileName; } else if (option == Size) { if (state == Error) return QVariant(); if (state == Ready && !const_cast<QXpmHandler*>(this)->readHeader()) return QVariant(); return QSize(width, height); } return QVariant();}void QXpmHandler::setOption(ImageOption option, const QVariant &value){ if (option == Name) fileName = value.toString();}QByteArray QXpmHandler::name() const{ return "xpm";}#endif // QT_NO_IMAGEFORMAT_XPM
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -