4

Primefaces Cropperを使用して画像をトリミングしようとすると、次のエラーが発生しますが、画像で何も選択されていません(選択がありません):

2013年3月17日17:10:46com.sun.faces.lifecycle.ProcessValidationsPhase実行警告:負またはゼロ幅

java.awt.image.RasterFormatException: negative or zero width
        at java.awt.image.Raster.<init>(Raster.java:1108)
        at java.awt.image.WritableRaster.<init>(WritableRaster.java:129)
        at sun.awt.image.SunWritableRaster.<init>(SunWritableRaster.java:129)
        at sun.awt.image.ByteComponentRaster.<init>(ByteComponentRaster.java:154)
        at sun.awt.image.ByteInterleavedRaster.<init>(ByteInterleavedRaster.java:191)
        at sun.awt.image.ByteInterleavedRaster.createWritableChild(ByteInterleavedRaster.java:1261)
        at java.awt.image.BufferedImage.getSubimage(BufferedImage.java:1173)
        at org.primefaces.component.imagecropper.ImageCropperRenderer.getConvertedValue(ImageCropperRenderer.java:146)
        at javax.faces.component.UIInput.getConvertedValue(UIInput.java:1030)
        at javax.faces.component.UIInput.validate(UIInput.java:960)
        at javax.faces.component.UIInput.executeValidate(UIInput.java:1233)
        at javax.faces.component.UIInput.processValidators(UIInput.java:698)
        at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:510)
        at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1612)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIForm.visitTree(UIForm.java:362)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623)
        at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:378)
        at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:253)
        at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:183)
        at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:183)
        at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:183)
        at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1171)
        at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
        at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
        at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.omnifaces.filter.FacesExceptionFilter.doFilter(FacesExceptionFilter.java:56)
        at org.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:75)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.omnifaces.filter.GzipResponseFilter.doFilter(GzipResponseFilter.java:148)
        at org.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:75)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.omnifaces.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:115)
        at org.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:75)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
        at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:200)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:722)

Mar 17, 2013 5:10:46 PM com.sun.faces.renderkit.html_basic.OutcomeTargetRenderer getNavigationCase
WARNING: JSF1090: Navigation case not resolved for component j_idt74.

トリミングの過程でエラーが発生していないようですので、どうすればいいのかわかりません。

この問題を解決するのを手伝ってくれませんか。私は本当に何をすべきかわかりません。

Primefaces3.5とMyfaces2.1.17を使用しています。

どうもありがとうございます。

更新:クロッパー豆:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.imageio.stream.FileImageOutputStream;
import javax.servlet.ServletContext;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.primefaces.model.CroppedImage;

import com.meinanliegen.backingbean.User;
import com.meinanliegen.handlers.filters.Configurations;

@ManagedBean
@ViewScoped
public class ImageCropperBean implements Serializable {
  private static final long serialVersionUID = -7835902358418363820L;
  private static final Logger LOGGER = Logger.getLogger(ImageCropperBean.class);
  private CroppedImage croppedImage;
  private String photoCropped;
  // This only contains the relative path to the temp image : /temp/croppedImage
  private String relativeImagePhotoCropped;
  private String originalUploadedPhotoFileName;
  @ManagedProperty(value = "#{user}")
  private User user;

  public CroppedImage getCroppedImage() {
    return croppedImage;
  }

  public void setCroppedImage(CroppedImage croppedImage) {
    this.croppedImage = croppedImage;
  }

  public String getPhotoCropped() {
    return photoCropped;
  }

  public void setPhotoCropped(String photoCropped) {
    this.photoCropped = photoCropped;
  }

  public String getRelativeImagePhotoCropped() {
    return relativeImagePhotoCropped;
  }

  public void setRelativeImagePhotoCropped(String relativeImagePhotoCropped) {
    this.relativeImagePhotoCropped = relativeImagePhotoCropped;
  }

  public User getUser() {
    return user;
  }

  public void setUser(User user) {
    this.user = user;
  }

  public String crop() {
    if (croppedImage == null) {
      LOGGER.error("The cropped image is null");
    }
    else {
      manageTheCrop();
    }
    return null;
    }

  private void manageTheCrop() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ServletContext servletContext = (ServletContext) facesContext.getExternalContext().getContext();

    String originalFilePhotoName = croppedImage.getOriginalFilename();
    String tempLocationForCroppedFile = servletContext.getRealPath(Configurations.UPLOAD_TEMP_FILE_PATH);

