Wir starten eine neue Version von ImageMagick
Bei Transloadit möchten wir Ihnen das bestmögliche Encoding-Erlebnis bieten, und einer der wichtigsten Faktoren dabei ist, dass wir stets die neuesten Encoding-Werkzeuge einsetzen.
Es ist kein Geheimnis, dass wir dabei stark auf Open-Source-Technologie setzen. Deshalb geben wir bewusst etwas an die Giganten zurück, auf deren Schultern wir stehen, etwa indem wir dem ImageMagick-Projekt kostenlose Hardware zur Verfügung stellen.
Obwohl wir eine enge Beziehung zu dem Projekt pflegen, hat es sich für uns als sehr problematisch erwiesen, unseren Stack zu modernisieren.
Die „spaßigen“ Seiten der Wartung von Encoding-Software
Häufig verlassen sich unsere Kunden auf das Verhalten der alten Version (sogar auf deren Fehler,
aber dazu später mehr), sodass ein „einfaches Upgrade“ - das wir vor einigen Jahren naiv versucht
haben - ihre Arbeitsabläufe zerstört. Um auch zwischen
Betriebssystem-Upgrades (English) ein konsistentes Erlebnis bieten zu können,
müssen wir ImageMagick und alle seine 31 Abhängigkeiten selbst kompilieren. Ja, 31, denn durch das
Hinzufügen von Bibliotheken wie pixman,
pango und ufraw unterstützen wir 131 Formate mehr, als unter Ubuntu
standardmäßig mit apt-get install imagemagick zur Verfügung stehen. Und indem wir Bibliotheken
bis hinunter zu zlib einbinden, schützen wir uns außerdem vor Brüchen der Abwärtskompatibilität,
die durch Betriebssystem-Upgrades entstehen könnten. So bleiben unsere Encoding-Funktionen die
verlässliche Konstante, auf der unsere Kunden ihr Geschäft aufbauen können.
Neben der umfangreichen Formatunterstützung und dieser garantierten Kontinuität hat das Kompilieren den Vorteil, dass sich damit eine statische Binärdatei erzeugen lässt. Das ist eine einzelne ausführbare Datei, in die jede Abhängigkeit fest eingebacken ist. Dadurch lassen sich sehr unterschiedliche Versionen derselben Software problemlos und ohne Konflikte nebeneinander betreiben, was unseren Kunden einen Upgrade-Pfad auf Opt-in-Basis bietet. Genau so stellen wir auch Upgrades für unsere Video-Encoding-Software (English) bereit.
Das Problem, das wir nun jedoch beim Upgrade unseres Image-Stacks haben, ist, dass das Kompilieren von ImageMagick und seinen 31 Abhängigkeiten zwei Stunden dauern würde, und das unter perfekten Bedingungen auf einem leistungsstarken Server. Wenn eine bestimmte Bibliotheksversion mit einer anderen in Konflikt gerät, merken Sie das unter Umständen erst nach 90 Minuten, und danach müssen Sie sich eine mögliche Lösung überlegen und alles noch einmal von vorn versuchen. Das lässt sich kaum als praktikabel oder wartbar bezeichnen, und mit der Agilität, die wir uns für unsere Entwicklung wünschen, hat es schon gar nichts zu tun.
Die Einführung von Docker-Containern würde, so dachten wir, einen Teil
dieser Mühen lösen: Zumindest könnten wir verschiedene Versionen leichter nebeneinander betreiben
und unsere Build-Zeiten durch den Einsatz von Layern beschleunigen. Außerdem müssten wir nicht mehr
einzelne riesige Binärdateien neu kompilieren, sondern bei Bedarf nur eine einzelne Shared Library.
Unsere anfängliche Freude wurde gedämpft, als wir feststellten, dass es keine Möglichkeit gab,
Container ohne gefährliche Systemrechte zu starten. Das bedeutete, dass wir entweder Container
dauerhaft laufen lassen und unseren nicht privilegierten API-Benutzer Befehle dorthin weiterleiten
lassen mussten, oder dass wir diesem Benutzer das Recht zum Starten von Containern einräumen
mussten. Beide Optionen waren, gelinde gesagt, nicht großartig. Das Weiterleiten wäre recht fragil,
und mit der Vergabe solcher Rechte könnte ein Angreifer theoretisch jedes Verzeichnis der
Host-Maschine als --volume in den Container einhängen und dann nach Belieben lesen, schreiben und
löschen. Später erfuhren wir auch von der Arbeit im runC-Projekt,
Container ohne Root-Zugriff zu starten (und wir werden diesen Weg
künftig wahrscheinlich einschlagen), doch sie war noch nicht so ausgereift, wie wir es brauchten.
Wir haben auch erwogen, für die neue Version einen separaten Cluster zu betreiben, doch das hätte erhebliche Kosten in Form zusätzlicher Hardware, Wartung und betrieblichem Aufwand verursacht.
Wir haben uns in all diese Richtungen tief eingearbeitet, mussten aber jedes Mal wieder umkehren, weil es gravierende Nachteile gab. Wie soll die Zukunft unserer Stack-Wartung aussehen? Welche Lösung ist zugleich zuverlässig und ausgereift genug, um uns garantierte Kontinuität zu bieten und dabei unsere Agilität zu erhalten?
Nix
Schon lange hatten wir auch Nix als mögliche Lösung im Blick. Wir bauen unsere Software mit einem einfachen Compile-Framework namens depmake, das Felix 2012 geschrieben hat und das bereits einige der grundlegenden Ideen und Eigenschaften von Nix umsetzte. Es funktioniert seit all diesen Jahren sehr gut für uns, doch Nix führt diese und weitere Konzepte deutlich weiter.
Nix ist eine funktionale Programmiersprache, mit der Sie deklarativ definieren, wie Software gebaut wird. Dank eines globalen Caches müssen Sie nur das kompilieren, was in Ihrer Umgebung einzigartig ist; in vielen Fällen können Sie die fertige Software einfach direkt aus diesem Cache ziehen. Das kann die Build-Zeiten enorm verbessern, aus dem einfachen Grund, dass gar nicht gebaut wird *Handbewegung* 👋
Nach einigem Lernen und Experimentieren haben wir herausgefunden, wie Nix und depmake koexistieren können, sodass wir das Neue nutzen können, ohne das Alte wegzuwerfen.
Zukunft
Der Einsatz von Nix öffnet die Schleusen für potenziell neue Software und macht es uns extrem leicht, einen neuen Stack auszurollen, ihn anzupassen, sicherzustellen, dass er für immer auf die gleiche Weise funktioniert, und mehrere Versionen derselben Software nebeneinander bestehen zu lassen.
Der Großteil der Arbeit, unseren Kunden einen neuen Stack bereitzustellen, hat sich nun vom Bauen zum Testen verlagert, was eine große Verbesserung ist.
Wir erwägen weiterhin, unsere mit Nix gebaute Software in Container zu verpacken und diese ohne Root-Rechte zu betreiben, doch das würde vor allem dazu dienen, zusätzliche Sicherheit über die bereits vorhandene Isolierung hinaus zu bieten.
Werden wir unsere alten Versionen jemals abkündigen? Ja. Aber wir tun das mit recht langen Übergangsfristen, in denen wir die Nutzerinnen und Nutzer sanft zur neuen Version hinführen.
Ohne weitere Umschweife.. Version zwei!
Wir sind ziemlich stolz, Ihnen unseren neuen ImageMagick-Stack mit dem Kürzel v2.0.3 vorzustellen
(kein SemVer, jede Änderung kann potenziell die Abwärtskompatibilität brechen). Er befindet sich
bereits seit zwei Wochen in der Private Beta und geht nun in die Public Beta. Er basiert auf der
neuesten ImageMagick-Version, die Nix bereitstellt, jedoch mit eigenen Ergänzungen wie libraw, damit
unsere Kunden weiterhin diese 131 zusätzlichen Formate nutzen können.
Neben RAW und allen anderen Formaten, die wir bereits unterstützen, wird es unsere Kunden freuen, dass der neue Stack sowohl das WebP- als auch das DjVu-Format unterstützt.
Wir haben unsere Seite mit den unterstützten Formaten aktualisiert, damit Sie Unterschiede zwischen unseren Stack-Versionen leichter erkennen können. Der Screenshot unten zeigt die Vergleichsfunktionen zum Zeitpunkt dieses Releases.

