Home › Forum › Nuclos Entwicklung › Makros und Regeln › NuclosImage in neuer API
- Dieses Thema hat 6 Antworten und 3 Teilnehmer, und wurde zuletzt aktualisiert vor 10 Jahren, 1 Monat von
Matthias Haake.
-
AutorBeiträge
-
17 Oktober 2013 um 00:43 Uhr #7154
Markus Glitzner
TeilnehmerHallo!
Ich habe eine Bibliotheksregel, die mir Bilder (NuclosImage) beim Speichern verkleinert. Diese Regel hab ich auf die neue API adaptiert, müsste auch funktionieren. Allerdings kann ich weder ein neues NuclosImage erzeugen, noch ein bestehendes ändern. Laut API Referenz gibt es zwar newImage, aber das bekomme ich nicht zum laufen (k.a. was ich davor setzen muss) und setName() und setContent() gibt es scheinbar nicht (mehr). Ich vermisse auch getWidth() und getHeight(), das gabs früher auch, ist aber nicht so schlimm, ich übergebe jetzt halt statt dem NuclosImage nur den Content.
Hat jemand ein simples Beispiel (inkl. import packages) wie NuclosImages erzeugt bzw. geändert werden können.
Das hier wäre meine Regel zum verkleinern von Bildern
package org.nuclet.rules;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;import javax.imageio.ImageIO;
public class Images {
public static byte[] Resize(byte[] nImg, Integer wNew, Integer hNew) {
if (nImg.length > 0) {
try {
BufferedImage img = ImageIO.read(new ByteArrayInputStream(nImg));
Integer wOld = img.getWidth(null);
Integer hOld = img.getHeight(null);if ((wOld>wNew && wNew>0) || (hOld>hNew && hNew>0)) {
if (wOld*1.0/wNew*1.0 > hOld*1.0/hNew*1.0) {
wNew = (int)(wOld*1.0/(wOld*1.0/wNew*1.0));
hNew = (int)(hOld*1.0/(wOld*1.0/wNew*1.0));
} else {
wNew = (int)(wOld*1.0/(hOld*1.0/hNew*1.0));
hNew = (int)(hOld*1.0/(hOld*1.0/hNew*1.0));
}Image scaledImage = img.getScaledInstance(wNew, hNew, Image.SCALE_SMOOTH);
BufferedImage outImg = new BufferedImage(wNew, hNew, BufferedImage.TYPE_INT_RGB);
Graphics g = outImg.getGraphics();
g.drawImage(scaledImage, 0, 0, null);
g.dispose();ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(outImg, "jpeg", baos);
}
} catch (IOException e) {
//do nothing
}
}return nImg;
}
}Gruß
Hugo17 Oktober 2013 um 16:40 Uhr #7159Matthias Haake
TeilnehmerHallo Hugo,
ich habe mir hier mit Reflections beholfen – das funktioniert, auch wenn es natürlich nicht so schön ist.
import java.lang.reflect.Field;
import java.lang.reflect.Method;[...]
// convert NuclosImage into Object
Object image = (Object)yourNuclosImage;Field contentField = image.getClass().getDeclaredField("content");
contentField.setAccessible(true);Field widthField = image.getClass().getDeclaredField("width");
widthField.setAccessible(true);Field heightField = image.getClass().getDeclaredField("height");
heightField.setAccessible(true);// resize image...
// set content
contentField.set(image, baos.toByteArray());// set dimensions
widthField.set(image, wNew);
heightField.set(image, hNew);Ich hoffe, das hilft Dir als Work-a-round erstmal, bis das Interface org.nuclos.api.common.NuclosImage um entsprechende Methoden erweitert ist. Hinter den Kulissen werkelt nach wie vor die herkömmliche Klasse „org.nuclos.common.NuclosImage“.
Viele Grüße,
MatthiasPS: Neue Images erzeugt habe ich noch nicht. Eventuell über „getClassByName“? Oder ein vorhandenes Bild-Objekt klonen?
17 Oktober 2013 um 16:47 Uhr #7160Markus Glitzner
Teilnehmerdanke schon mal, werde ich bei Gelegeheit ausprobieren.
Momentan funktioniert es ja noch über die alte API, parallel zur neuen.
Gruß
Hugo17 Oktober 2013 um 16:50 Uhr #7161Ramin Goettlich
TeilnehmerDer Nachteil an Reflection ist natürlich, dass die Sicherheit (Abwärtskompatibilität) der API umgangen wird. Wenn wir die über Reflection aufgerufenen Methoden im Kern ändern / entfernen / umbenennen, knallt die Regel, die über Reflection versucht, darauf zuzugreifen.
Der bessere Weg ist auf jeden Fall, ein Ticket zur Erweiterung der API-Klasse NuclosImage einzustellen.
Oder Nuclos auf Bitbucket zu forken, die Änderung selbst einzubauen und einen GIT Pull Request zu stellen, damit wir die Aufnahme der Änderung in den Kern prüfen können…
17 Oktober 2013 um 17:06 Uhr #7162Matthias Haake
TeilnehmerIch stimme nuclosian zu: Der Nachteil liegt auf der Hand. Aber im Developer-Alltag hat man meist Zeitdruck, eine Sache schnell lauffähig zu bekommen – ich kann ja nicht jede Sache, die lokal noch nicht funktioniert, mit höchster Priorität ins IssueTracking stellen.
Wenn man das aber als Methode kapselt, kann man sie später überladen (statt Object wird dann NuclosImage als Methodenparameter übergeben) und schon arbeiten alle Instanzen mit dem Interface aus der API.
Gibt es für Bitbucket eine Anleitung? Was muss man auschecken? Welche Abhängigkeiten gibt es beim Kompilieren usw… bin im Alltag eher mit Visual Studio und Team Foundation Server unterwegs. Von daher wäre da etwas Einarbeitung nötig – prinzipiell bin ich aber gerne bereit mich an gewissen Stellen einzubringen.
UPDATE: Dank MercurialEclipse ist der Einstieg ziemlich simpel 😉
Viele Grüße,
Matthias17 Oktober 2013 um 17:44 Uhr #7163Markus Glitzner
Teilnehmerso, hab es nun doch mit Boardmitteln der neuen API geschafft. Hab lediglich immer versucht das Interface statt der Klasse aufzurufen. War gestern Abend dann wohl doch schon zu spät.
Meine Image Klasse:
package org.nuclet.rules;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;import javax.imageio.ImageIO;
public class Images {
public static byte[] Resize(byte[] content, Integer wNew, Integer hNew) {
if (content.length > 0) {
try {
BufferedImage img = ImageIO.read(new ByteArrayInputStream(content));
Integer wOld = img.getWidth(null);
Integer hOld = img.getHeight(null);if ((wOld>wNew && wNew>0) || (hOld>hNew && hNew>0)) {
if (wOld*1.0/wNew*1.0 > hOld*1.0/hNew*1.0) {
wNew = (int)(wOld*1.0/(wOld*1.0/wNew*1.0));
hNew = (int)(hOld*1.0/(wOld*1.0/wNew*1.0));
} else {
wNew = (int)(wOld*1.0/(hOld*1.0/hNew*1.0));
hNew = (int)(hOld*1.0/(hOld*1.0/hNew*1.0));
}Image scaledImage = img.getScaledInstance(wNew, hNew, Image.SCALE_SMOOTH);
BufferedImage outImg = new BufferedImage(wNew, hNew, BufferedImage.TYPE_INT_RGB);
Graphics g = outImg.getGraphics();
g.drawImage(scaledImage, 0, 0, null);
g.dispose();ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(outImg, "jpeg", baos);return baos.toByteArray();
}
} catch (IOException e) {
return null;
}
}return content;
}
}Aufruf:
if (pos.getBild() != null && pos.getBild().getContent() != null) {
byte[] content = Images.Resize(pos.getBild().getContent(), 240, 240);
pos.setBild(BusinessObjectProvider.newImage(pos.getBild().getName(), content));
}Danke für den Denkanstoß!
Gruß
Hugo17 Oktober 2013 um 18:12 Uhr #7164Matthias Haake
TeilnehmerIch werde es mit Update 3.15 (Tests sehen bislang gut aus! :laugh:) ebenfalls ohne Reflections umsetzen. Bislang verwenden wir 3.12 – da gibt es das NuclosImage in der neuen API noch nicht und das alte Objekt ist ja bereits gesperrt – von daher blieb ja nichts anderes übrig als obiger Weg.
-
AutorBeiträge