From c79fc809f206e9f77b684f5e2deb8050946f9718 Mon Sep 17 00:00:00 2001 From: Georgy Litvinov Date: Sun, 1 Aug 2021 16:26:30 +0200 Subject: [PATCH] feat: Added option to reduce image PPI --- build.gradle | 1 + gradle.properties | 2 +- .../w2phtml/gui/ConfigurationWindow.java | 325 ++++++++++-------- .../gui/localizations/w2phtml.properties | 3 +- .../gui/localizations/w2phtml_ru.properties | 3 +- .../w2phtml/base/BinaryGraphicsDocument.java | 82 ++++- src/main/java/w2phtml/xhtml/XhtmlConfig.java | 14 +- .../w2phtml/xhtml/content/DrawParser.java | 1 + 8 files changed, 270 insertions(+), 161 deletions(-) diff --git a/build.gradle b/build.gradle index f291ebe..14beeda 100644 --- a/build.gradle +++ b/build.gradle @@ -46,6 +46,7 @@ dependencies{ bundledLibs group: 'org.apache.jena', name: 'jena-arq', version: '3.15.0' bundledLibs group: 'org.slf4j', name: 'slf4j-api', version: '1.7.30' bundledLibs group: 'com.opencsv', name: 'opencsv', version: '5.1' + bundledLibs group: 'org.imgscalr', name: 'imgscalr-lib', version: '4.2' bundledLibs group: 'org.apache.commons', name: 'commons-imaging', version: '1.0-alpha2' configurations.compile.extendsFrom(configurations.bundledLibs) diff --git a/gradle.properties b/gradle.properties index 9f2c3a0..0428a05 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=0.9.19 +version=0.9.20 diff --git a/src/main/java/pro/litvinovg/w2phtml/gui/ConfigurationWindow.java b/src/main/java/pro/litvinovg/w2phtml/gui/ConfigurationWindow.java index db602b9..94afdf6 100644 --- a/src/main/java/pro/litvinovg/w2phtml/gui/ConfigurationWindow.java +++ b/src/main/java/pro/litvinovg/w2phtml/gui/ConfigurationWindow.java @@ -38,12 +38,14 @@ import javax.swing.JSplitPane; import java.awt.BorderLayout; import javax.swing.JDesktopPane; import javax.swing.BoxLayout; +import javax.swing.ComboBoxModel; import javax.swing.SpringLayout; import java.awt.FlowLayout; import java.awt.CardLayout; import java.awt.Component; import javax.swing.SwingConstants; import javax.swing.JComboBox; +import java.awt.Choice; public class ConfigurationWindow extends JFrame { @@ -54,6 +56,7 @@ public class ConfigurationWindow extends JFrame { private static final String BUTTON_SAVE_LABEL = "button_save_label"; private static final String BUTTON_SAVEAS_LABEL = "button_saveas_label"; private static final String ARG_PAGINATION = "pagination"; + private static final String ARG_IMAGE_RESOLUTION = "image_resolution"; private static final String ARG_CSV_METADATA = "csv_metadata"; private static final String ARG_RDF_TYPE = "rdf_type"; private static final String CSV_FILE_EXTENSION = "csv"; @@ -88,6 +91,7 @@ public class ConfigurationWindow extends JFrame { private static final String ARG_CSS_INLINE = "css_inline"; private static final String ARG_MIN_LETTER_SPACING = "min_letter_spacing"; private static final String LABEL_PAGINATION = "label_pagination"; + private static final String LABEL_IMAGE_RESOLUTION = "label_image_resolution"; private static final String ARG_PAGE_BREAK_STYLE = "page_break_style"; private static final String LABEL_BREAK_STYLE = "label_break_style"; private static final String LETTER_SPACING_DEFAULT_VALUE = "0.15"; @@ -122,6 +126,7 @@ public class ConfigurationWindow extends JFrame { private XComponentContext context; private String fileName = ""; private Localizer localizer; + private String[] resolutions = {"0","72","150","300","600","1200","2400"}; /** * Create the application. @@ -244,11 +249,11 @@ public class ConfigurationWindow extends JFrame { configuration.put(ARG_USE_MATHJAX, cb_UseMathJax); JCheckBox cb_IgnoreEmptyParagraphs = new JCheckBox(localizer.getTranslation(LABEL_INGNORE_EMPTY_PARS)); - cb_IgnoreEmptyParagraphs.setSelected(true); + cb_IgnoreEmptyParagraphs.setSelected(false); configuration.put(ARG_IGNORE_EMPTY_PARAGRAPHS, cb_IgnoreEmptyParagraphs); JCheckBox cb_IgnoreHardLineBreaks = new JCheckBox(localizer.getTranslation(LABEL_FILETER_HARD_LINE_BREAKS)); - cb_IgnoreHardLineBreaks.setSelected(true); + cb_IgnoreHardLineBreaks.setSelected(false); configuration.put(ARG_IGNORE_HARD_LINE_BREAKS, cb_IgnoreHardLineBreaks); JLabel lb_FilterLetterSpacing = new JLabel(localizer.getTranslation(LABEL_MIN_LETTER_SPACING)); @@ -336,64 +341,75 @@ public class ConfigurationWindow extends JFrame { JCheckBox cb_Pagination = new JCheckBox(localizer.getTranslation(LABEL_PAGINATION)); cb_Pagination.setSelected(true); configuration.put(ARG_PAGINATION, cb_Pagination); + + JLabel lb_ImageResolution = new JLabel(localizer.getTranslation(LABEL_IMAGE_RESOLUTION)); + + JComboBox cbox_image_resolution = new JComboBox(resolutions); + configuration.put(ARG_IMAGE_RESOLUTION, cbox_image_resolution); + cbox_image_resolution.setSelectedIndex(2); GroupLayout gl_panel_configHTML = new GroupLayout(panel_configHTML); gl_panel_configHTML.setHorizontalGroup( gl_panel_configHTML.createParallelGroup(Alignment.LEADING) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addGap(32) - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addComponent(cb_Pagination, GroupLayout.PREFERRED_SIZE, 303, GroupLayout.PREFERRED_SIZE) - .addContainerGap()) - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addComponent(lb_Scale, GroupLayout.PREFERRED_SIZE, 175, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(ComponentPlacement.RELATED) - .addComponent(tf_Scale, GroupLayout.PREFERRED_SIZE, 175, GroupLayout.PREFERRED_SIZE)) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addComponent(lb_FilterLetterSpacing, GroupLayout.PREFERRED_SIZE, 297, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(ComponentPlacement.RELATED) - .addComponent(tf_FilterLetterSpacing, GroupLayout.PREFERRED_SIZE, 58, GroupLayout.PREFERRED_SIZE)) - .addComponent(cb_convertToPx, GroupLayout.PREFERRED_SIZE, 592, GroupLayout.PREFERRED_SIZE) - .addComponent(cb_IgnoreHardLineBreaks, GroupLayout.PREFERRED_SIZE, 389, GroupLayout.PREFERRED_SIZE) - .addComponent(cb_IgnoreEmptyParagraphs, GroupLayout.PREFERRED_SIZE, 405, GroupLayout.PREFERRED_SIZE) - .addComponent(cb_UseMathJax, GroupLayout.PREFERRED_SIZE, 409, GroupLayout.PREFERRED_SIZE) - .addComponent(cb_EmbedVectorImages, GroupLayout.PREFERRED_SIZE, 313, GroupLayout.PREFERRED_SIZE) - .addComponent(cb_InlineStyles, GroupLayout.PREFERRED_SIZE, 349, GroupLayout.PREFERRED_SIZE) - .addComponent(cb_EmbedRaster, GroupLayout.PREFERRED_SIZE, 416, GroupLayout.PREFERRED_SIZE)) - .addContainerGap()) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addGap(1) - .addComponent(lb_OutFilePath, GroupLayout.PREFERRED_SIZE, 184, GroupLayout.PREFERRED_SIZE) - .addGap(10) - .addComponent(tf_OutputFile, GroupLayout.DEFAULT_SIZE, 665, Short.MAX_VALUE) - .addGap(21) - .addComponent(btn_ChooseOutputFile, GroupLayout.PREFERRED_SIZE, 113, GroupLayout.PREFERRED_SIZE) - .addGap(10)) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addComponent(lb_TargetFormat_description) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addComponent(lb_TargetFormat, GroupLayout.PREFERRED_SIZE, 111, GroupLayout.PREFERRED_SIZE)) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addGap(3) - .addComponent(lb_FilePath, GroupLayout.PREFERRED_SIZE, 178, GroupLayout.PREFERRED_SIZE) - .addGap(14) - .addComponent(tf_inputFile, GroupLayout.DEFAULT_SIZE, 664, Short.MAX_VALUE) - .addGap(22) - .addComponent(btnChooseFile, GroupLayout.PREFERRED_SIZE, 113, GroupLayout.PREFERRED_SIZE) - .addGap(10))) - .addGap(48))))) .addGroup(gl_panel_configHTML.createSequentialGroup() .addGap(34) .addComponent(lb_pageBreakInlineStyle, GroupLayout.PREFERRED_SIZE, 184, GroupLayout.PREFERRED_SIZE) .addGap(7) - .addComponent(tf_pageBreakInlineStyle, GroupLayout.DEFAULT_SIZE, 799, Short.MAX_VALUE) + .addComponent(tf_pageBreakInlineStyle, GroupLayout.DEFAULT_SIZE, 802, Short.MAX_VALUE) .addGap(60)) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addGap(32) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addComponent(lb_ImageResolution, GroupLayout.PREFERRED_SIZE, 336, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(cbox_image_resolution, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) + .addComponent(cb_Pagination, GroupLayout.PREFERRED_SIZE, 303, GroupLayout.PREFERRED_SIZE) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addComponent(lb_Scale, GroupLayout.PREFERRED_SIZE, 175, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(tf_Scale, GroupLayout.PREFERRED_SIZE, 175, GroupLayout.PREFERRED_SIZE)) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addComponent(lb_FilterLetterSpacing, GroupLayout.DEFAULT_SIZE, 307, Short.MAX_VALUE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(tf_FilterLetterSpacing, GroupLayout.PREFERRED_SIZE, 58, GroupLayout.PREFERRED_SIZE) + .addGap(215)) + .addComponent(cb_convertToPx, GroupLayout.PREFERRED_SIZE, 592, GroupLayout.PREFERRED_SIZE) + .addComponent(cb_IgnoreHardLineBreaks, GroupLayout.PREFERRED_SIZE, 389, GroupLayout.PREFERRED_SIZE) + .addComponent(cb_IgnoreEmptyParagraphs, GroupLayout.PREFERRED_SIZE, 405, GroupLayout.PREFERRED_SIZE) + .addComponent(cb_UseMathJax, GroupLayout.PREFERRED_SIZE, 409, GroupLayout.PREFERRED_SIZE) + .addComponent(cb_EmbedVectorImages, GroupLayout.PREFERRED_SIZE, 313, GroupLayout.PREFERRED_SIZE) + .addComponent(cb_InlineStyles, GroupLayout.PREFERRED_SIZE, 349, GroupLayout.PREFERRED_SIZE) + .addComponent(cb_EmbedRaster, GroupLayout.PREFERRED_SIZE, 416, GroupLayout.PREFERRED_SIZE)) + .addGap(463)) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addGap(1) + .addComponent(lb_OutFilePath, GroupLayout.PREFERRED_SIZE, 184, GroupLayout.PREFERRED_SIZE) + .addGap(10) + .addComponent(tf_OutputFile, GroupLayout.DEFAULT_SIZE, 668, Short.MAX_VALUE) + .addGap(21) + .addComponent(btn_ChooseOutputFile, GroupLayout.PREFERRED_SIZE, 113, GroupLayout.PREFERRED_SIZE) + .addGap(10)) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addComponent(lb_TargetFormat_description) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(lb_TargetFormat, GroupLayout.PREFERRED_SIZE, 111, GroupLayout.PREFERRED_SIZE)) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addGap(3) + .addComponent(lb_FilePath, GroupLayout.PREFERRED_SIZE, 178, GroupLayout.PREFERRED_SIZE) + .addGap(14) + .addComponent(tf_inputFile, GroupLayout.DEFAULT_SIZE, 667, Short.MAX_VALUE) + .addGap(22) + .addComponent(btnChooseFile, GroupLayout.PREFERRED_SIZE, 113, GroupLayout.PREFERRED_SIZE) + .addGap(10))) + .addGap(48)))))) ); gl_panel_configHTML.setVerticalGroup( gl_panel_configHTML.createParallelGroup(Alignment.LEADING) @@ -438,13 +454,10 @@ public class ConfigurationWindow extends JFrame { .addGap(2) .addComponent(lb_Scale)) .addComponent(tf_Scale, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addGap(6) - .addComponent(tf_FilterLetterSpacing, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addGap(8) - .addComponent(lb_FilterLetterSpacing, GroupLayout.PREFERRED_SIZE, 18, GroupLayout.PREFERRED_SIZE))) + .addGap(8) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(lb_FilterLetterSpacing, GroupLayout.PREFERRED_SIZE, 18, GroupLayout.PREFERRED_SIZE) + .addComponent(tf_FilterLetterSpacing, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(cb_InlineStyles) .addGap(7) @@ -459,9 +472,13 @@ public class ConfigurationWindow extends JFrame { .addComponent(cb_IgnoreEmptyParagraphs) .addPreferredGap(ComponentPlacement.UNRELATED) .addComponent(cb_UseMathJax) - .addPreferredGap(ComponentPlacement.UNRELATED) + .addPreferredGap(ComponentPlacement.RELATED) .addComponent(cb_Pagination) - .addContainerGap(277, Short.MAX_VALUE)) + .addGap(7) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(lb_ImageResolution) + .addComponent(cbox_image_resolution, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addContainerGap(118, Short.MAX_VALUE)) ); panel_configHTML.setLayout(gl_panel_configHTML); return panel_configHTML; @@ -488,11 +505,11 @@ public class ConfigurationWindow extends JFrame { configuration.put(ARG_GREENSTONE, cb_Greenstone); JCheckBox cb_IgnoreEmptyParagraphs = new JCheckBox(localizer.getTranslation(LABEL_INGNORE_EMPTY_PARS)); - cb_IgnoreEmptyParagraphs.setSelected(true); + cb_IgnoreEmptyParagraphs.setSelected(false); configuration.put(ARG_IGNORE_EMPTY_PARAGRAPHS, cb_IgnoreEmptyParagraphs); JCheckBox cb_IgnoreHardLineBreaks = new JCheckBox(localizer.getTranslation(LABEL_FILETER_HARD_LINE_BREAKS)); - cb_IgnoreHardLineBreaks.setSelected(true); + cb_IgnoreHardLineBreaks.setSelected(false); configuration.put(ARG_IGNORE_HARD_LINE_BREAKS, cb_IgnoreHardLineBreaks); JLabel lb_FilterLetterSpacing = new JLabel(localizer.getTranslation(LABEL_MIN_LETTER_SPACING)); @@ -583,6 +600,14 @@ public class ConfigurationWindow extends JFrame { JCheckBox cb_Pagination = new JCheckBox(localizer.getTranslation(LABEL_PAGINATION)); cb_Pagination.setSelected(true); configuration.put(ARG_PAGINATION, cb_Pagination); + + JLabel lb_ImageResolution = new JLabel(localizer.getTranslation(LABEL_IMAGE_RESOLUTION)); + + JComboBox cbox_image_resolution = new JComboBox(resolutions); + cbox_image_resolution.setSelectedIndex(2); + + configuration.put(ARG_IMAGE_RESOLUTION, cbox_image_resolution); + GroupLayout gl_panel_configHTML = new GroupLayout(panel_configHTML); gl_panel_configHTML.setHorizontalGroup( @@ -590,9 +615,6 @@ public class ConfigurationWindow extends JFrame { .addGroup(gl_panel_configHTML.createSequentialGroup() .addGap(32) .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addComponent(cb_Pagination, GroupLayout.PREFERRED_SIZE, 303, GroupLayout.PREFERRED_SIZE) - .addContainerGap()) .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) .addGroup(gl_panel_configHTML.createSequentialGroup() .addComponent(lb_SplitByLevel, GroupLayout.PREFERRED_SIZE, 454, GroupLayout.PREFERRED_SIZE) @@ -651,12 +673,12 @@ public class ConfigurationWindow extends JFrame { .addComponent(lb_OutFilePath, GroupLayout.PREFERRED_SIZE, 191, GroupLayout.PREFERRED_SIZE)) .addPreferredGap(ComponentPlacement.RELATED) .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) - .addComponent(tf_OutputFile, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 579, Short.MAX_VALUE) - .addComponent(tf_inputFile, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 579, Short.MAX_VALUE)) - .addGap(13) + .addComponent(tf_OutputFile, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 586, Short.MAX_VALUE) + .addComponent(tf_inputFile, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 586, Short.MAX_VALUE)) + .addPreferredGap(ComponentPlacement.RELATED) .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) - .addComponent(btn_ChooseInputFile, GroupLayout.PREFERRED_SIZE, 113, GroupLayout.PREFERRED_SIZE) - .addComponent(btn_ChooseOutputFile, GroupLayout.PREFERRED_SIZE, 113, GroupLayout.PREFERRED_SIZE))) + .addComponent(btn_ChooseOutputFile, GroupLayout.PREFERRED_SIZE, 113, GroupLayout.PREFERRED_SIZE) + .addComponent(btn_ChooseInputFile, GroupLayout.PREFERRED_SIZE, 113, GroupLayout.PREFERRED_SIZE))) .addComponent(cb_UseMathJax, GroupLayout.PREFERRED_SIZE, 352, GroupLayout.PREFERRED_SIZE) .addComponent(cb_SplitWholePagesOnly, GroupLayout.PREFERRED_SIZE, 323, GroupLayout.PREFERRED_SIZE) .addGroup(gl_panel_configHTML.createSequentialGroup() @@ -666,75 +688,81 @@ public class ConfigurationWindow extends JFrame { .addComponent(tf_Scale, GroupLayout.PREFERRED_SIZE, 175, GroupLayout.PREFERRED_SIZE) .addComponent(tf_pageBreakInlineStyle, GroupLayout.DEFAULT_SIZE, 707, Short.MAX_VALUE) .addComponent(tf_MaxWidth, GroupLayout.PREFERRED_SIZE, 175, GroupLayout.PREFERRED_SIZE)))) - .addGap(145))))))))))))))) + .addGap(145))))))))))))) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) + .addComponent(cb_Pagination, GroupLayout.PREFERRED_SIZE, 303, GroupLayout.PREFERRED_SIZE) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addComponent(lb_ImageResolution, GroupLayout.PREFERRED_SIZE, 366, GroupLayout.PREFERRED_SIZE) + .addGap(4) + .addComponent(cbox_image_resolution, GroupLayout.PREFERRED_SIZE, 70, GroupLayout.PREFERRED_SIZE))) + .addGap(615)))) ); gl_panel_configHTML.setVerticalGroup( gl_panel_configHTML.createParallelGroup(Alignment.LEADING) .addGroup(gl_panel_configHTML.createSequentialGroup() + .addGap(12) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(lb_TargetFormat_description) + .addComponent(lb_TargetFormat)) + .addPreferredGap(ComponentPlacement.UNRELATED) .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(tf_inputFile, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(btn_ChooseInputFile)) .addGroup(gl_panel_configHTML.createSequentialGroup() - .addContainerGap() - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) - .addComponent(lb_TargetFormat_description) - .addComponent(lb_TargetFormat)) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) - .addComponent(tf_inputFile, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addGap(2) - .addComponent(lb_FilePath))) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) - .addComponent(lb_OutFilePath) - .addComponent(tf_OutputFile, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) - .addGap(12) - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) - .addComponent(lb_pageBreakInlineStyle) - .addComponent(tf_pageBreakInlineStyle, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) - .addGap(18) - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) - .addComponent(lb_Scale) - .addComponent(tf_Scale, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) - .addComponent(lb_MaxWidth) - .addComponent(tf_MaxWidth, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(ComponentPlacement.RELATED) - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) - .addComponent(lb_FilterLetterSpacing) - .addComponent(tf_FilterLetterSpacing, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addComponent(cb_InlineStyles) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addComponent(cb_EmbedVectorImages) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addComponent(cb_EmbedRaster) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addComponent(cb_convertToPx) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addComponent(cb_IgnoreHardLineBreaks) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addComponent(cb_IgnoreEmptyParagraphs) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addComponent(cb_Greenstone) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) - .addComponent(lb_SplitByLevel, GroupLayout.PREFERRED_SIZE, 16, GroupLayout.PREFERRED_SIZE) - .addComponent(tf_SplitByLevel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(ComponentPlacement.RELATED) - .addComponent(cb_SplitWholePagesOnly) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addComponent(cb_UseMathJax) - .addPreferredGap(ComponentPlacement.UNRELATED) - .addComponent(cb_Pagination) - .addPreferredGap(ComponentPlacement.RELATED, 128, Short.MAX_VALUE)) - .addGroup(gl_panel_configHTML.createSequentialGroup() - .addGap(34) - .addComponent(btn_ChooseInputFile) - .addGap(10) - .addComponent(btn_ChooseOutputFile) - .addPreferredGap(ComponentPlacement.RELATED, 414, Short.MAX_VALUE))) - .addGap(118)) + .addGap(2) + .addComponent(lb_FilePath))) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(lb_OutFilePath) + .addComponent(tf_OutputFile, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(btn_ChooseOutputFile)) + .addGap(12) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(lb_pageBreakInlineStyle) + .addComponent(tf_pageBreakInlineStyle, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addGap(18) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(lb_Scale) + .addComponent(tf_Scale, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(lb_MaxWidth) + .addComponent(tf_MaxWidth, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(lb_FilterLetterSpacing) + .addComponent(tf_FilterLetterSpacing, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(cb_InlineStyles) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(cb_EmbedVectorImages) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(cb_EmbedRaster) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(cb_convertToPx) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(cb_IgnoreHardLineBreaks) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(cb_IgnoreEmptyParagraphs) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(cb_Greenstone) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(lb_SplitByLevel, GroupLayout.PREFERRED_SIZE, 16, GroupLayout.PREFERRED_SIZE) + .addComponent(tf_SplitByLevel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(cb_SplitWholePagesOnly) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(cb_UseMathJax) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(cb_Pagination) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(lb_ImageResolution) + .addComponent(cbox_image_resolution, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addGap(101)) ); panel_configHTML.setLayout(gl_panel_configHTML); return panel_configHTML; @@ -808,11 +836,11 @@ public class ConfigurationWindow extends JFrame { configuration.put(ARG_USE_MATHJAX, cb_UseMathJax); JCheckBox cb_IgnoreEmptyParagraphs = new JCheckBox(localizer.getTranslation(LABEL_INGNORE_EMPTY_PARS)); - cb_IgnoreEmptyParagraphs.setSelected(true); + cb_IgnoreEmptyParagraphs.setSelected(false); configuration.put(ARG_IGNORE_EMPTY_PARAGRAPHS, cb_IgnoreEmptyParagraphs); JCheckBox cb_IgnoreHardLineBreaks = new JCheckBox(localizer.getTranslation(LABEL_FILETER_HARD_LINE_BREAKS)); - cb_IgnoreHardLineBreaks.setSelected(true); + cb_IgnoreHardLineBreaks.setSelected(false); configuration.put(ARG_IGNORE_HARD_LINE_BREAKS, cb_IgnoreHardLineBreaks); JLabel lb_FilterLetterSpacing = new JLabel(localizer.getTranslation(LABEL_MIN_LETTER_SPACING)); @@ -927,6 +955,12 @@ public class ConfigurationWindow extends JFrame { JCheckBox cb_Pagination = new JCheckBox(localizer.getTranslation(LABEL_PAGINATION)); configuration.put(ARG_PAGINATION, cb_Pagination); + + JLabel lb_ImageResolution = new JLabel(localizer.getTranslation(LABEL_IMAGE_RESOLUTION)); + + JComboBox cbox_image_resolution = new JComboBox(resolutions); + configuration.put(ARG_IMAGE_RESOLUTION, cbox_image_resolution); + cbox_image_resolution.setSelectedIndex(2); GroupLayout gl_panel_configHTML = new GroupLayout(panel_configHTML); @@ -936,9 +970,14 @@ public class ConfigurationWindow extends JFrame { .addGap(32) .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) .addGroup(gl_panel_configHTML.createSequentialGroup() - .addComponent(cb_Pagination, GroupLayout.PREFERRED_SIZE, 303, GroupLayout.PREFERRED_SIZE) + .addComponent(lb_ImageResolution, GroupLayout.PREFERRED_SIZE, 369, GroupLayout.PREFERRED_SIZE) + .addGap(4) + .addComponent(cbox_image_resolution, GroupLayout.PREFERRED_SIZE, 70, GroupLayout.PREFERRED_SIZE) .addContainerGap()) .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) + .addGroup(gl_panel_configHTML.createSequentialGroup() + .addComponent(cb_Pagination, GroupLayout.PREFERRED_SIZE, 303, GroupLayout.PREFERRED_SIZE) + .addContainerGap()) .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) .addGroup(gl_panel_configHTML.createSequentialGroup() .addComponent(cb_convertToPx, GroupLayout.PREFERRED_SIZE, 592, GroupLayout.PREFERRED_SIZE) @@ -972,12 +1011,12 @@ public class ConfigurationWindow extends JFrame { .addPreferredGap(ComponentPlacement.RELATED) .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) .addComponent(lb_TargetFormat, GroupLayout.PREFERRED_SIZE, 68, GroupLayout.PREFERRED_SIZE) - .addComponent(tf_OutputFile, GroupLayout.DEFAULT_SIZE, 572, Short.MAX_VALUE) + .addComponent(tf_OutputFile, GroupLayout.DEFAULT_SIZE, 561, Short.MAX_VALUE) .addGroup(gl_panel_configHTML.createSequentialGroup() - .addComponent(tf_metadataPath, GroupLayout.DEFAULT_SIZE, 571, Short.MAX_VALUE) + .addComponent(tf_metadataPath, GroupLayout.DEFAULT_SIZE, 560, Short.MAX_VALUE) .addGap(1)) .addGroup(gl_panel_configHTML.createSequentialGroup() - .addComponent(tf_inputFile, GroupLayout.DEFAULT_SIZE, 569, Short.MAX_VALUE) + .addComponent(tf_inputFile, GroupLayout.DEFAULT_SIZE, 558, Short.MAX_VALUE) .addGap(3))))) .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.LEADING) .addGroup(gl_panel_configHTML.createSequentialGroup() @@ -993,7 +1032,7 @@ public class ConfigurationWindow extends JFrame { .addGroup(gl_panel_configHTML.createSequentialGroup() .addComponent(lb_pageBreakInlineStyle, GroupLayout.PREFERRED_SIZE, 196, GroupLayout.PREFERRED_SIZE) .addPreferredGap(ComponentPlacement.RELATED) - .addComponent(tf_pageBreakInlineStyle, GroupLayout.DEFAULT_SIZE, 692, Short.MAX_VALUE) + .addComponent(tf_pageBreakInlineStyle, GroupLayout.DEFAULT_SIZE, 681, Short.MAX_VALUE) .addGap(145)) .addGroup(gl_panel_configHTML.createSequentialGroup() .addComponent(lb_type, GroupLayout.PREFERRED_SIZE, 148, GroupLayout.PREFERRED_SIZE) @@ -1078,7 +1117,11 @@ public class ConfigurationWindow extends JFrame { .addComponent(cb_UseMathJax) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(cb_Pagination) - .addContainerGap(113, Short.MAX_VALUE)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(gl_panel_configHTML.createParallelGroup(Alignment.BASELINE) + .addComponent(lb_ImageResolution) + .addComponent(cbox_image_resolution, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addContainerGap(87, Short.MAX_VALUE)) ); panel_configHTML.setLayout(gl_panel_configHTML); return panel_configHTML; diff --git a/src/main/java/pro/litvinovg/w2phtml/gui/localizations/w2phtml.properties b/src/main/java/pro/litvinovg/w2phtml/gui/localizations/w2phtml.properties index 607f184..bfa6cdc 100644 --- a/src/main/java/pro/litvinovg/w2phtml/gui/localizations/w2phtml.properties +++ b/src/main/java/pro/litvinovg/w2phtml/gui/localizations/w2phtml.properties @@ -26,4 +26,5 @@ label_type=Type label_split_by_heading=Split into multiple files by heading level label_html5=html5 error_cant_write=Attention. Can't save file in output directory. -message_not_implemented=Not implemented \ No newline at end of file +message_not_implemented=Not implemented +label_image_resolution=Resize image resolution to (PPI) \ No newline at end of file diff --git a/src/main/java/pro/litvinovg/w2phtml/gui/localizations/w2phtml_ru.properties b/src/main/java/pro/litvinovg/w2phtml/gui/localizations/w2phtml_ru.properties index 24920e4..e3b230a 100644 --- a/src/main/java/pro/litvinovg/w2phtml/gui/localizations/w2phtml_ru.properties +++ b/src/main/java/pro/litvinovg/w2phtml/gui/localizations/w2phtml_ru.properties @@ -26,4 +26,5 @@ label_type=Тип документа label_split_by_heading=Разделить на файлы по заголовкам до уровня (включительно) label_html5=html5 error_cant_write=Ошибка. Не удалось сохранить файл в целевую директорию -message_not_implemented=Данная функциональность еще не реализована \ No newline at end of file +message_not_implemented=Данная функциональность еще не реализована +label_image_resolution=Уменьшить разрешение изображений до (PPI) \ No newline at end of file diff --git a/src/main/java/w2phtml/base/BinaryGraphicsDocument.java b/src/main/java/w2phtml/base/BinaryGraphicsDocument.java index 00834a5..f7386a4 100644 --- a/src/main/java/w2phtml/base/BinaryGraphicsDocument.java +++ b/src/main/java/w2phtml/base/BinaryGraphicsDocument.java @@ -39,11 +39,15 @@ import javax.imageio.ImageIO; import org.apache.commons.imaging.ImageInfo; import org.apache.commons.imaging.ImageReadException; import org.apache.commons.imaging.Imaging; +import org.imgscalr.Scalr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import w2phtml.api.OutputFile; import w2phtml.office.MIMETypes; import w2phtml.office.StyleWithProperties; import w2phtml.util.DimensionsConverter; +import w2phtml.xhtml.XhtmlConfig; /** This class is used to represent a binary graphics document to be included in the converter result. * I may also represent a linked image, which should not be included (and will produce an empty file @@ -65,6 +69,8 @@ public class BinaryGraphicsDocument implements OutputFile { private boolean cropped = false; private float horizontalPPI = 96.0F; private float verticalPPI = 96.0F; + private static final Logger logger = LoggerFactory.getLogger(BinaryGraphicsDocument.class); + /**Constructs a new graphics document. * Until data is added using the read methods, the document is considered a link to @@ -106,6 +112,7 @@ public class BinaryGraphicsDocument implements OutputFile { this.horizontalPPI = widthDPI; } } catch (ImageReadException | IOException e) { + logger.error("Image " + sFileName + "error reading image info."); e.printStackTrace(); } @@ -216,29 +223,24 @@ public class BinaryGraphicsDocument implements OutputFile { /* Crop image from byte array */ public void cropImage(StyleWithProperties style) { - if (blob == null || style == null) { - return; - } - if (sMimeType == null || ( - !sMimeType.equals(MIMETypes.PNG) - && !sMimeType.equals(MIMETypes.JPEG) - && !sMimeType.equals(MIMETypes.GIF) - && !sMimeType.equals(MIMETypes.TIFF) - )){ + if (blob == null || style == null || isInvalidImageFormat()) { return; } extractPPI(); int[] offsets = getOffsets(style); - if (offsets[0] == 0 && offsets[1] == 0 && offsets[2] == 0 && offsets[3] == 0) { + if (isNotCropped(offsets)) { return; } ByteArrayInputStream bis = new ByteArrayInputStream(blob); try { BufferedImage image = ImageIO.read(bis); + if (image == null) { + logger.error("Image " + sFileName + " couldn't be processed as it is damaged or has unknown format."); + return; + } int height = image.getHeight(); int width = image.getWidth(); - String formatName = MIMETypes.getFormatType(blob); int leftOffset = offsets[3]; int topOffset = offsets[0]; int newWidth = width - offsets[3] - offsets[1]; @@ -251,13 +253,64 @@ public class BinaryGraphicsDocument implements OutputFile { this.cropped = true; updateFileName(offsets); } catch (IOException e) { - // TODO Auto-generated catch block + logger.error("Image " + sFileName + " " + e.getLocalizedMessage()); e.printStackTrace(); } catch (RasterFormatException e ) { - System.out.println(e.getLocalizedMessage()); + logger.error("Image " + sFileName + " " + e.getLocalizedMessage()); e.printStackTrace(); } + } + + public void applyQuality(StyleWithProperties style, XhtmlConfig config) { + float targetPPI = config.getImageResolution(); + //int targetQuality = config.getImageQuality(); + //float quality = targetQuality / 100; + if (blob == null || style == null || isInvalidImageFormat()) { + return; + } + extractPPI(); + if (targetPPI >= verticalPPI || targetPPI >= horizontalPPI ) { + return; + } + float minPPI = Math.min(verticalPPI, horizontalPPI); + double divider = minPPI / targetPPI; + ByteArrayInputStream bis = new ByteArrayInputStream(blob); + try { + BufferedImage image = ImageIO.read(bis); + if (image == null) { + logger.error("Image " + sFileName + " couldn't be processed as it is damaged or has unknown format."); + return; + } + int width = image.getWidth(); + if (width > 0) { + Integer newWidth = (int) ( width/divider); + BufferedImage resizedImage = Scalr.resize(image, newWidth); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(resizedImage, "JPG", baos); + this.blob = baos.toByteArray(); + extractPPI(); + //logger.error(sFileName + " Vertical PPI " + this.verticalPPI); + //logger.error(sFileName + " Horizontal PPI " + this.horizontalPPI); + } else { + logger.error("Image " + sFileName + " width = 0"); + } + } catch (IOException e) { + logger.error("Image " + sFileName + " " + e.getLocalizedMessage()); + e.printStackTrace(); + } + } + private boolean isNotCropped(int[] offsets) { + return offsets[0] == 0 && offsets[1] == 0 && offsets[2] == 0 && offsets[3] == 0; + } + + private boolean isInvalidImageFormat() { + return sMimeType == null || ( + !sMimeType.equals(MIMETypes.PNG) + && !sMimeType.equals(MIMETypes.JPEG) + && !sMimeType.equals(MIMETypes.GIF) + && !sMimeType.equals(MIMETypes.TIFF) + ); } private void updateFileName(int[] offsets) { @@ -300,4 +353,7 @@ public class BinaryGraphicsDocument implements OutputFile { public boolean containsMath() { return false; } + + + } \ No newline at end of file diff --git a/src/main/java/w2phtml/xhtml/XhtmlConfig.java b/src/main/java/w2phtml/xhtml/XhtmlConfig.java index 347343c..8f717b4 100644 --- a/src/main/java/w2phtml/xhtml/XhtmlConfig.java +++ b/src/main/java/w2phtml/xhtml/XhtmlConfig.java @@ -40,7 +40,7 @@ import w2phtml.util.Misc; public class XhtmlConfig extends w2phtml.base.ConfigBase { // Implement configuration methods - protected int getOptionCount() { return 65; } + protected int getOptionCount() { return 66; } protected String getDefaultConfigPath() { return "/writer2latex/xhtml/config/"; } // Override setOption: To be backwards compatible, we must accept options @@ -164,6 +164,7 @@ public class XhtmlConfig extends w2phtml.base.ConfigBase { private static final int PAGE_BREAK_STYLE = 62; private static final int ANNOTATION_METADATA = 63; private static final int RDF_TYPE = 64; + private static final int IMAGE_RESOLUTION = 65; protected ComplexOption xheading = addComplexOption("heading-map"); protected ComplexOption xpar = addComplexOption("paragraph-map"); @@ -298,8 +299,12 @@ public class XhtmlConfig extends w2phtml.base.ConfigBase { options[CSS_INLINE] = new BooleanOption("css_inline","true"); options[ALIGN_SPLITS_TO_PAGES] = new BooleanOption("align_splits_to_pages","false"); options[ANNOTATION_METADATA] = new BooleanOption("annotation_metad","true"); - - + options[IMAGE_RESOLUTION] = new IntegerOption("image_resolution","0") { + @Override public void setString(String sValue) { + super.setString(sValue); + nValue = Misc.getPosInteger(sValue,0); + } + }; } @@ -444,7 +449,7 @@ public class XhtmlConfig extends w2phtml.base.ConfigBase { public String getXhtmlDocumentIcon() { return options[DOCUMENT_ICON].getString(); } public String getCSVMetadataFile() { return options[CSV_METADATA].getString(); } public String getRDFType() { return options[RDF_TYPE].getString(); } - + public int getImageResolution() { return ((IntegerOption) options[IMAGE_RESOLUTION]).getValue(); } public boolean getGreenstoneSeparation() { if ( ((IntegerOption) options[SPLIT_LEVEL]).getValue() != 0) { @@ -484,5 +489,6 @@ public class XhtmlConfig extends w2phtml.base.ConfigBase { public boolean useAnnotationMetadata() { return ((BooleanOption) options[ANNOTATION_METADATA]).getValue(); } + } diff --git a/src/main/java/w2phtml/xhtml/content/DrawParser.java b/src/main/java/w2phtml/xhtml/content/DrawParser.java index ef2a6d3..942befb 100644 --- a/src/main/java/w2phtml/xhtml/content/DrawParser.java +++ b/src/main/java/w2phtml/xhtml/content/DrawParser.java @@ -541,6 +541,7 @@ public class DrawParser extends Parser { if (bgd!=null) { StyleWithProperties style = ofr.getFrameStyle(frame.getAttribute(XMLString.DRAW_STYLE_NAME)); bgd.cropImage(style); + bgd.applyQuality(style,config); if (!bgd.isLinked()) { // embedded image sFileName = bgd.getFileName(); // If this is the cover image, add it to the converter result