    String prefix = FilenameUtils.getBaseName(originalFilePhotoName);
    String suffix = FilenameUtils.getExtension(originalFilePhotoName);

    // First time we need to save the original photo name
    if (originalUploadedPhotoFileName == null) {
      originalUploadedPhotoFileName = prefix + "." + suffix;
    }

    try {
      // We will keep the same name for cropped photo, until the user decides
      File photoCroppedFile = File.createTempFile(prefix, "." + suffix, new File(tempLocationForCroppedFile));
      photoCropped = photoCroppedFile.getPath();
      cropImageAddContentTo(photoCropped);

      String prefixCroppedPhoto = FilenameUtils.getBaseName(photoCropped);
      String suffixCroppedPhoto = FilenameUtils.getExtension(photoCropped);
      String photoCroppedFileName = prefixCroppedPhoto + "." + suffixCroppedPhoto;
      relativeImagePhotoCropped = Configurations.UPLOAD_TEMP_FILE_PATH + photoCroppedFileName;
    }
    catch (IOException ex) {
      LOGGER.error(ex);
      BeanUtils.addMessage(FacesMessage.SEVERITY_ERROR, "Bitte versuchen Sie es noch einmal.",
      "Fehler beim Zuschneiden Ihres Fotos");
    }
      }

public void saveCroppedImageAsPrimaryUserImage() {
if (photoCropped != null) {
  String profilePhotoChosenFilePrefix = String.format("%s_%s_%s", user.getFirstName(), user.getLastName(),
      originalUploadedPhotoFileName);
  try {
    // We will save the last cropped image as profile
    File finalPhotoLocation = new File(Configurations.UPLOAD_FILE_PATH, profilePhotoChosenFilePrefix);

    OutputStream output = null;
    output = new FileOutputStream(finalPhotoLocation);
    IOUtils.copy(new FileInputStream(photoCropped), output);
    user.setTempProfilePictureSrc(relativeImagePhotoCropped);
    user.setProfilePictureSrc("../uploads/" + finalPhotoLocation.getName());
  }
  catch (IOException ex) {
    LOGGER.error(ex);
    BeanUtils.addMessage(FacesMessage.SEVERITY_ERROR, "Bitte versuchen Sie es noch         einmal.", "Fehlermeldung");
      }
    }
  }

  public void cropImageAddContentTo(String croppedImagePath) {
    try {
      cropImage(croppedImagePath);
    }
    catch (IOException ex) {
      LOGGER.error(ex);
      BeanUtils.addMessage(FacesMessage.SEVERITY_ERROR, "Fehlermeldung",
          "Es ist eiin Fehler aufgetreten. Bitte versuchen Sie es noch einmal.");
    }
  }

  public void cropImage(String imageFileName) throws IOException {
    FileImageOutputStream imageFileOutput = null;
    imageFileOutput = new FileImageOutputStream(new File(imageFileName));
    imageFileOutput.write(croppedImage.getBytes(), 0, croppedImage.getBytes().length);
    imageFileOutput.close();
  }
}

およびJSF部分:

<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">

<p:row>
    <p:column style="height:120px; width 120px;">
        <p:panelGrid columns="2">
            <p:row>
                <p:column>
                    <div class="photo">
                        <p:graphicImage id="standardUploadedImage" value="#{user.tempProfilePictureSrc}" />
                    </div>
                </p:column>
            </p:row>
            <p:row>
                <h:panelGroup id="adjustImage">
                    <p:column style="width:150px">
                        <p:panelGrid>
                            <p:row>
                                <p:column>
                                    <h:outputText value="Bild innerhalb des Rahmens positionieren"
                                        rendered="#{uploadPhotoHandler.userImageUploaded == true}" />
                                </p:column>
                            </p:row>
                            <p:row>
                                <p:column>
                                    <p:commandButton value="Bild anpassen" oncomplete="cropWidget.show()"
                                        update=":growl cropDialog" immediate="true"
                                        rendered="#{uploadPhotoHandler.userImageUploaded == true}"
                                        styleClass="css3button" />
                                </p:column>
                            </p:row>
                        </p:panelGrid>
                    </p:column>
                </h:panelGroup>
            </p:row>
        </p:panelGrid>
    </p:column>
</p:row>

