Ticket #15574: josm-large-jpeg-scaled-loading-through-jni-turbojpeg-to-workaround-oom-experimental__r3.patch

File josm-large-jpeg-scaled-loading-through-jni-turbojpeg-to-workaround-oom-experimental__r3.patch, 3.7 KB (added by cmuelle8, 6 years ago)

patch against r13191 + josm-store-width-and-height-info-in-ImageEntry.patch applied; deprecates the two oldest patches; of limited use until (a) distros support jni in turbojpeg lib; atm debian, ubuntu, etc do not and (b) binding classes for turbojpeg support partial image decoding

  • src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java

     
    2424import java.awt.image.BufferedImage;
    2525import java.awt.image.ImageObserver;
    2626import java.io.File;
     27import java.io.FileInputStream;
     28import java.io.IOException;
    2729
    2830import javax.swing.JComponent;
    2931import javax.swing.SwingUtilities;
    3032
     33import org.libjpegturbo.turbojpeg.TJDecompressor;
     34import org.libjpegturbo.turbojpeg.TJException;
    3135import org.openstreetmap.josm.data.preferences.BooleanProperty;
    3236import org.openstreetmap.josm.data.preferences.DoubleProperty;
    3337import org.openstreetmap.josm.spi.preferences.Config;
     
    320324                img = null;
    321325            }
    322326
     327            if (img == null && file.getPath().matches(".*\\.[jJ][pP][eE]?[gG]$")) {
     328                TJDecompressor tjd = null;
     329                FileInputStream fis = null;
     330                try {
     331                    tjd = new TJDecompressor();
     332                    fis = new FileInputStream(file);
     333
     334                    Logging.info("Loading {0} ({1}x{2}) using turbojpeg", file.getPath(), width, height);
     335                    final byte[] buf = new byte[(int) file.length()];
     336                    int off = 0;
     337                    while (fis.available() > 0) {
     338                        off += fis.read(buf, off, Math.min(512*1024, buf.length-off));
     339                        if (this.entry != ImageDisplay.this.entry)
     340                            return;
     341                    }
     342                    tjd.setSourceImage(buf, buf.length);
     343
     344                    while (width > 0 && height > 0) {
     345                        if (mayFitMemory(((long) width)*height*4*2)) {
     346                            BufferedImage bi = new BufferedImage(
     347                                    tjd.getScaledWidth(width, height),
     348                                    tjd.getScaledHeight(width, height),
     349                                    BufferedImage.TYPE_INT_RGB);
     350                            if (this.entry != ImageDisplay.this.entry)
     351                                return;
     352                            try {
     353                                tjd.decompress(bi, 0);
     354                                width = bi.getWidth(null);
     355                                height = bi.getHeight(null);
     356                                img = bi;
     357                                break;
     358                            } catch (OutOfMemoryError oom) {
     359                                bi = null;
     360                            }
     361                        }
     362                        width = (width*4)/5;
     363                        height = (height*4)/5;
     364                    }
     365                } catch (UnsatisfiedLinkError ule) {
     366                    Logging.warn("turbojpeg not found in {0}", System.getProperty("java.library.path"));
     367                } catch (TJException e) {
     368                    Logging.warn("turbojpeg unusable or error decoding {0}", file.getPath());
     369                } catch (IOException e) {
     370                    Logging.warn("error reading file {0} for turbojpeg decoding", file.getPath());
     371                } finally {
     372                    try {
     373                        if (tjd != null) {
     374                            tjd.close();
     375                        }
     376                        if (fis != null) {
     377                            fis.close();
     378                        }
     379                    } catch (Exception e) {
     380                        e.printStackTrace();
     381                    }
     382                }
     383            }
     384
    323385            synchronized (ImageDisplay.this) {
    324386                if (this.entry != ImageDisplay.this.entry) {
    325387                    // The file has changed