From 2a25f7814eec9854022f1c9dee188bfbdb955591 Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Wed, 29 Nov 2017 21:02:19 +0100 Subject: [PATCH] Update nikiroo-utils, bugfixes: - covers were sometimes not found (so not displayed or not deleted) - images could fail to save in JPG mode (now, we retry in PNG) - covers were not sent over the network (still need more tests) - some tmp files were not deleted in case of an import failure --- changelog.md | 3 ++ ...es.jar => nikiroo-utils-3.1.2-sources.jar} | Bin 271032 -> 274642 bytes src/be/nikiroo/fanfix/DataLoader.java | 43 ++++++++++++++++-- src/be/nikiroo/fanfix/data/Paragraph.java | 23 +++++++--- .../nikiroo/fanfix/library/LocalLibrary.java | 9 ++-- .../fanfix/library/RemoteLibraryServer.java | 23 ++++++---- src/be/nikiroo/fanfix/output/Cbz.java | 26 ++++++----- src/be/nikiroo/fanfix/output/Epub.java | 3 +- src/be/nikiroo/fanfix/output/Text.java | 3 +- .../fanfix/supported/BasicSupport.java | 6 +-- src/be/nikiroo/fanfix/supported/Cbz.java | 39 +++++++--------- .../nikiroo/fanfix/supported/InfoReader.java | 5 +- .../nikiroo/fanfix/test/BasicSupportTest.java | 2 +- src/be/nikiroo/fanfix/test/LibraryTest.java | 2 +- src/be/nikiroo/fanfix/test/Test.java | 8 ++++ 15 files changed, 126 insertions(+), 69 deletions(-) rename libs/{nikiroo-utils-3.0.0-sources.jar => nikiroo-utils-3.1.2-sources.jar} (80%) diff --git a/changelog.md b/changelog.md index d36c87f6..41028127 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,9 @@ - Bug fixes - Remote server/client improvements - Better support for some CBZ files (if SUMMARY or URL files are present in it) +- Fix cover images not deleted on story delete +- Fix some images not supported because not jpeg-able (now try again in png) +- Fix some covers not found (normal and remote hopefully) ## Version 1.6.2 diff --git a/libs/nikiroo-utils-3.0.0-sources.jar b/libs/nikiroo-utils-3.1.2-sources.jar similarity index 80% rename from libs/nikiroo-utils-3.0.0-sources.jar rename to libs/nikiroo-utils-3.1.2-sources.jar index 82feb00ed344bcc6ad54ea0ec897f03e8f454406..ec1ed6edf838b46b9fbb7d4c3eb3ab343690d42c 100644 GIT binary patch delta 23915 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 delta 20480 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 F{U0IH4=Dfu diff --git a/src/be/nikiroo/fanfix/DataLoader.java b/src/be/nikiroo/fanfix/DataLoader.java index 2fd59d89..25300130 100644 --- a/src/be/nikiroo/fanfix/DataLoader.java +++ b/src/be/nikiroo/fanfix/DataLoader.java @@ -1,5 +1,6 @@ package be.nikiroo.fanfix; +import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -228,16 +229,48 @@ public class DataLoader { public void saveAsImage(URL url, File target) throws IOException { InputStream in = open(url, null, true); try { - ImageIO.write(ImageUtils.fromStream(in), Instance.getConfig() - .getString(Config.IMAGE_FORMAT_CONTENT).toLowerCase(), - target); - } catch (IOException e) { - throw new IOException("Cannot write image " + url, e); + saveAsImage(ImageUtils.fromStream(in), target); } finally { in.close(); } } + /** + * Save the given resource as an image on disk using the default image + * format for content. + * + * @param image + * the resource + * @param target + * the target file + * + * @throws IOException + * in case of I/O error + */ + public void saveAsImage(BufferedImage image, File target) + throws IOException { + try { + String format = Instance.getConfig() + .getString(Config.IMAGE_FORMAT_CONTENT).toLowerCase(); + boolean ok = ImageIO.write(image, format, target); + if (!ok) { + // Some formats are not reliable + // Second change: PNG + if (!format.equals("png")) { + ok = ImageIO.write(image, "png", target); + } + + if (!ok) { + throw new IOException( + "Cannot find a writer for this image and format: " + + format); + } + } + } catch (IOException e) { + throw new IOException("Cannot write image to " + target, e); + } + } + /** * Manually add this item to the cache. * diff --git a/src/be/nikiroo/fanfix/data/Paragraph.java b/src/be/nikiroo/fanfix/data/Paragraph.java index 273aca3a..a731c328 100644 --- a/src/be/nikiroo/fanfix/data/Paragraph.java +++ b/src/be/nikiroo/fanfix/data/Paragraph.java @@ -1,6 +1,6 @@ package be.nikiroo.fanfix.data; -import java.net.URL; +import java.awt.image.BufferedImage; /** * A paragraph in a chapter of the story. @@ -28,6 +28,7 @@ public class Paragraph { private ParagraphType type; private String content; + private BufferedImage contentImage; private long words; /** @@ -41,11 +42,12 @@ public class Paragraph { /** * Create a new {@link Paragraph} with the given image. * - * @param imageUrl - * the image as an URL + * @param contentImage + * the image */ - public Paragraph(URL imageUrl) { - this(ParagraphType.IMAGE, imageUrl.toString(), 1); + public Paragraph(BufferedImage contentImage) { + this(ParagraphType.IMAGE, null, 1); + this.contentImage = contentImage; } /** @@ -84,7 +86,7 @@ public class Paragraph { } /** - * The content of this {@link Paragraph}. + * The content of this {@link Paragraph} if it is not an image. * * @return the content */ @@ -102,6 +104,15 @@ public class Paragraph { this.content = content; } + /** + * The content of this {@link Paragraph} if it is an image. + * + * @return the content + */ + public BufferedImage getContentImage() { + return contentImage; + } + /** * The number of words (or images) in this {@link Paragraph}. * diff --git a/src/be/nikiroo/fanfix/library/LocalLibrary.java b/src/be/nikiroo/fanfix/library/LocalLibrary.java index 917ce093..4c454255 100644 --- a/src/be/nikiroo/fanfix/library/LocalLibrary.java +++ b/src/be/nikiroo/fanfix/library/LocalLibrary.java @@ -383,7 +383,8 @@ public class LocalLibrary extends BasicLibrary { } String coverExt = "." - + Instance.getConfig().getString(Config.IMAGE_FORMAT_COVER); + + Instance.getConfig().getString(Config.IMAGE_FORMAT_COVER) + .toLowerCase(); File coverFile = new File(path + coverExt); if (!coverFile.exists()) { coverFile = new File(path.substring(0, @@ -472,8 +473,10 @@ public class LocalLibrary extends BasicLibrary { } catch (IOException e) { // We should not have not-supported files in the // library - Instance.getTraceHandler().error(new IOException( - "Cannot load file from library: " + infoFile, e)); + Instance.getTraceHandler().error( + new IOException( + "Cannot load file from library: " + + infoFile, e)); } pgFiles.add(1); } diff --git a/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java b/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java index 58362938..b2689993 100644 --- a/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java +++ b/src/be/nikiroo/fanfix/library/RemoteLibraryServer.java @@ -14,20 +14,23 @@ import be.nikiroo.utils.serial.server.ServerObject; /** * Create a new remote server that will listen for order on the given port. *

