NikitaIvanovV / ctpv

Image previews for lf file manager
https://www.nikitaivanov.com/man1/ctpv
MIT License
264 stars 24 forks source link

Add dark/black/negative PDF preview #35

Open Andrew15-5 opened 1 year ago

Andrew15-5 commented 1 year ago

I looked up, and it seems there is no support for dark PDF preview like in stpv:

DARK_DOCS=                # invert documents preview color in image previews

https://github.com/Naheel-Azawy/stpv/blob/5c6058cc4afe289bdcb89bc0eaab84bd1df8f14d/stpv#L282-L286:

    if [ -n "$is_doc" ] && [ -n "$DARK_DOCS" ]; then
        dark_opts='-channel RGB -negate'
    else
        dark_opts=
    fi

https://github.com/Naheel-Azawy/stpv/blob/5c6058cc4afe289bdcb89bc0eaab84bd1df8f14d/stpv#L300-L306:

    # shellcheck disable=SC2086
    convert "${conv_file}[0]"          \
            $dark_opts                 \
            $auto_orient_opts          \
            $max_img_size_opts         \
            -resize ${width}x${height} \
            "$image_cache_path"

I'm not familiar with pdftoppm's options, but it looks like there is no way to invert colors. Maybe it's better to switch to convert instead of pdftoppm for PDF files? Or add a second way to preview PDF files and also set the priority: convert > pdftoppm.

NikitaIvanovV commented 1 year ago

I tried testing convert for pdf files but they turn out very blurry.

convert 'file.pdf[0]' file.jpeg

I tried adding -resize option but then I got an empty black image.

Andrew15-5 commented 1 year ago

I think there's some black magic going on in stpv code — I don't know what exact command is being used to create preview. Maybe printing it out by modifying source code can help out. Or just print out env variables at the start.

But to unblur the image, you can put -density # before the input file:

convert -density 100 'file.pdf[0]' file.jpeg
convert -density 300 'file.pdf[0]' file.jpeg

Sadly, I don't know if this is because of using only 1 flag, but on my machine converting a random PDF file's page takes 0.33s with -density 100 and 1s with -density 300. Of course, if this is all cached, then it's not such a big problem.

Option -flatten removes transparent background. For me, it works better than without it. I don't think it will change the way the page is previewed, but you have to investigate.

Andrew15-5 commented 1 year ago

I think the best way is to ask Naheel directly. Or to dig a bit dipper in the source code.

Andrew15-5 commented 1 year ago

As a side note.

This project was recently patched to correctly show image previews using kitty's icat command (latest version) and there's also a fixed GIF bug in latest icat. Hence, I can finally use both latest kitty and ctpv.

But there is a problem with flashing PDF files (they are white, and I have quite sensitive eyes, especially with dark mode all over the place). Maybe I can make a temporary mix of ctpv + stpv, but I'm not sure about this right now, as it looks a bit complicated to mix all this previewers and cleaners (in lf).

Andrew15-5 commented 1 year ago

Ok, it works. But I forgot one critical thing: if I were to use latest kitty + ctpv + stpv then the PDF files would not render because of the same bug in stpv which is not yet been fixed. So I'm still stuck with kitty v0.26.5 and therefore GIF animations are broken, and as a result I also need to use stpv for GIF files (no animation).

Here is my previewer.sh:

#!/bin/sh
[ "$#" -eq 5 ] || exit
case "$(file -b --mime-type "$1")" in
  application/pdf|image/gif)
    exec stpv "$@"
    ;;
  *)
    exec ctpv "$@"
    ;;
esac

and cleaner.sh:

#!/bin/sh
[ "$#" -eq 5 ] || exit
case "$(file -b --mime-type "$1")" in
  application/pdf|image/gif)
    # shellcheck disable=SC2154
    exec stpv --clear "$id"
    ;;
  *)
    exec ctpv -c "$id"
    ;;
esac

P.S. I don't know which program is used by stpv to render static GIF files, and I failed to use chafa only for GIF format inside ctpv config file, that's why I'll just keep using stpv for this.

Andrew15-5 commented 6 months ago

I made it work! Yay!

So, I'm using kitty v0.32.2 and lf r31 and images/gif/pdf/videos/etc. work ok. And my only real problem is white PDF preview. And today I said "enough is enough" and started digging through the stpv code to find the secret sauce for dark PDF preview. And I found it very quickly, actually. It's a combination of pdftoppm that converts PDF to JPEG and then convert that converts JPEG to JPEG (I think) but with different option such as -channel RGB -negate for making PDF preview look dark (assuming the background is bright).

So I only had to change one file. I didn't optimize anything, I just copied some stuff and hoped that it would work:

# pdf: pdftoppm

pdf() {
    pdftoppm -f 1 -l 1              \
        -scale-to-x 1920            \
        -scale-to-y -1              \
        -singlefile                 \
        -jpeg \
        -- "$f" "$cache_f" \
  && (
    set -eu
    file="$cache_f.jpg"
    dark_opts='-channel RGB -negate'
    auto_orient_opts='-auto-orient'
    MAX_IMG_CACHE_SIZE=300kb  # max image cache size
    max_img_size_opts="-define jpeg:extent=$MAX_IMG_CACHE_SIZE"

    dims="$(identify -ping -format '%w\n%h\n' "$file")"
    width="$(echo "$dims" | head -1)"
    height="$(echo "$dims" | tail -1)"
    # shellcheck disable=SC2086
    convert "$file"    \
        $dark_opts                 \
        $auto_orient_opts          \
        $max_img_size_opts         \
        -resize "${width}x${height}" \
        "$file"
  ) \
  && mv -- "$cache_f.jpg" "$cache_f"
}

convert_and_show_image pdf

I think it does add some waiting time for the uncached PDF files, but at least the preview doesn't make bright flashes when it is shown. Of course, there are probably some optimizations that can be made to decrease the conversion time, but I think it will require quite a lot of tinkering, which I don't want to do (at least not in the near future).

So, if you want to play with it — go ahead. If you don't then I can make a PR (with a bit more cleaning up, adding the dark mode toggle to the config file/man page). I patched my version once,G and I think that's gonna be enough for me for a long time.

Key places:

rg 'image_prepare\('
rg 'pdftoppm -'

P.S. I don't think I mentioned it, but stpv doesn't work starting from some version of kitty or lf. For me, it is broken with all MIME types (maybe because the args for the previewer were changed once). And this is what I get in previews _Ga=d,d=A\.