2016-11-26 3 views
0

einen Satz von 80 Symbolen in QML als nicht-sichtbaren Bilder importieren, um für Shader-Quellen verwendet werden (für beliebiges Einfärben):Rastern QML SVG Bild in alpha8 Format

property Image action: Image { sourceSize.width: 512; sourceSize.height: 512; source: "icons/action.svg"; mipmap: true; antialiasing: true } 
    // 79 more of those 

ich feststellen, dass mein Speicherverbrauch sprunghaft angestiegen , von 45 mb bis 128 mb, ein whooping ~ 185% zu erhöhen, das ist 83 extra mb für die 80 Symbole.

Es wurde erwartet, immerhin 512 * 512 * 4/1024/1024 für genau 1 MB Speicher macht. Diese Kosten sind jedoch nicht akzeptabel, insbesondere im Hinblick auf das Targeting von Mobiltelefonen mit der App.

Ich konnte die Rasterungsgröße reduzieren, jedoch möchte ich die Symbole schön und knackig sein. Die Größe des Symbols hängt von der Anzeige des Geräts ab, für eine optimale Benutzererfahrung muss es jedoch ungefähr einen Zoll groß sein. Angesichts der Tatsache, dass die meisten neuen High-End-Telefone bereits über 500 dpi drücken, würde ich es wirklich hassen, die Symbole nach unten zu skalieren und sie unscharf erscheinen zu lassen.

Da die SVGs sollen in beliebigen Farben koloriert werden, sind sie in der Tat einfach Masken alpha, was bedeutet, dass alles, was ich wirklich brauchen, ist eine dieser vier Kanäle. Leider scheint QMLs Image keine Art von Kontrolle zu bieten, das SVG wird zu einem RGBA-Bild gerastert.

Und in der Tat, wenn ich

QVector<QImage> imgs; 
    imgs.reserve(80); 
    QDirIterator it(":/icons", QDirIterator::Subdirectories); 
    while (it.hasNext()) { 
     QSvgRenderer renderer (it.next()); 
     QImage ic(512, 512, QImage::Format_Alpha8); 
     ic.fill(Qt::transparent); 
     QPainter pp(&ic); 
     renderer.render(&pp); 
     imgs.append(ic); 
    } 

ich den erwarteten bescheidenen 20 mb Anstieg der Speichernutzung erhalten.

Irgendwelche Ideen, wie auf einigen Speicherplatz zu sparen?

+0

Wenn Sie die Anzeigegrößen nicht ändern müssen, können Sie dies in C++ tun und die resultierenden Bilder/Bitmaps zwischenspeichern. Je nach Plattform ist dies möglicherweise sogar zur Installationszeit möglich. –

+0

Die Bilder wurden für einen qml 'ShaderEffect' benötigt, ich habe nicht getestet, ob es direkt mit' QImage' funktioniert, aber ich wäre überrascht, wenn es qmls Designentscheidungen trifft und der Mangel an eingebauter Interoperabilität zwischen qml's 'Image' und' QImage'. – dtech

+0

Interessant, ich hätte angenommen, dass es funktioniert, wenn man bedenkt, dass 'QImage' der wichtigste C++ - Typ für Pixeldatenbilder ist und daher auch vom QQuick' Image'-Element verwendet wird. –

Antwort

0

2 Stunden später - gute Nachrichten, in erster Linie, eine benutzerdefinierte QQuickImageProvider funktioniert out of the box mit QImage::Format_Alpha8, keine Probleme gibt es. Unnötige Kanäle werden eliminiert.

Aber noch wichtiger, ich erkannte, dass die Symbole sich sehr gut für die Darstellung von Distanzfeldern eignen. So verwende ich jetzt 128x128 SDF Texturen, die schön skaliert bis weit über 512x512, die Speichernutzung für die Symbole auf den schlappen 1,25 mb, für insgesamt 64x Reduzierung der RAM-Auslastung im Vergleich zu der ersten Implementierung zu reduzieren.

Der einzige Nachteil ist die 3-4 Sekunden (auf einem Note 3 Telefon) zusätzlichen Start, weil die Entfernung Felder beim Start berechnet werden, aber es gibt auch Abhilfemaßnahmen dafür, ich könnte zu vorberechneten SDFs oder wechseln Offload wenn zu Shadern, was ein wenig komplexer wäre, sollte aber die Zeit mindestens 5-fach reduzieren.