-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Thumbnail generation #17
Conversation
* Reduces memory usage by using a base64.Decoder instead of storing the temp image in memory. * Simplified resize logic. * Reorganize koboCover stuff. * Extract image dir hashing to util. * Use filepath instead of path.
* Loop over cover types instead of duplicating code * Fix: Create the parent dir for images * Show errors from imaging.Encode * Close files sooner
kobo-uncaged/main.go
Outdated
} | ||
for _, cover := range []koboCover{libFull, libGrid} { | ||
nsz := resizeKeepAspectRatioByExpanding(sz, cover.Size(ku.device)) | ||
nimg := imaging.Resize(img, nsz.X, nsz.Y, imaging.Linear) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which image resize library/algorithm are we planning to use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may have to upscale the full cover, so an algorithm that's only decent for downscaling probably isn't the best idea.
Rez seemed pretty quick, so I would be happy with that. Bilinear or Bicubic perhaps. Or we could make the algorithm selectable in the config file, and the quality purists among us can select a better algorithm if they want to take the performance hit.
* Also fixed bug in hashedImageParts about forgetting to return dir1 and dir2
* Also fixed file extension
This is ready for testing (and choosing the resize library/algorithm). |
Just added a small update to request the full size cover from Calibre, so we aren't upscaling a tiny thumbnail! |
Nickel still appears to be generating its own thumbnails for me. It is very obvious when sending larger numbers of books at a time (eg: > 5 books). It may appear to work when sending one or two books, but I don't think it actually is. I'm going out in a few minutes, but I'll try and do some more investigation when I get back later. |
Yep, confirmed. I'm not getting anything (thumbnails-wise) getting generated by KU. It's easy enough to check by SSH'ing into the device while it's still connected to Calibre. Now, zilch. And Nickel indeed generates all three in one go the first time you open the Library (or earlier if one pops up at the front of one of the Home tiles, generally, My Books, which will definitely happen for one book if it's fresh). |
Ok, I'll test this myself once I get Calibre and my old Kobo Mini set up (probably tomorrow). I've been working on this blindly so far. Is there anything in the logs? Update: Oh, I think I know why. I forgot the |
Oh, right, found a few of 'em in The set isn't complete, though, sometimes I have a Will check again w/ the latest commit ;). |
Okay, yeah, I'm only ever getting KU to generate |
I'm also getting slightly wonky thumbnail sizes: Given a Calibre cover.jpg @ 1391x2200, I'd expect GRID to be 149x236, but it's 149x352; and LIB_FULL to be 355x561, but it's 355x838 This is possibly a side-effect of what Calibre sends as a source? |
Ok, can see why the full cover isn't been created. Just need to add it to the array at Not sure about the thumbnail sizes, but it looks to me like the wrong axis is being scaled. Calibre sends a base64 string, and a separate width and height. |
That's all it's currently configured to generate. Should I add
The algorithm has not been changed yet.
Possibly. Can you check what Qt does with them? |
The numbers I pulled were from my quick'n dirty Python port of Qt's QSize:scaled, but based on the original cover resolution, which is potentially not what's actually happening here ;). |
Yep, after a bit of extra logging, Note that the full cover should also not be using |
Could you provide some test data for it?
Good catch. I'll implement that next. |
On the full cover, I just had a thought that I might make generating it a configurable option. Point of that is, there are probably others, like me, who disable showing the cover on the sleep screen, so the full cover isn't used (unless it's used else where that I don't know of). Not using the full cover means requesting a smaller image from Calibre, which means a smaller transfer, and quicker downscaling. Thoughts? |
If Point is an int, doesn't the division need to explicitly cast to a float so we get anything useful out of it, instead of 1 or 0? |
@NiLuJe Yes. TBH, I haven't actually got my head completely wrapped around the logic behind the Qt equations (and now I realize that my unit tests didn't include fractional ratios). |
@geek1011 : This simple change made it easier to grok on my end, but that may be fairly subjective ^^: diff --git a/kobo-uncaged/util.go b/kobo-uncaged/util.go
index 6f9d37a..ddbc894 100644
--- a/kobo-uncaged/util.go
+++ b/kobo-uncaged/util.go
@@ -79,7 +79,8 @@ func resizeKeepAspectRatio(sz image.Point, bounds image.Point, expand bool) imag
}
var useHeight bool
- rw := int(float64(bounds.Y) * float64(sz.X) / float64(sz.Y))
+ ar := float64(sz.X) / float64(sz.Y)
+ rw := int(float64(bounds.Y) * ar)
if !expand {
useHeight = rw <= bounds.X
@@ -90,7 +91,7 @@ func resizeKeepAspectRatio(sz image.Point, bounds image.Point, expand bool) imag
if useHeight {
return image.Pt(rw, bounds.Y)
}
- return image.Pt(bounds.X, int(float64(bounds.X)*float64(sz.Y)/float64(sz.X)))
+ return image.Pt(bounds.X, int(float64(bounds.X) / ar))
}
// hashedImageParts returns the parts needed for constructing the path to the EDIT: |
As for my bit of logging: diff --git a/kobo-uncaged/main.go b/kobo-uncaged/main.go
index 365ab7e..05c4563 100644
--- a/kobo-uncaged/main.go
+++ b/kobo-uncaged/main.go
@@ -498,6 +498,7 @@ func (ku *KoboUncaged) saveCoverImage(contentID string, size image.Point, imgB64
for _, cover := range []koboCover{fullCover, libFull, libGrid} {
nsz := cover.Resize(ku.device, sz)
nimg := imaging.Resize(img, nsz.X, nsz.Y, imaging.Linear)
+ log.Printf("Resized %dx%d cover to %dx%d -> %dx%d => %dx%d\n", sz.X, sz.Y, cover.Size(ku.device).X, cover.Size(ku.device).Y, nsz.X, nsz.Y, nimg.Bounds().Size().X, nimg.Bounds().Size().Y)
nfn := filepath.Join(imgDir, cover.RelPath(imgID))
if err := os.MkdirAll(filepath.Dir(nfn), 0755); err != nil { And success:
Well, almost, because we could essentially skip the scaling pass for the full cover if That should hopefully be the most common case with sane Calibre libraries, and would alleviate some of @shermp's concerns ;). |
* Better logging for image resizr * More readable resize formula
Fixed an issue with the WaitGroup. It actually does what it was supposed to now! I REALLY wouldn't recommend sending large numbers of books at the moment. It is slooooow. Stick to three max. |
I'll take the thumbs up as confirmation :) Thank you both very much. |
Based on our (@geek1011, @NiLuJe) previous work for @shermp's Kobo-UNCaGED (shermp/Kobo-UNCaGED#17)
Reworks the thumbnail generation to be faster and better match Kobo's behavior.
See #16 and #9.