<p:row>
    <p:column>
        <p:fileUpload fileUploadListener="#{uploadPhotoHandler.handleFileUpload}" mode="advanced"
            label="Portraitfoto hochladen" sizeLimit="5242880" allowTypes="/(\.|\/)(gif|jpe?g|png)$/"
            invalidSizeMessage="Datei darf maximal 5 MB groß sein"
            invalidFileMessage="Bitte prüfen Sie das Format. Es können nur jpg, gif, png Dateien verwendet werden."
            update=":growl standardUploadedImage uploadedImage imageCropper adjustImage" auto="true"
            required="false" />
    </p:column>
</p:row>

<p:row>
    <p:column>
        <p:confirmDialog id="cropDialog" header="Bild anpassen" severity="alert" showEffect="fade" closeOnEscape="true"
            closable="true" hideEffect="fade" widgetVar="cropWidget">
            <p:panelGrid>
                <p:row>
                    <p:column colspan="2">
                        <p:panelGrid columns="3" style="height:50px">
                            <p:row>
                                <p:column>
                                    <p:commandButton id="cancel" value="Löschen" onclick="cropWidget.hide()"
                                        type="button"
                                        update=":growl imageCropper uploadedImage standardUploadedImage"
                                        immediate="true" styleClass="css3button" />
                                </p:column>
                            </p:row>
                            <p:row>
                                <p:column>
                                    <h:panelGrid id="cropBtnPanel">
                                        <p:commandButton id="crop" value="Zuschneiden"
                                            action="#{imageCropperBean.crop}"
                                            update=":growl imageCropper uploadedImage standardUploadedImage cropFinished crop cropBtnPanel ApplyBtnPanel"
                                            process="crop imageCropper" styleClass="css3button"
                                            rendered="#{imageCropperBean.showCrop}" />
                                    </h:panelGrid>
                                </p:column>
                            </p:row>
                            <p:row>
                                <p:column>
                                    <h:panelGrid id="ApplyBtnPanel">
                                        <p:commandButton id="cropFinished" value="Übernehmen"
                                            actionListener="#{imageCropperBean.saveCroppedImageAsPrimaryUserImage}"
                                            oncomplete="cropWidget.hide()"
                                            update=":growl imageCropper uploadedImage standardUploadedImage crop cropFinished cropBtnPanel ApplyBtnPanel"
                                            process="cropFinished imageCropper" styleClass="css3button"
                                            rendered="#{imageCropperBean.showApply}" />
                                    </h:panelGrid>
                                </p:column>
                            </p:row>
                        </p:panelGrid>
                    </p:column>
                </p:row>

                <p:row>
                    <p:column headerText="Original">
                        <div class="photoToBeCropped">
                            <p:imageCropper id="imageCropper" 
                                            value="#{imageCropperBean.croppedImage}"
                                            image="#{user.tempProfilePictureSrc}" 
                                            initialCoords="225,75,300,125"
                                            aspectRatio="1.0" 
                                            rendered="#{uploadPhotoHandler.userImageUploaded == true}"
                                            minSize="170" 
                                            required="true" />
                        </div>
                    </p:column>
                    <p:column headerText="Cropped">
                        <div class="photoToBeCropped">
                            <p:graphicImage id="uploadedImage" value="#{imageCropperBean.relativeImagePhotoCropped}" />
                        </div>
                    </p:column>
                </p:row>
            </p:panelGrid>
        </p:confirmDialog>
    </p:column>
</p:row>

このクロップモジュール全体が1つのウィザードのprimefacesステップに埋め込まれていることに注意してください。

4

5 に答える 5

7

自分のショーケースで再現できます。画像の選択を解除して[切り抜き]をクリックすると、ajax応答に未処理の例外が表示されます。

ここに画像の説明を入力してください

(彼らがまともなajax例外ハンドラーをインストールして、これがエンドユーザーにすぐに見えるようになったら良かったです)

まあ、これは本当に彼ら自身のコードのバグです。これは4日前に、現在予定されていない問題5349としてすでに報告されています。

彼らがそれを修正するのを本当に待つことができない場合、あなたの最善はレンダラーをオーバーライドしてジョブをスキップすることですgetConvertedValue()

public class MyImageCropperRenderer extends ImageCropperRenderer {

    @Override
    public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException {
        if (submittedValue == null || ((String) submittedValue).endsWith("_0_0")) {
            return null;
        }

        return super.getConvertedValue(context, component, submittedValue);
    }

}