- * The available commands are given as String arrays (first item is the key, - * second is the command, the rest are the arguments): + * The available commands are given as arrays of objects (first item is the key, + * second is the command, the rest are the arguments). + *

+ * The key is always a String, the commands are also Strings; the parameters + * vary depending upon the command. *

    - *
  • KEY GET_METADATA *: will return the metadata of all the stories in the + *
  • [key] GET_METADATA *: will return the metadata of all the stories in the * library
  • - *
  • KEY GET_STORY [luid]: will return the given story if it exists (or NULL + *
  • [key] GET_STORY [luid]: will return the given story if it exists (or NULL * if not)
  • - *
  • KEY SAVE_STORY [story] [luid]: save the story with the given LUID
  • - *
  • KEY DELETE_STORY [luid]: delete the story of LUID luid
  • - *
  • KEY GET_COVER [luid]: return the cover of the story
  • - *
  • KEY GET_SOURCE_COVER [source]: return the cover for this source
  • - *
  • KEY SET_SOURCE_COVER [source], [luid]: set the default cover for the + *
  • [key] SAVE_STORY [story] [luid]: save the story with the given LUID
  • + *
  • [key] DELETE_STORY [luid]: delete the story of LUID luid
  • + *
  • [key] GET_COVER [luid]: return the cover of the story
  • + *
  • [key] GET_SOURCE_COVER [source]: return the cover for this source
  • + *
  • [key] SET_SOURCE_COVER [source], [luid]: set the default cover for the * given source to the cover of the story denoted by luid
  • - *
  • KEY EXIT: stop the server
  • + *
  • [key] EXIT: stop the server
  • *
* * @author niki diff --git a/src/be/nikiroo/fanfix/output/Cbz.java b/src/be/nikiroo/fanfix/output/Cbz.java index c350eb24..c70cc412 100644 --- a/src/be/nikiroo/fanfix/output/Cbz.java +++ b/src/be/nikiroo/fanfix/output/Cbz.java @@ -25,25 +25,27 @@ class Cbz extends BasicOutput { dir = File.createTempFile("fanfic-reader-cbz-dir", ".wip"); dir.delete(); dir.mkdir(); + try { + // will also save the images! + new InfoText().process(story, dir, targetNameOrig); - // will also save the images! - new InfoText().process(story, dir, targetNameOrig); + InfoCover.writeInfo(dir, targetNameOrig, story.getMeta()); + if (story.getMeta() != null && !story.getMeta().isFakeCover()) { + InfoCover.writeCover(dir, targetNameOrig, story.getMeta()); + } - InfoCover.writeInfo(dir, targetNameOrig, story.getMeta()); - if (story.getMeta() != null && !story.getMeta().isFakeCover()) { - InfoCover.writeCover(dir, targetNameOrig, story.getMeta()); - } + IOUtils.writeSmallFile(dir, "version", "3.0"); - IOUtils.writeSmallFile(dir, "version", "3.0"); + try { + super.process(story, targetDir, targetNameOrig); + } finally { + } - try { - super.process(story, targetDir, targetNameOrig); + IOUtils.zip(dir, target, true); } finally { + IOUtils.deltree(dir); } - IOUtils.zip(dir, target, true); - IOUtils.deltree(dir); - return target; } diff --git a/src/be/nikiroo/fanfix/output/Epub.java b/src/be/nikiroo/fanfix/output/Epub.java index 869a0bc2..2c47dcbc 100644 --- a/src/be/nikiroo/fanfix/output/Epub.java +++ b/src/be/nikiroo/fanfix/output/Epub.java @@ -6,7 +6,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; -import java.net.URL; import javax.imageio.ImageIO; @@ -209,7 +208,7 @@ class Epub extends BasicOutput { break; case IMAGE: File file = new File(images, getCurrentImageBestName(false)); - Instance.getCache().saveAsImage(new URL(para.getContent()), file); + Instance.getCache().saveAsImage(para.getContentImage(), file); writer.write(" "); break; diff --git a/src/be/nikiroo/fanfix/output/Text.java b/src/be/nikiroo/fanfix/output/Text.java index 28f3894b..ee72385b 100644 --- a/src/be/nikiroo/fanfix/output/Text.java +++ b/src/be/nikiroo/fanfix/output/Text.java @@ -5,7 +5,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; -import java.net.URL; import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.bundles.StringId; @@ -105,7 +104,7 @@ class Text extends BasicOutput { protected void writeParagraphHeader(Paragraph para) throws IOException { if (para.getType() == ParagraphType.IMAGE) { File file = new File(targetDir, getCurrentImageBestName(true)); - Instance.getCache().saveAsImage(new URL(para.getContent()), file); + Instance.getCache().saveAsImage(para.getContentImage(), file); } } diff --git a/src/be/nikiroo/fanfix/supported/BasicSupport.java b/src/be/nikiroo/fanfix/supported/BasicSupport.java index ae7521ef..c609c703 100644 --- a/src/be/nikiroo/fanfix/supported/BasicSupport.java +++ b/src/be/nikiroo/fanfix/supported/BasicSupport.java @@ -757,10 +757,10 @@ public abstract class BasicSupport { * @return the {@link Paragraph} */ private Paragraph makeParagraph(URL source, String line) { - URL image = null; + BufferedImage image = null; if (line.startsWith("[") && line.endsWith("]")) { - image = getImageUrl(this, source, - line.substring(1, line.length() - 1).trim()); + image = getImage(this, source, line.substring(1, line.length() - 1) + .trim()); } if (image != null) { diff --git a/src/be/nikiroo/fanfix/supported/Cbz.java b/src/be/nikiroo/fanfix/supported/Cbz.java index 02c667c1..f67f28ae 100644 --- a/src/be/nikiroo/fanfix/supported/Cbz.java +++ b/src/be/nikiroo/fanfix/supported/Cbz.java @@ -1,22 +1,22 @@ package be.nikiroo.fanfix.supported; import java.awt.image.BufferedImage; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import javax.imageio.ImageIO; - import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.data.Chapter; import be.nikiroo.fanfix.data.Paragraph; import be.nikiroo.fanfix.data.Story; +import be.nikiroo.utils.ImageUtils; import be.nikiroo.utils.Progress; /** @@ -68,9 +68,7 @@ class Cbz extends Epub { Progress pgMeta = new Progress(); pg.addProgress(pgMeta, 10); Story story = processMeta(url, false, true, pgMeta); - if (!pgMeta.isDone()) { - pgMeta.setProgress(pgMeta.getMax()); // 10% - } + pgMeta.done(); // 10% story.setChapters(new ArrayList()); Chapter chap = new Chapter(1, null); @@ -78,7 +76,7 @@ class Cbz extends Epub { ZipInputStream zipIn = new ZipInputStream(getInput()); - List images = new ArrayList(); + Map images = new HashMap(); for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn .getNextEntry()) { if (!entry.isDirectory() @@ -94,39 +92,36 @@ class Cbz extends Epub { if (imageEntry) { String uuid = meta.getUuid() + "_" + entry.getName(); try { - File tmp = Instance.getCache().addToCache(zipIn, uuid); - images.add(tmp.toURI().toURL().toString()); + images.put(uuid, ImageUtils.fromStream(zipIn)); } catch (Exception e) { Instance.getTraceHandler().error(e); } + + if (pg.getProgress() < 85) { + pg.add(1); + } } } } - pg.setProgress(80); + pg.setProgress(85); // ZIP order is not correct for us - Collections.sort(images); + List imagesList = new ArrayList(images.keySet()); + Collections.sort(imagesList); + pg.setProgress(90); - for (String uuid : images) { + for (String uuid : imagesList) { try { - chap.getParagraphs().add(new Paragraph(new URL(uuid))); + chap.getParagraphs().add(new Paragraph(images.get(uuid))); } catch (Exception e) { Instance.getTraceHandler().error(e); } } if (meta.getCover() == null && !images.isEmpty()) { - InputStream in = Instance.getCache().open(new URL(images.get(0)), - this, true); - try { - BufferedImage fcover = ImageIO.read(in); - meta.setCover(fcover); - meta.setFakeCover(true); - } finally { - in.close(); - } + meta.setCover(images.get(imagesList.get(0))); } pg.setProgress(100); diff --git a/src/be/nikiroo/fanfix/supported/InfoReader.java b/src/be/nikiroo/fanfix/supported/InfoReader.java index 466a8853..ccffd7c9 100644 --- a/src/be/nikiroo/fanfix/supported/InfoReader.java +++ b/src/be/nikiroo/fanfix/supported/InfoReader.java @@ -64,8 +64,9 @@ public class InfoReader { if (info.endsWith(".info")) { info = info.substring(0, info.length() - ".info".length()); String ext = "." - + Instance.getConfig().getString( - Config.IMAGE_FORMAT_COVER); + + Instance.getConfig() + .getString(Config.IMAGE_FORMAT_COVER) + .toLowerCase(); meta.setCover(BasicSupport.getImage(null, sourceInfoFile, info + ext)); } diff --git a/src/be/nikiroo/fanfix/test/BasicSupportTest.java b/src/be/nikiroo/fanfix/test/BasicSupportTest.java index af33f9d0..dba0ef02 100644 --- a/src/be/nikiroo/fanfix/test/BasicSupportTest.java +++ b/src/be/nikiroo/fanfix/test/BasicSupportTest.java @@ -21,7 +21,7 @@ import be.nikiroo.utils.Progress; import be.nikiroo.utils.test.TestCase; import be.nikiroo.utils.test.TestLauncher; -public class BasicSupportTest extends TestLauncher { +class BasicSupportTest extends TestLauncher { // quote chars private char openQuote = Instance.getTrans().getCharacter( StringId.OPEN_SINGLE_QUOTE); diff --git a/src/be/nikiroo/fanfix/test/LibraryTest.java b/src/be/nikiroo/fanfix/test/LibraryTest.java index 43ca0879..fc61e7dd 100644 --- a/src/be/nikiroo/fanfix/test/LibraryTest.java +++ b/src/be/nikiroo/fanfix/test/LibraryTest.java @@ -15,7 +15,7 @@ import be.nikiroo.utils.IOUtils; import be.nikiroo.utils.test.TestCase; import be.nikiroo.utils.test.TestLauncher; -public class LibraryTest extends TestLauncher { +class LibraryTest extends TestLauncher { private BasicLibrary lib; private File tmp; diff --git a/src/be/nikiroo/fanfix/test/Test.java b/src/be/nikiroo/fanfix/test/Test.java index 0dc544b8..3ff9a7ab 100644 --- a/src/be/nikiroo/fanfix/test/Test.java +++ b/src/be/nikiroo/fanfix/test/Test.java @@ -17,6 +17,13 @@ import be.nikiroo.utils.test.TestLauncher; * @author niki */ public class Test extends TestLauncher { + /** + * Create the Fanfix {@link TestLauncher}. + * + * @param args + * the arguments to configure the number of columns and the ok/ko + * {@link String}s + */ public Test(String[] args) { super("Fanfix", args); Instance.setTraceHandler(null); @@ -30,6 +37,7 @@ public class Test extends TestLauncher { * @param args * the arguments passed to the {@link TestLauncher}s. * @throws IOException + * in case of I/O error */ static public void main(String[] args) throws IOException { File tmpConfig = File.createTempFile("fanfix-config_", ".test"); -- 2.27.0