<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Yeah. Erlang is not normally seen as the ultimate language for that kind of image processing. For my application I need the alpha channel, so that's me.<div class=""><br class=""></div><div class="">If it becomes a bigger perf problem I would imagine some integration with libpng is in order.</div><div class=""><br class=""></div><div class="">I don't see why the alpha channel should require a named process, but I've not got very far with my usage. Will check - thanks for the heads up</div><div class=""><br class=""></div><div class="">And the code isn't actually that complex - it's mostly just that PDF itself is fairly complex</div><div class=""><br class=""></div><div class="">Sean<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On 25 Sep 2018, at 20:45, Theepan <<a href="mailto:vasdeveloper@gmail.com" class="">vasdeveloper@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Hi Sean,<div class=""><br class=""></div><div class="">I used GraphicsMagic to remove the alpha channel before passing onto ErlGuten. It ensures that the code not taking that inefficient path. It works very well.</div><div class=""><br class=""></div><div class="">I hope ErlGuten needs to be improved for image embedding support and performance using port. Also when the alpha channel is removed, eg_pdg gen_server can be made to work for parallel PDF generation by removing the local name registration.</div><div class=""><br class=""></div><div class="">Best,</div><div class="">Theepan</div><div class=""><br class=""></div><div class=""><br class=""></div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Tue, Sep 25, 2018 at 7:50 PM Sean Hinde <<a href="mailto:sean.hinde@mac.com" class="">sean.hinde@mac.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space" class="">I hit the same issue. I guess you are using one of the versions with lots of lists:nth.<div class=""><br class=""></div><div class="">Following find my patch on the version I was using.</div><div class=""><br class=""></div><div class="">You can find my branch at:</div><div class=""><br class=""></div><div class=""><a href="https://github.com/proactively/erlguten/tree/png-performance" target="_blank" class="">https://github.com/proactively/erlguten/tree/png-performance</a></div><div class=""><br class=""></div><div class="">No time right now to make nice pull requests - I will eventually</div><div class=""><br class=""></div><div class="">===============================================</div><div class=""><br class=""></div><div class=""><div class="">diff --git a/src/eg_pdf_image.erl b/src/eg_pdf_image.erl</div><div class="">index 1a97e0b..817f1b8 100644</div><div class="">--- a/src/eg_pdf_image.erl</div><div class="">+++ b/src/eg_pdf_image.erl</div><div class="">@@ -431,11 +431,11 @@ extractScanLines(Width,Decompressed) -></div><div class=""><br class=""></div><div class=""> extractLine(ScanLines,Width,<< >>) -></div><div class=""> AlmostDone = lists:reverse(ScanLines),</div><div class="">- [ {0, string:chars(0,Width-1)} | AlmostDone];</div><div class="">+ [ {0, list_to_binary(string:chars(0,Width-1))} | AlmostDone];</div><div class=""> extractLine(ScanLines,Width,Image) -></div><div class=""> LineSize = Width - 1,</div><div class=""> << Method:8, Line:LineSize/binary-unit:8, Rest/binary>> = Image,</div><div class="">- extractLine([{Method, binary_to_list(Line) } | ScanLines ], Width, Rest).</div><div class="">+ extractLine([{Method, Line} | ScanLines ], Width, Rest).</div><div class=""><br class=""></div><div class=""> %% @doc Remove the filter on all the bytes in the scan lines.</div><div class=""><br class=""></div><div class="">@@ -448,19 +448,26 @@ processLine([{_Method, _Line1}], _Iter, _Offset, Results)-></div><div class=""> A = lists:flatten( lists:reverse(Results) ),</div><div class=""> list_to_binary( A );</div><div class=""> processLine([{_, Line1},{Method, Line2} | Remainder], Iter, Offset, Results) -></div><div class="">- {ok, Unfiltered} = defilter(Method, Line1, Line2,Offset,length(Line1),Iter),</div><div class="">+ {ok, Unfiltered} = defilter(Method, Line1, Line2,Offset,size(Line1),Iter),</div><div class=""> processLine([{Method, Unfiltered } | Remainder], Iter, Offset, [Unfiltered | Results] ).</div><div class=""><br class=""></div><div class=""> %% @doc Taking two lines of stream defilter the 2nd with the previously defiltered 1st line.</div><div class=""><br class=""></div><div class=""> defilter(Method, Line1, Line2, Offset, Width, Iter) when Iter =< Width -></div><div class=""> NewVal = case Iter =< Offset of</div><div class="">- true -> filter(lists:nth(Iter,Line2), 0, lists:nth(Iter,Line1), 0, Method);</div><div class="">- false -> filter(lists:nth(Iter,Line2), lists:nth(Iter-Offset,Line2), lists:nth(Iter,Line1), lists:nth(Iter-Offset,Line1), Method)</div><div class="">+ true -> filter(binary:at(Line2, Iter - 1), 0,</div><div class="">+ binary:at(Line1, Iter - 1), 0, Method);</div><div class="">+ false -> filter(binary:at(Line2, Iter - 1),</div><div class="">+ binary:at(Line2, Iter - Offset - 1),</div><div class="">+ binary:at(Line1, Iter - 1),</div><div class="">+ binary:at(Line1, Iter - Offset - 1), Method)</div><div class=""> end,</div><div class=""> L2 = case Iter == Width of</div><div class="">- true -> lists:flatten([lists:sublist(Line2,Iter - 1),NewVal]);</div><div class="">- false -> lists:flatten([lists:sublist(Line2,Iter - 1),NewVal,lists:nthtail(Iter, Line2)])</div><div class="">+ true -> Start = binary:part(Line2, 0, Iter - 1),</div><div class="">+ <<Start/binary, NewVal>>;</div><div class="">+ false -> Start = binary:part(Line2, 0, Iter - 1),</div><div class="">+ End = binary:part(Line2, Iter, size(Line2) - Iter),</div><div class="">+ <<Start/binary, NewVal, End/binary>></div><div class=""> end,</div><div class=""> defilter(Method, Line1, L2 ,Offset, Width, Iter+1);</div><div class=""> defilter(_Method, _Line1, Line2, _Offset, _Width, _Iter) -></div><div class="">@@ -513,8 +520,7 @@ inflate_stream(Data) -></div><div class=""> Decompressed = zlib:inflate(Z, Data),</div><div class=""> ok = zlib:inflateEnd(Z),</div><div class=""> zlib:close(Z),</div><div class="">- F = fun(A, B) -> <<A/binary, B/binary>> end,</div><div class="">- MergedBinaries = lists:foldr(F, <<>>, Decompressed),</div><div class="">+ MergedBinaries = iolist_to_binary(Decompressed),</div><div class=""> {ok,MergedBinaries}.</div><div class=""><br class=""></div><div class=""> %% @doc Compress a bit stream using the zlib/deflate algorithm</div><div class=""><br class=""></div><div class="">===============================================</div><div class=""><br class=""><blockquote type="cite" class=""><div class="">On 25 Sep 2018, at 01:15, Theepan <<a href="mailto:vasdeveloper@gmail.com" target="_blank" class="">vasdeveloper@gmail.com</a>> wrote:</div><br class="m_-7771908096063233798Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div dir="ltr" class=""><div dir="ltr" class="">Thanks Lloyd for your detailed explanation on what has been done, and your vision for the library. However we are already using ErlGuten in one of our production systems, and the issues is mainly with the images.</div><div dir="ltr" class=""><br class=""></div><div dir="ltr" class="">I will definitely keep an eye on the development of erlpress_core in the future, as you seem enthusiastic about making it a lively library.<br class=""><div class=""><br class=""></div><div class="">The issues we have are: </div><div class=""><br class=""></div><div class="">** When some JPEG image is embedded into the PDF, it turns out dark in the generated PDF file</div><div class="">** When some PNG file is embedded, it takes too long (unto 5 minutes) to generate the PDF file. Debugging shows that the delay is on <span style="font-family:Menlo;font-size:9pt" class="">defilter(</span><span style="font-family:Menlo;font-size:9pt;color:rgb(102,14,122)" class="">Method</span><span style="font-family:Menlo;font-size:9pt" class="">, </span><span style="font-family:Menlo;font-size:9pt;color:rgb(102,14,122)" class="">Line1</span><span style="font-family:Menlo;font-size:9pt" class="">, </span><span style="font-family:Menlo;font-size:9pt;color:rgb(102,14,122)" class="">Line2</span><span style="font-family:Menlo;font-size:9pt" class="">, </span><span style="font-family:Menlo;font-size:9pt;color:rgb(102,14,122)" class="">Offset</span><span style="font-family:Menlo;font-size:9pt" class="">, </span><span style="font-family:Menlo;font-size:9pt;color:rgb(102,14,122)" class="">Width</span><span style="font-family:Menlo;font-size:9pt" class="">, </span><span style="font-family:Menlo;font-size:9pt;color:rgb(102,14,122)" class="">Iter</span><span style="font-family:Menlo;font-size:9pt" class="">) of eg_pdf_image module.</span></div><div class=""><span style="font-family:Menlo;font-size:9pt" class=""><br class=""></span></div><div class=""><font face="Menlo" class=""><span style="font-size:9pt" class="">Did you </span><span style="font-size:12px" class="">come acrsoss</span><span style="font-size:9pt" class=""> this?</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size:9pt" class=""><br class=""></span></font></div><div class=""><font face="Menlo" class=""><span style="font-size:9pt" class="">Best,</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size:9pt" class="">Theepan</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size:9pt" class=""><br class=""></span></font></div><div class=""><font face="Menlo" class=""><span style="font-size:9pt" class=""><br class=""></span></font></div><div class=""><span style="font-family:Menlo;font-size:9pt" class=""><br class=""></span></div><div class=""><span style="font-family:Menlo;font-size:9pt" class=""><br class=""></span></div></div></div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Tue, Sep 25, 2018 at 2:56 AM <<a href="mailto:lloyd@writersglen.com" target="_blank" class="">lloyd@writersglen.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Theepan,<br class="">
<br class="">
1. If you look at ErlGuten source, you'll see that function documentation is fairly minimal and many parameters have single character names with little to no documentation. This makes maintenance and revision very difficult. I consider the core ErlGuten modules diamonds-in-the-rough.<br class="">
<br class="">
I also found the high-level page make-up functions provided by Hugh and Carl limited with respect to professional page make-up and, to me at least, a bit confusing. <br class="">
<br class="">
But erlpress_core owes a deep debt and much gratitude to the ErlGuten lineage. <br class="">
<br class="">
erlpress_core is based on Joe's font-handling, justification, and XML parsing code with few if any changes. But it provides map structures to represent nearly all of the PDF objects represented in eg_pdf_op.erl. These map structures incorporate many default parameters so generating PDF documents is syntactically simple and consistent without sacrificing expressive flexibility. You can easily customize display by instantiating map parameters with your own values. <br class="">
<br class="">
You can see most of the PDF objects currently supported by erlpress_core, including boxed text, justification options, and various line and text objects, demonstrated in ep_show_n_tell.pdf and the source in ep_show_n_tell.erl.<br class="">
<br class="">
If you look at the map definitions of the various PDF objects, you'll see how to customize display.<br class="">
<br class="">
At some point if would be good to re-write the base Erlguten modules with more explicit function and parameter documentation, but I'm not up to that at this point. But, anyone looking for a challenge is free to jump in.<br class="">
<br class="">
I'm currently working on tables and text flow across pages (think reports and book chapters). Hope to deliver these features plus much code polishing in the next release coming "real soon now."<br class="">
<br class="">
High on my wish/to-do list are:<br class="">
<br class="">
-- Easy-to_use page-grid design functions<br class="">
-- Imposition (printing multiple page impressions on a single sheet of paper stock)<br class="">
-- Articles and beads (think text jumping across columns and pages)<br class="">
-- Easy-to-use and expressive page make-up functions<br class="">
-- Example templates for various print formats<br class="">
-- Markdown input<br class="">
-- Support of TTF and OTF fonts<br class="">
<br class="">
Joe Armstrong expressed the following goal when he first announced ErlGuten: <br class="">
<br class="">
"Better than TeX." <br class="">
<br class="">
That's a tall order, yet to be realized. My hope is that erlpress will move the ball further down the field.<br class="">
<br class="">
2. I haven't done anything with image formats beyond what you'll find in eg_pdf_image.erl. I'd welcome work in that direction.<br class="">
<br class="">
3. erlpress_core is still at Version 0.01. It's just out. I'm working toward sufficient functionality and stability to support a web application that we have currently under development. <br class="">
<br class="">
4. I developed erlpress_core on Erlang/OTP 19. It does require support for maps.<br class="">
<br class="">
I see the erlpress_core library as a valuable library for embedding PDF generation into Erlang applications and as the basis for many exciting Erlang-based print production tools.<br class="">
<br class="">
So, Treepan, I appreciate your interest and would welcome your involvement in testing and feature development. <br class="">
<br class="">
I would jump for joy if some Erlang guru were to step forward take on the TTF/OTF support issue. I've done some research and have a few ideas on how expanded font support might be accomplished, but have too little time over the next several months to dig into it.<br class="">
<br class="">
Incidentally, in my previous post my iPad decided it was smarter than me and erroneously corrected my GitHUb <a href="http://address.it/" rel="noreferrer" target="_blank" class="">address.it</a> should be writersglen/erlPress_core. <br class="">
<br class="">
My intention is to bag the camel case in my next release with luck in a week or two so it should look like writersglen/erlpress_core.<br class="">
<br class="">
All the best,<br class="">
<br class="">
Lloyd<br class="">
<br class="">
<br class="">
-----Original Message-----<br class="">
From: "Theepan" <<a href="mailto:vasdeveloper@gmail.com" target="_blank" class="">vasdeveloper@gmail.com</a>><br class="">
Sent: Monday, September 24, 2018 3:59pm<br class="">
To: <a href="mailto:lloyd@writersglen.com" target="_blank" class="">lloyd@writersglen.com</a><br class="">
Cc: "Erlang Questions Mailing List" <<a href="mailto:erlang-questions@erlang.org" target="_blank" class="">erlang-questions@erlang.org</a>>, "Joe Armstrong" <<a href="mailto:erlang@gmail.com" target="_blank" class="">erlang@gmail.com</a>><br class="">
Subject: Re: [erlang-questions] ErlGuten<br class="">
<br class="">
Hi Lloyd,<br class="">
<br class="">
Thank you for your response. I have some quick clarifications --<br class="">
<br class="">
* What are the major improvements made on the source ErlGuten? Did you<br class="">
improve support to different image formats? Any critical bugs fixed?<br class="">
* Is erlPress_core used in commercial applications, specifically of high<br class="">
throughput types?<br class="">
* What is the minimum erlang/OTP version required?<br class="">
<br class="">
Best,<br class="">
Theepan<br class="">
<br class="">
<br class="">
<br class="">
<br class="">
<br class="">
<br class="">
On Mon, Sep 24, 2018 at 6:36 AM Lloyd R. Prentice <<a href="mailto:lloyd@writersglen.com" target="_blank" class="">lloyd@writersglen.com</a>><br class="">
wrote:<br class="">
<br class="">
> Hi Thepan,<br class="">
><br class="">
> I’ve undertaken a major revision of ErlGuten called erlPress_core—<br class="">
> announced it on Erlang questions several weeks ago. It’s available from<br class="">
> GitHub as Writersglen/erlPress_core. I think you’ll find it much more<br class="">
> accessible than the ErlGutens.<br class="">
><br class="">
> I’ve since been polishing up the code and adding a few new features. After<br class="">
> the launch I learned that camel case is not conventional usage when it<br class="">
> comes to the names of Erlang applications and libraries. So I plan to<br class="">
> release the updated version as erlpress_core. With smooth sailing I hope to<br class="">
> release sometime this week or next.<br class="">
><br class="">
> All the best,<br class="">
><br class="">
> Lloyd<br class="">
><br class="">
> Sent from my iPad<br class="">
><br class="">
> On Sep 23, 2018, at 8:30 PM, Theepan <<a href="mailto:vasdeveloper@gmail.com" target="_blank" class="">vasdeveloper@gmail.com</a>> wrote:<br class="">
><br class="">
><br class="">
> Hi Team,<br class="">
><br class="">
> I see many forks of ErlGuten. Which one is the latest, most stable and<br class="">
> widely used?<br class="">
><br class="">
> <a href="https://github.com/richcarl/erlguten" rel="noreferrer" target="_blank" class="">https://github.com/richcarl/erlguten</a><br class="">
> <a href="https://github.com/CarlWright/NGerlguten" rel="noreferrer" target="_blank" class="">https://github.com/CarlWright/NGerlguten</a><br class="">
> <a href="https://github.com/hwatkins/erlguten/commits/master" rel="noreferrer" target="_blank" class="">https://github.com/hwatkins/erlguten/commits/master</a><br class="">
><br class="">
> Best,<br class="">
> Theepan<br class="">
><br class="">
><br class="">
> _______________________________________________<br class="">
> erlang-questions mailing list<br class="">
> <a href="mailto:erlang-questions@erlang.org" target="_blank" class="">erlang-questions@erlang.org</a><br class="">
> <a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank" class="">http://erlang.org/mailman/listinfo/erlang-questions</a><br class="">
><br class="">
><br class="">
<br class="">
<br class="">
</blockquote></div>
_______________________________________________<br class="">erlang-questions mailing list<br class=""><a href="mailto:erlang-questions@erlang.org" target="_blank" class="">erlang-questions@erlang.org</a><br class=""><a href="http://erlang.org/mailman/listinfo/erlang-questions" target="_blank" class="">http://erlang.org/mailman/listinfo/erlang-questions</a><br class=""></div></blockquote></div><br class=""></div></div></blockquote></div>
</div></blockquote></div><br class=""></div></body></html>