送信された値は、何も選択されていない場合の形式x_y_w_h_w_hなります。_0_0その場合、上記のカスタムレンダラーはnull、例外をスローする変換ジョブを続行する代わりに、すぐに戻ります。

このレンダラーを実行するには、次のように登録します。faces-config.xmlここで、<renderer-class>はカスタムレンダラーのFQNです。

<render-kit>
    <renderer>
        <component-family>org.primefaces.component</component-family>
        <renderer-type>org.primefaces.component.ImageCropperRenderer</renderer-type>
        <renderer-class>com.example.MyImageCropperRenderer</renderer-class>
    </renderer>
</render-kit>
于 2013-03-19T19:12:52.380 に答える
1

BalusC用に投稿されたソリューションを使用しました。しかし、散発的に私は値「_2_0」またはそのようなものを取得します。このような場合、エラーが再度発生します。それから私はそう解決しました:

@Override
public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException {
    if (submittedValue != null ){
        String[] submittedValueArray = ((String) submittedValue).split("_");
        if (!"0".equals(submittedValueArray[2]) && !"0".equals(submittedValueArray[3])) {
            return super.getConvertedValue(context, component, submittedValue);
        }           
    }
    return null;
}
于 2014-05-12T13:58:38.460 に答える
0
catch (RasterFormatException e) {
 FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "This crop size is not supported", null);
 throw new ErrorImageSizeException(message); }

コンストラクターを使用してConverterExceptionを拡張するErrorImageSizeExceptionを作成します

public ErrorImageSizeException(FacesMessage mensagem) {
    super(mensagem);
}
于 2013-12-26T03:30:53.500 に答える
0

java.lang.NumberFormatExceptionが発生します:入力文字列の場合:トリミング領域を変更する前にボタンを押すと、「NaN」になります。

<h:form id="editUserPhotoForm" > 
    <p:messages showDetail="true" autoUpdate="false" closable="true" />
        <h:panelGrid columns="2" rendered="#{not empty adminView.editUser}">
            <p:imageCropper value="#{adminView.croppedImage}"  image="#{adminView.userImagePath}" initialCoords="0,0,200,260" aspectRatio="0.77" minSize="200,260"/>
            <p:graphicImage value="#{adminView.imageUser}" width="200" cache="false" />
        </h:panelGrid>
        <p:commandButton value="crop" action="#{adminView.crop}" ignoreAutoUpdate="true" process="@form" update="@form" icon="ui-icon-scissors"/>
</h:form>

@BalusCによって投稿されたソリューションを使用しましたが、条件を追加しました:

if (submittedValue == null || ((String) submittedValue).endsWith("_0_0") || ((String)submittedValue).contains("NaN"))
于 2014-10-30T05:53:19.487 に答える
0

@BalusCによって投稿されたソリューションに従って、私は独自のソリューションを実装し、選択がない場合は全体像を保存します。

@Override
public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException {

    if (submittedValue != null ){
        String[] submittedValueArray = ((String) submittedValue).split("_");
        if (!"0".equals(submittedValueArray[2]) && !"0".equals(submittedValueArray[3])) {
            return super.getConvertedValue(context, component, submittedValue);
        }           
    }

    try {
        return super.getConvertedValue(context, component, buildDefaultSubmittedValue(context, component));
    } catch (IOException e) {
        throw new ConverterException("Error cropping the whole image");
    }
}

private String buildDefaultSubmittedValue(FacesContext context, UIComponent component) throws IOException {
    ImageCropper cropper = (ImageCropper) component;

    //remove query string
    String imagePath = cropper.getImage();
    int queryStringIndex = imagePath.indexOf("?");
    if(queryStringIndex != -1 ) {
        imagePath = imagePath.substring(0, queryStringIndex);
    }

    BufferedImage outputImage = getSourceImage(context, imagePath);
    return "0_0_" + outputImage.getWidth() + "_" + outputImage.getHeight();
}

private BufferedImage getSourceImage(FacesContext context, String imagePath) throws IOException {
    BufferedImage outputImage = null;
    boolean isExternal = imagePath.startsWith("http");

    if(isExternal) {
        URL url = new URL(imagePath);

        outputImage =  ImageIO.read(url);
    }
    else {
        ExternalContext externalContext = context.getExternalContext();

        outputImage = ImageIO.read(new File(externalContext.getRealPath("") + imagePath));
    }

    return outputImage;
}
于 2016-09-09T20:41:10.787 に答える