JuliaImages / QRCoders.jl

Creating QR Codes within Julia
https://juliaimages.org/QRCoders.jl/
MIT License
68 stars 11 forks source link

Plot image by qrcode #37

Closed RexWzh closed 1 year ago

RexWzh commented 1 year ago

Plot using error correction.

Plot image inside QRCode as mentioned in #38

Example

julia> using QRCoders, ColorTypes, ImageTransformations
julia> img = load("test/assets/badapple.png")
julia> img = .! (Bool ∘ round ∘ Gray).(imresize(img, 37, 37))
julia> code = QRCode("HELLO WORLD", eclevel=High(), version=12, width=4)
julia> exportbitmat(imageinqrcode(code, img, rate=1))

example The image above is generated without using the remainder message bits. For cases like subtitle, the real message bits take only about 10% of the message space. By this, we can reduce noise and enlarge the image in the center. For now, I use getsegments to track the message bits, might need a little work after the first stage passed.

Related table: characters capacity for UTF8 mode with High quality.

(High(), UTF8()) =>
[7, 14, 24, 34, 44, 58, 64, 84, 98, 119, 137, 155, 177, 194, 220, 250, # version 1-16
280, 310, 338, 382, 403, 439, 461, 511, 535, 593, 625, 658, 698, 742,
790, 842, 898, 958, 983, 1051, 1093, 1139, 1219, 1273]

For example, one can store at least 62(250/4) characters in version 16 using UTF8 mode in the worst case.

codecov[bot] commented 1 year ago

Codecov Report

Base: 100.00% // Head: 100.00% // No change to project coverage :thumbsup:

Coverage data is based on head (c043ab3) compared to base (10b5721). Patch coverage: 100.00% of modified lines in pull request are covered.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## master #37 +/- ## ========================================== Coverage 100.00% 100.00% ========================================== Files 6 6 Lines 436 541 +105 ========================================== + Hits 436 541 +105 ``` | [Impacted Files](https://codecov.io/gh/JuliaImages/QRCoders.jl/pull/37?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=JuliaImages) | Coverage Δ | | |---|---|---| | [src/tables.jl](https://codecov.io/gh/JuliaImages/QRCoders.jl/pull/37/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=JuliaImages#diff-c3JjL3RhYmxlcy5qbA==) | `100.00% <ø> (ø)` | | | [src/QRCoders.jl](https://codecov.io/gh/JuliaImages/QRCoders.jl/pull/37/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=JuliaImages#diff-c3JjL1FSQ29kZXJzLmps) | `100.00% <100.00%> (ø)` | | | [src/matrix.jl](https://codecov.io/gh/JuliaImages/QRCoders.jl/pull/37/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=JuliaImages#diff-c3JjL21hdHJpeC5qbA==) | `100.00% <100.00%> (ø)` | | | [src/style.jl](https://codecov.io/gh/JuliaImages/QRCoders.jl/pull/37/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=JuliaImages#diff-c3JjL3N0eWxlLmps) | `100.00% <100.00%> (ø)` | | Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=JuliaImages). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=JuliaImages)

:umbrella: View full report at Codecov.
:loudspeaker: Do you have feedback about the report comment? Let us know in this issue.

RexWzh commented 1 year ago

where's the source of test image test/assets/badapple.png? Is it well-licensed and okay to use?

It is an image capture of the bad apple video.

I think it is ok since there are lots of secondaries of bad apple on the internet. And the old "saying", If there's a screen, there can be Bad Apple.(有屏幕的地方就有烂苹果)

RexWzh commented 1 year ago

I think it is ready for merge now.

Benchmark result

code = QRCode("HELLO WORLD", eclevel=High(), version=40, width=4);
@btime qrcode(code);
# 667.130 μs (12993 allocations: 918.61 KiB)
mat = @btime imageinqrcode(code, img, rate=1);
# 16.706 ms (137533 allocations: 14.23 MiB)

All the steps cost less than 100 μs except the last for loop.

for mask in 0:7
    code.mask = mask
    newmat = qrcode(code) # 663.652 μs (12991 allocations: 914.25 KiB)
    for (vinds, blockinds) in zip(validmsgecinds, msgecinds) # 81 block
        errinds = filter(x -> newmat[x] != targetval(x), vinds)
        inds = filter!(isvalid, pickcodewords(errinds, blockinds, destroy))
        newmat[inds] = targetval.(inds)
    end
    ...
end