Ein- und Ausgabebibliotheken für Grafikformate?
-
Hi(gh)!
Bislang konnte mein kommandozeilenorientiertes Grafikbearbeitungsprogrämmchen ("yip", "Yadgar's Image Processor") nur unkomprimierte 24-bit-TGA-Files einlesen und erzeugen, was auf die Dauer etwas umständlich ist. Daher will ich jetzt endlich mal die entsprechenden Funktionalitäten für GIF, PNG, JPG und WEBP implementieren... aber auf cppreference.com finde ich nirgendwo einen Link, der auf so etwas wie Grafikbibliotheken hindeutet! Wo müsste ich da suchen?
Mir ist schon klar, das so etwas häufig compilerspezifisch ist, mein Compiler ist der g++ unter Linux... wahrscheinlich sind die Bibliotheken, nach denen ich suche, längst auf meinem System (Debian "Bullseye" 11) installiert - nur, wie heißen sie und wo finde ich sie?
Bis bald im Khyberspace!
Yadgar
-
"Compilerspezifisch" ist das mitnichten, gerade solche Bibliotheken lassen sich meist mit jedem Compiler und für jedes System bauen. Generell verwenden Programme, die mit Grafikformaten umgehen wollen die entsprechenden Referenzbibliotheken oder alternative Implementierungen für das jeweilige Bildformat. Das wären z.B. für die von dir aufgelisteten Formate GIFLIB, libpng, libjpeg oder (glaube mittlerweile populärer) libjpeg-turbo und libwebp.
Die sind ziemlich sicher bereits auf einem Desktop-Linux installiert. Eventuell benötigst du noch die
-dev-Pakete dieser Bibliotheken für Header und andere Dinge, die man braucht, wenn man die in eigenen Programmen verwenden will.Diese Bibliotheken direkt zu verwenden ist wahrscheinlich das, was die meisten Bildverarbeitungsprogramme ebenfalls machen. Damit hast du Zugriff auf alle (auch die exotischeren) Features der Formate. Das bedeutet aber auch, dass du das Laden und Speichern für jedes Format individuell implementieren musst, da jede dieser Bibliotheken eine eigene API verwendet.
Es gibt aber auch Bibliotheken, die das vereinheitlichen. Auf Anhieb fällt mir da nur SDL_image ein, da sollte es aber auch noch etliche andere geben. Die verwenden dann ebenfalls diese Referenzbibliotheken, stellen aber eine einheitliche API zur Verfügung. Eventuell muss man aber ein paar Abstriche bei den unterstützten Funktionalitäten machen. Es ist möglich, dass weniger verbreitete Features wie 12-bit JPEGs oder PNGs mit 16-bit pro Kanal eventuell nicht unterstützt werden.
Sehr populär scheint auch stb zu sein (in Debian als libstb0). Das sieht mir wie eine Header-Only-Bibliothek zu sein die eine Reihe von Bildformaten laden und speichern kann. Offenbar bringt diese Bibliothek eigene Implementierungen der Bildformate mit, so dass es keine Abhängigkeiten zu den Referenzbibliotheken gibt. Die könnte am simpelsten zu verwenden sein.
Ich muss noch anmerken, dass ich selbst nur wenig Erfahrung mit all diesen Bibliotheken habe. Das sind aber die, die ich mir selbst auch ansehen würde, wenn ich eine solche Funktionalität benötige. Ich würde wahrscheinlich die Bibliotheken für die jeweiligen Formate direkt verwenden, da ich Standard/Referenzimplementierungen generell bevorzuge und versuche, Abhängigkeiten gering zu halten (
stbhätte zwar die wenigsten, ist aber eine eigene Implementierung der Formate).
-
Was für ein Framework nutzt Du für die Softwareentwicklung? Je nachdem was Du verwendest, gibt es schon Libraries im Framework, um Pixel Bilder bzw. Vektorbilder zu laden.
-
Hi(gh)!
Sehr populär scheint auch stb zu sein (in Debian als libstb0). Das sieht mir wie eine Header-Only-Bibliothek zu sein die eine Reihe von Bildformaten laden und speichern kann. Offenbar bringt diese Bibliothek eigene Implementierungen der Bildformate mit, so dass es keine Abhängigkeiten zu den Referenzbibliotheken gibt. Die könnte am simpelsten zu verwenden sein.
Ich habe mir jetzt libstb0 und die zugehörige Header-Datei libstb-dev installiert... ein erstes kleines Testprogramm:
// yaigat - Yadgar's Artificial Intelligence Graphics Analysis Tool #include <stdlib.h> #include <iostream> #include <string.h> #include <stb_image.h> using namespace std; int main() { cout << "Test!" << endl; return 0; }wurde leider nicht kompiliert, es gab eine Fehlermeldung:
yaigat.cc:6:10: fatal error: stb_image.h: Datei oder Verzeichnis nicht gefunden
6 | #include <stb_image.h>
| ^~~~~~~~~~~~~Der Header ist laut https://packages.debian.org/bullseye/libstb-dev korrekt - aber in welchem Verzeichnis liegt er lokal?
Bis bald im Khyberspace!
Yadgar
-
Laut deinem eigenem Link sollte das aber
<stb/stb_image.h>sein. Ansonsten: Deine Dateien auf deinem Computer danach durchsuchen?
-
@SeppJ sagte in Ein- und Ausgabebibliotheken für Grafikformate?:
Laut deinem eigenem Link sollte das aber
<stb/stb_image.h>sein. Ansonsten: Deine Dateien auf deinem Computer danach durchsuchen?Ja, ich habe es jetzt gefunden, die Zeile 6 ersetzt durch
#include <stb/stb_image.h>...und weiß seither, dass sämtliche C-Header standardmäßig in /usr/include liegen, die C++-Bibliotheken in /usr/include/C++/10/! Sehr instruktiv, danke für den Tipp!
Bis bald im Khyberspace!
Yadgar
Now playing: Karlheinz Stockhausen: Kontra-Punkte (Ensemble Recherche)
-
@Yadgar sagte in Ein- und Ausgabebibliotheken für Grafikformate?:
Ja, ich habe es jetzt gefunden, die Zeile 6 ersetzt durch
#include <stb/stb_image.h>...und weiß seither, dass sämtliche C-Header standardmäßig in /usr/include liegen, die C++-Bibliotheken in /usr/include/C++/10/! Sehr instruktiv, danke für den Tipp!
Das Wichtige ist nicht
/usr/include, da liegen fast alle systemweiten Header, sondern dass das Paket die Header nach/usr/include/stb/installiert. Compiler auf Linux sind typischerweise so konfiguriert, dass sie standardmäßig/usr/includeals eines der Default-Includeverzeichnisse verwenden. Um von diesem aus/usr/include/stbzu erreichen, muss man natürlich im Quellcode einen relativen Pfadstb/stb_image.hangeben. Mitg++ -v ...bekommst du das auch angezeigt. Da gibt GCC dann am Ende z.B. so was aus:#include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-pc-linux-gnu/16/../../../../include/c++/16 /usr/lib/gcc/x86_64-pc-linux-gnu/16/../../../../include/c++/16/x86_64-pc-linux-gnu /usr/lib/gcc/x86_64-pc-linux-gnu/16/../../../../include/c++/16/backward /usr/lib/gcc/x86_64-pc-linux-gnu/16/include /usr/local/include /usr/include End of search list.Wenn der Compiler also ein relatives
#include <stb/stb_image.h>sieht, dann hängt er das an all diese Verzeichnisse an und nimmt das erste, wo er die Datei findet:/usr/lib/gcc/x86_64-pc-linux-gnu/16/../../../../include/c++/16/stb/stb_image.h /usr/lib/gcc/x86_64-pc-linux-gnu/16/../../../../include/c++/16/x86_64-pc-linux-gnu/stb/stb_image.h /usr/lib/gcc/x86_64-pc-linux-gnu/16/../../../../include/c++/16/backward/stb/stb_image.h /usr/lib/gcc/x86_64-pc-linux-gnu/16/include/stb/stb_image.h /usr/local/include/stb/stb_image.h /usr/include/stb/stb_image.hUnd das letzte Verzeichnis ist genau das, wo das
libstb-dev-Paket den Header installiert hat.So am Rande:
/usr/include/C++/10(ich sehe du verwendest GCC 10
) ist übrigens nicht unbedingt nicht immer das Include-Verzeichnis für die C++-Header. Die werden beim Build von GCC konfiguriert und können z.B. auch relativ zum g++-Program sein, wie bei einer anderen portablen GCC-Toolchain die ich verwende:/toolchains/dlo-toolchain-x86_64-linux-musl/bin/../lib/gcc/i386-dlo-elf/16.2.0/include/c++Das passt sich dann immer an das Verzeichnis an, in dem GCC installiert wurde und ermöglicht, den Compiler auch neben dem System-Compiler in einem beliebigen Verzeichnis zu installieren. System-Compiler (also die, die mit der Distribution kommen) sind aber typischerweise für feste, absolute Include-Verzeichnisse wie
/usr/includekonfiguriert.Das nur am Rande, falls du in Zukunft noch andere nicht gefundene Header debuggen willst. Schau die am besten an, was
gcc -v ...oderg++ -v ...als Include-Verzeichnisse angeben und ob er den Header damit auch finden kann.Natürlich kannst du auch eigene Suchverzeichnisse hinzufügen. Wenn du z.B. mit
g++ -I/usr/include/stbkompilierst, dann funktioniert auch
#include <stb_image.h>. Lass es aber besser bei#include <stb/stb_image.h>. Das ist portabler, weil es nicht den expliziten Include-Pfade erfordert.