Der Einfachheit halber hier die vollständigen Listen:
Neu hinzugekommene Leseunterstützung: 3FR, 3G2, 3GP, CANVAS, CLIP (zuvor nur Schreiben), FILE, FTP, HALD, HTTP, IIQ, JNX, MAC, MEF, NRW, PES, RAW, RMF, RW2, SCREENSHOT, WMF, WMZ.
Neu hinzugekommene Schreibunterstützung: BRF, DDS (zuvor nur Lesen), INLINE (zuvor nur Lesen), ISOBRL, ISOBRL6, JSON, SPARSE, UBRL, UBRL6
Neu hinzugekommene Lese- und Schreibunterstützung: AAI, BGRA, BGRO, CAL, CALS, DXT1, DXT5, G4, GROUP4, HDR, JPE, JPS, MASK, MKV, PNG00, PNG48, PNG64, PSB, RGF, SIX, SIXEL, TIFF64, VIPS, WEBP
Neben mehr Formaten aktiviert unsere neue ImageMagick-Version standardmäßig auch HDRI (High Dynamic Range Imaging), sodass Sie genauere Ergebnisse bei der Bildverarbeitung erwarten können.
Abgesehen von diesen für Kunden sichtbaren Verbesserungen freuen wir uns sehr darüber, dass die neue Version auch einige betriebliche Vorteile für uns bringt, etwa das Schließen einer Reihe von Sicherheitslücken (English), Speicherlecks und so weiter.
Nennenswerte inkompatible Änderungen
Unsere frühere ImageMagick-Version hatte einen Fehler in der Farbraumbehandlung, der zu dunkleren Bildern und zu einer falschen Angabe von sRGB gegenüber RGB führte. Das ist nun behoben. Wenn Sie jedoch einen Weg gefunden haben, diesen Fehler zu umgehen, verlassen Sie sich im Grunde darauf und müssen Ihre Kompensation wieder zurücknehmen, wenn Sie das Upgrade durchführen.
Wir unterstützen das Lesen von PGX- und JPX-Dateien nicht mehr, und für die Formate: BRG, GBR, GRB und RBG wird nun empfohlen, ein RGB-Format zu erzeugen und anschließend die Kanäle zu tauschen.
Zur Referenz finden Sie am Ende dieses Beitrags ein vollständiges Changelog.
Upgrade
Dieser Abschnitt beschreibt das Release von 2017. Der Stack
v2.0.3wurde 2019 abgekündigt (English). Nutzen Sie für eine neue Integration den Stack, der in der aktuellen /image/resize-Dokumentation empfohlen wird.
Transloadit empfiehlt, den neuen ImageMagick-Stack zunächst für Tests und unkritische Workloads
einzusetzen. Fügen Sie dazu imagemagick_stack: "v2.0.3" zu Ihrem
Step mit dem Robot /image/resize hinzu.
Wir entschuldigen uns, dass dieses Upgrade so lange gedauert hat. Dank unserer neuen Art, den Stack zu hüten, können Sie künftig deutlich pünktlichere Updates erwarten! 😄
Wir würden gerne von Ihren Erfahrungen hören: Sagen Sie uns über die bekannte Sprechblase auf unserer Website, was Sie denken!
Changelog
Zur Referenz hier das vollständige Changelog:
- Zusätzliche Prüfungen im DCM-Reader ergänzt, um datengetriebene Fehler zu verhindern (Fehlerbericht von Hanno Böck)
- Am Ende der sigmoidalen Colormap-Schleife
ClampToQuantumergänzt - Unterstützung für Sprachen ergänzt, die ein komplexes Textlayout erfordern (Referenz)
- tanh/atanh-Klon der alten sigmoidalen Map ergänzt (schneller und genauer)
- Define
psd:additional-infoergänzt, um die zusätzlichen Informationen in einer PSD-Datei zu erhalten - Define
psd:preserve-opacity-maskergänzt, um die Deckkraftmaske in einer PSD-Datei zu erhalten - RLE-Komprimierung von Ebenen zum PSD-Encoder ergänzt
- RLE-Komprimierung von Ebenen zum PSD-Encoder ergänzt
- Unterstützung für GROUP4-Komprimierung zum FAX-Coder ergänzt
- Unterstützung für RGB555, RGB565, ARGB4444 und ARGB1555 zum BMP-Encoder ergänzt (Referenz)
- Verwendung von set und Escapes erlaubt, wenn keine Bilder im Speicher sind (sofern Sie nicht auf
bildspezifische Metadaten zugreifen). Derzeit sind
%[fx:...]und%[pixel:...]nicht enthalten - Debian-Patches angewendet (Referenz)
- Epsilon für endliche Genauigkeit zurückgenommen (Referenz)
- Shared-Object-Version (SO) von Magick++ erhöht. Zuvor hatte ein globales Ersetzen
matteColorinalphaColorgeändert - Geobezogene EXIF-Metadaten können wieder gelesen werden (Referenz)
- Prüfung auf Pufferüberlauf in
magick/draw.c/DrawStrokePolygon() - Path Traversal im Coder ist nicht zulässig (Fehlerbericht von Masaaki Chida)
- coders/png.c: Unterstützung für einen vorgeschlagenen neuen PNG-Chunk ergänzt (exIf lesen und schreiben, eXIf nur lesen), der derzeit auf der Mailingliste png-mng-misc at lists.sourceforge.net diskutiert wird
- coders/png.c: Unterstützung für einen vorgeschlagenen neuen PNG-Chunk ergänzt (zxIf, nur lesen),
der derzeit auf der Mailingliste png-mng-misc at lists.sourceforge.net diskutiert wird. Aktivieren
Sie exIf und zxIf mit
CPPFLAGS="-DexIf_SUPPORTED -DxzIf_SUPPORTED"Wenn exIf aktiviert ist, wird nur der unkomprimierte exIF-Chunk geschrieben, und der hex-codierte zTXt-Chunk mit dem rohen Exif-Profil wird nicht geschrieben. - Numerische Instabilität korrigiert (Referenz)
- Korrektur am Composite-Operator
Over(Referenz) - Die Maske
CompositeChannelsaufRed,Green,Blue,AlphaundBlackdefiniert - Indirekte Lesezugriffe per Policy verweigert; entfernen Sie die Policy, um sie zuzulassen, z. B.
convert caption:@mytext.txt - Distort konvertiert Bilder vom Typ
grayscalenicht mehr nachsRGB(Referenz) - Pfad bei runden Linienverbindungen nicht mehr schließen (Referenz)
- Verhaltensänderung in der Sicherheitsrichtlinie dokumentiert (Dank an yoya)
- Argumente der Option
-fxnicht mehr interpretieren (Referenz) - Für
QueryMultilineFontMetrics()keine Bounding-Box mit Nullwerten mehr zurückgeben (Referenz) - Für transparente gekachelte Bilder keinen Hintergrund mehr setzen (Referenz)
- Das Update-Trait nicht mehr für den Alphakanal setzen (private E-Mail zur Option
-levels-colors) - Pixel-Cache in
AcquireAuthenticCacheView()nicht mehr synchronisieren (Fehlerbericht von Hanno Böck) - Compiler-Warnung beseitigt
- Alphakanal aktivieren, wenn die Hintergrundfarbe nicht deckend ist (Referenz)
- Lazy-Pixel-Cache-Morphologie auswerten, um einen Pufferüberlauf zu verhindern (Fehlerbericht von Ibrahim M. El-Sayed)
- Kompilierfehler in
opencl.cbehoben (Referenz) - Zeichenfehler bei Strichbreiten größer als 2 behoben (Referenz)
- Korrektur für mögliche Sicherheitslücken (Referenz)
- Off-by-one-Fehler in
GetNextToken()behoben - Speicherleck im MPC-Format behoben
- MVG-stroke-opacity behoben (Referenz)
- Regression beim Pixel-Cache auf der Festplatte behoben (Referenz)
- Möglichen Pufferüberlauf beim Schreiben komprimierter TIFFS behoben (Schwachstellenbericht von Cisco Talos, CVE-2016-8707)
- Erneute Deklaration von i behoben (am Anfang und innerhalb einer Bedingung)
- Kleines Speicherleck behoben (Patch von Андрей Черный)
- Problem mit dem Strichversatz für
-annotatebehoben (Referenz) - fd-Leck im WebP-Coder behoben (Referenz)
- Fehlerhafte Skalierung bestimmter FITS-Bilder behoben (Referenz)
- Falsche Padding-Berechnung im PSD-Encoder behoben
- Falsches Parsen bei Ordered Dither behoben (Referenz)
- Falsches RLE-Decodieren beim Lesen eines DCM-Bildes mit mehreren Segmenten behoben
- Falsches RLE-Decodieren beim Lesen eines SGI-Bildes behoben (Referenz)
- Problem behoben, bei dem beim Lesen von EXR-Dateien das Anzeigefenster statt des Datenfensters verwendet wurde (Referenz)
- Speicherleck beim Erzeugen verschachtelter Exceptions in Magick++ behoben (Referenz)
- Korrekte Platzierung von Textanmerkungen für
east/westgravitybehoben - Lesen von DXT1-Bildern mit Alphakanal behoben.
- Wenn kein passender Zeilenumbruch gefunden wird, wird er für caption: erzwungen (Referenz)
- Einen privaten PNG-caNv-Chunk (canvas) implementiert, um die ursprünglichen Abmessungen und Offsets zu speichern, wenn ein Bild zugeschnitten wird. Zuvor haben wir dafür die Chunks oFFs und vpAg verwendet, was jedoch zu Konflikten mit anderen Anwendungen führen konnte, die den oFFs-Chunk ebenfalls nutzen
- Speicherzuweisung für TIFF-Pixel erhöht (Referenz)
- Das Alpha-Member von draw_info mit OpaqueAlpha initialisiert
- Indexkanal initialisiert, um die erwarteten Ergebnisse vom Stegano-Coder zu erhalten
- Kanäle über das Quellbild statt über das Zielbild iterieren (Fehlerbericht von Hanno Böck)
- Mask-Composite liefert korrekte Ergebnisse für das Werkzeug
convert(Referenz) - Monochrome Bilder haben keine invertierten Farben mehr (Referenz)
- Alphakanal beim Kombinieren von 4 oder mehr Bildern berücksichtigen (Referenz)
- Off-by-1-Fehler bei der Berechnung der Standardabweichung (Referenz)
- Off-by-one-Fehler bei der Speicherzuweisung (Referenz)
- Patch, damit die Option
-kuwaharaKanten mit Farbtabelle erhalten kann - EPT-Bilder mit nur einem TIFF- oder EPS-Bild zulassen, nicht mit beiden (Referenz)
- Pufferüberlauf verhindert (Fehlerbericht von Max Thrane)
- Pufferüberlauf und andere Probleme in den SIXEL-, PDB-, MAP-, TIFF- und CALS-Codern verhindert (Fehlerbericht von Donghai Zhu)
- Pufferüberlauf in den BMP- & SGI-Codern verhindert (Fehlerbericht von pwchen&rayzhong von tencent)
- Pufferüberlauf beim Streamen eines Bildes verhindert (Referenz)
- Fehler im MSL-Interpreter verhindert
- Speichernutzung nach dem Freigeben verhindert (Referenz)
- Möglichen Pufferüberlauf beim Lesen von TIFF-Bildern verhindert (Fehlerbericht von Shi Pu vom MS509 Team)
- Mögliche Schwachstelle für Shell-Command-Injection über den Parameter authenticate der PDF-, PCL- und XPS-Coder verhindert (Bericht von Erez Turjeman)
- Zufällige Pixeldaten bei beschädigten JPEG-Bildern verhindert (Fehlerbericht von Hirokazu Moriguchi, Sony)
- Unbeabsichtigtes Entfernen von MPC-Cache-Dateien verhindert (Referenz)
- Für
-channel-equalizewerden Kanäle unabhängig voneinander verarbeitet (Referenz) - Automatisches Einpassen von caption korrigiert (Referenz)
- Textlabel korrekt zentriert (Referenz)
- PES-Blöcke korrekt initialisiert (Referenz)
- Passwörter in Anführungszeichen setzen, wenn sie an ein Delegate-Programm übergeben werden.
- Statt
optionsnachartifactszu replizieren, wird vom Bild ein Link aufimage_infoerstellt und eine globale Option nachgeschlagen, wenn kein Artefakt definiert ist. - Schließende XML-Policy-Tags erkennen (Referenz)
- https-Delegate entfernt
- OpenMP-Aufrufe aus den Colormap-Update-Schleifen entfernt
- Unterstützung für den internen Ephemeral-Coder entfernt
- Die Funktion
read_vpag_chunk_callback()inpng_user_chunk_callback()umbenannt, und zwar incoders/png.c - Beim MVG-Grafikprimitiv clip-path in die Clip-Maske statt in das Bild rendern
- Den Titel des show-Delegate durch den Bilddateinamen statt durch das Label ersetzen
CoderSeekableStreamFlagdurchCoderDecoderSeekableStreamFlagundCoderEncoderSeekableStreamFlagersetzt- Das Define
connected-components:area-thresholdberücksichtigen (Referenz) - Die Option
gravityberücksichtigen (Referenz) - Option
-mattecolorwiederhergestellt - Korrekten Offset für negative Indizes bei der Option
-fxzurückgeben (Referenz) - Erwartungstreue Standardabweichung für Bildstatistiken zurückgeben (Referenz)
- Patch zurückgenommen, der das Update-Trait nicht für den Alphakanal setzte
- RLE-Prüfung auf Pixel-Offsets kleiner als 0 (Heap-Overflow-Bericht von Craig Young)
- Alle in Delegates eingebetteten Formatierungszeichen bereinigen
- Kommentare mit geschweiften Klammern für das MIFF-Bildformat bereinigen (Referenz)
- Eingabedateinamen für http-/https-Delegates bereinigen (verbesserter Patch)
- Sicherheitsverbesserungen am TEXT-Coder hatten ihn unbrauchbar gemacht (Referenz)
- Das Alpha-Member der Draw-Struktur auf
OpaqueAlphasetzen (Referenz) - Farbraum auf
sRGBsetzen, wenn-appenduneinheitliche Farbräume hat (Referenz) - sigmoidal-contrast: Direkte Berechnung, ohne LUT
- sigmoidal-contrast: Am Anfang unnötiges
ClampToQuantumentfernt - Option
-regionunterstützt (Referenz) - Unterstützung für die Option
--enable-indirect-readsdes Configure-Skripts, um indirekte Lesezugriffe (@) in Dateinamen zu aktivieren - Unterstützung für
--enable-pipes optionim Configure-Skript, um Pipes (|) in Dateinamen zu aktivieren - Unterstützung für die Sicherheitsrichtlinien pixel-cache und shred
- Unterstützung für Read-Masks bei der Option
-modulate - Unterstützung für die Option
-read-maskvon compare - Unterstützung für die Optionen
phash:colorspacesundphash:normalize - Die Option
-cloneverursacht kein Speicherleck mehr - Die Option
-extententspricht jetzt den Ergebnissen von IMv6 (Referenz) - Die Option
-streaminkrementiert den Pixelzeiger jetzt korrekt (Referenz) - Der Histogramm-Coder gibt jetzt den korrekten Extent zurück
- Um dem SVG-Standard zu entsprechen, wird
stroke-opacityfür transparente Striche verwendet - Alphakanal für das Differenzbild von compare deaktivieren (Referenz)
- Build ohne JPEG-Unterstützung wieder funktionsfähig gemacht (Referenz)
- Nicht initialisierte Daten im MAT-Bildformat (Referenz)
- Unit-Tests laufen nach einem kleinen SUN-Bild-Patch wieder durch
CopyMagickString()stattCopyMagickMemory()für Zeichenketten verwenden- Der Validierungs-Unit-Test für MNG funktioniert wieder
