Home Forum Nuclos Entwicklung Makros und Regeln NuclosImage in neuer API

Ansicht von 7 Beiträgen - 1 bis 7 (von insgesamt 7)
  • Autor
    Beiträge
  • #7154
    Markus Glitzner
    Teilnehmer

    Hallo!

    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 Bildernpackage 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ß
    Hugo

    #7159
    Matthias Haake
    Teilnehmer

    Hallo 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,
    Matthias

    PS: Neue Images erzeugt habe ich noch nicht. Eventuell über „getClassByName“? Oder ein vorhandenes Bild-Objekt klonen?

    #7160
    Markus Glitzner
    Teilnehmer

    danke schon mal, werde ich bei Gelegeheit ausprobieren.

    Momentan funktioniert es ja noch über die alte API, parallel zur neuen.

    Gruß
    Hugo

    #7161
    Ramin Goettlich
    Teilnehmer

    Der 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…

    #7162
    Matthias Haake
    Teilnehmer

    Ich 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,
    Matthias

    #7163
    Markus Glitzner
    Teilnehmer

    so, 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ß
    Hugo

    #7164
    Matthias Haake
    Teilnehmer

    Ich 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.

Ansicht von 7 Beiträgen - 1 bis 7 (von insgesamt 7)