<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrey</title>
    <description>The latest articles on DEV Community by Andrey (@tonfotos).</description>
    <link>https://dev.to/tonfotos</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F864750%2F305af1ad-101e-49fd-aa97-d885c7164e32.jpg</url>
      <title>DEV Community: Andrey</title>
      <link>https://dev.to/tonfotos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tonfotos"/>
    <language>en</language>
    <item>
      <title>Using LibRaw for RAW files support</title>
      <dc:creator>Andrey</dc:creator>
      <pubDate>Tue, 13 Sep 2022 12:16:21 +0000</pubDate>
      <link>https://dev.to/tonfotos/using-libraw-for-raw-files-support-2dom</link>
      <guid>https://dev.to/tonfotos/using-libraw-for-raw-files-support-2dom</guid>
      <description>&lt;p&gt;One of the features in Tonfotos our users asked us for some time, is support for "digital negatives" - RAW image files. Even though RAW files are mostly used by professional photographers, while Tonfotos is mostly targeted at general audience, our users encounter RAW files here and there, and would like to work with them just like with any other photo.&lt;/p&gt;

&lt;p&gt;And unlike regular image formats (jpeg and others), there is no single standard for RAW files. All leading camera vendors came up with not just one format of their own, but several. For example, Canon started with CRW, then moved on to &lt;a href="https://tonfotos.com/articles/cr2/"&gt;CR2&lt;/a&gt;, and now uses CR3. So RAW support is definitely one of those features that enables incremental amount of value, that may come at very high cost.&lt;/p&gt;

&lt;p&gt;Luckily, there is &lt;a href="https://www.libraw.org/"&gt;LibRaw&lt;/a&gt;. This is open source library that comes with two types of licenses: LGPL 2.1 and CDDL 1.0. And thanks to latter, it can be freely used even in commercial projects.&lt;/p&gt;

&lt;p&gt;Camera models support this library provides is pretty impressive. So far we were able to meet only one case, when user was not completely satisfied - his new Canon camera was not yet supported.&lt;/p&gt;

&lt;p&gt;Overall, experience with adding it was pretty smooth. Here are just a few know-how we would like to share in case others may face similar obstacles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;There is precompiled version of library available for download, but platform support is not that extensive. For example there is no Apple Silicon version for macOS. So we ended up with just adding whole source code of the library to our project, and that solved all platform support issues. No need for separate .dll, everything started working for all our architectures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;During compilation library generates lots of warnings. Probably we will do some cleanup and submit a PR, but so far time restrictions did not allow us to do so.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Library is not thread safe by design. Even though it uses classes, for some reason some of the internal codecs rely on global variables. If you plan to use it in several threads, you will need to compile it with TLS support for global variables. Make sure that &lt;strong&gt;LIBRAW_NOTHREADS&lt;/strong&gt; is not set in your config (it is set in macOS build by default).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You will need &lt;strong&gt;LIBRAW_NODLL&lt;/strong&gt; define for inclusion of source codes into your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.libraw.org/docs/API-overview.html"&gt;Here&lt;/a&gt; you can find boilerplate code to start playing around with the library.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are two ways how you can get dimensions of output bitmap image. Boilerplate code uses &lt;strong&gt;imgdata.sizes&lt;/strong&gt;, but there is also &lt;strong&gt;get_mem_image_format()&lt;/strong&gt;. And, as we learned the hard way, there is small percentage of cases when their results may differ, which will lead memory exception when you call &lt;strong&gt;copy_mem_image()&lt;/strong&gt;. Difference is tiny - width and hight are swapped, but that is enough to calculate wrong stride and go out of allocated memory.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that seems to be pretty much it. Everything else went pretty smooth. Unfortunately, the list of &lt;a href="https://www.libraw.org/node/2088"&gt;applications that use LibRaw&lt;/a&gt; is pretty small, which is sad, since library is great. Probably this is just because people are too lazy to report their usage.&lt;/p&gt;

&lt;p&gt;Happy hacking!&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>opensource</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Collecting logs from B2C customers</title>
      <dc:creator>Andrey</dc:creator>
      <pubDate>Wed, 03 Aug 2022 14:19:00 +0000</pubDate>
      <link>https://dev.to/tonfotos/collecting-logs-from-b2c-customers-nbk</link>
      <guid>https://dev.to/tonfotos/collecting-logs-from-b2c-customers-nbk</guid>
      <description>&lt;h1&gt;
  
  
  We all need logs sometimes
&lt;/h1&gt;

&lt;p&gt;It is no surprise, software has bugs. And what is worse, it contains bugs that are only reproducible at customer site. Regardless how good your testing is, there will always be bugs that you can't reproduce in your test labs.&lt;/p&gt;

&lt;p&gt;What can we do in those cases? Well, we can torture customers with tons of stupid questions like "What did you do?", "what is your OS and environment?", "send me a screenshot please" and so on. But most of the time, this is just shooting into the darkness. You have idea what might be wrong, and ask, if this is the case or not. This is far from being productive, as most important bugs come from situations you would never even think of.&lt;/p&gt;

&lt;p&gt;And this is where logging can be very helpful. If you software has ability to log every step it takes and warn about anything that is out of ordinary, this kind of log can narrow down search area significantly, and pretty fast.&lt;/p&gt;

&lt;h1&gt;
  
  
  ...but everybody collects telemetry. Right?
&lt;/h1&gt;

&lt;p&gt;Telemetry collection is still quite controversial topic these days. Something like 15-20 years ago it was not, meaning if you were try to collect telemetry from your customers, that would definitely end up as public scandal that would cost you at least your reputation, if not business.&lt;/p&gt;

&lt;p&gt;Today situation is different. Social media and mobile applications made all sort of crazy stuff kinda normal. They collect so much personal data, but people tend to tolerate that in exchange for free service. Public opinion shifted significantly in this area.&lt;/p&gt;

&lt;p&gt;And provided how much useful data you can get from collecting few metrics from your application, this made it a must have instrument for everyone who works with large numbers of customers. If you don't collect telemetry, you can be sure your competitors do. Which puts you into competitive disadvantage immediately. Therefore, everyone collects it.&lt;/p&gt;

&lt;p&gt;Nevertheless, telemetry is not logs. It can never be so detailed. And regardless of the shift in public opinion, there are still pretty strict moral and technical boundaries of what you can and should collect. You still have to be very discreet and keep in mind customer privacy, as well as respect users internet bandwidth. Just remember, you are not Google and not Facebook. You just can't afford full blown legal battle. It will destroy you.&lt;/p&gt;

&lt;p&gt;Therefore, no telemetry can substitute good old logs of your application, collected on the customer side.&lt;/p&gt;

&lt;h1&gt;
  
  
  How do you collect logs from customers?
&lt;/h1&gt;

&lt;p&gt;We at &lt;a href="https://tonfotos.com"&gt;Tonfotos&lt;/a&gt; decided make this process as simple for customer as possible. Here's what we did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer can turn on and off logging at any time in the application Preferences.&lt;/li&gt;
&lt;li&gt;Even though it is trivial to turn on, we published &lt;a href="https://telegra.ph/Collecting-logs-in-Tonfotos-application-08-03"&gt;simple instruction&lt;/a&gt; how to do that and refer to it, with pictures.&lt;/li&gt;
&lt;li&gt;When logging is on, log file will be located in &lt;code&gt;Downloads&lt;/code&gt; folder, so user will not have hard time looking for it to send to us.&lt;/li&gt;
&lt;li&gt;Logging is pretty verbose, so file can become quite large pretty fast, but since it is being turned on only when necessary, that is OK.&lt;/li&gt;
&lt;li&gt;Additionally, we introduced some sort of 'Time machine'. That means, even before logging on, we still collect (error-only) logs of application into memory buffer. And when logging is turned on, this backlog gets flushed in the log file too. Yes, it is not that detailed, but still very useful.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What are your best practices for collecting logs from customers? Please share in comments.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>programming</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Tonfotos is listed among 11 best Photo Managers by Rafal Reyzer</title>
      <dc:creator>Andrey</dc:creator>
      <pubDate>Tue, 02 Aug 2022 19:17:16 +0000</pubDate>
      <link>https://dev.to/tonfotos/tonfotos-is-listed-among-11-best-photo-managers-by-rafal-reyzer-11hh</link>
      <guid>https://dev.to/tonfotos/tonfotos-is-listed-among-11-best-photo-managers-by-rafal-reyzer-11hh</guid>
      <description>&lt;p&gt;Tonfotos, our application for managing personal photo archive, was featured among other 10 applications in the Rafal Reyzer's blog post &lt;a href="https://rafalreyzer.com/photo-managers-with-face-recognition/"&gt;11 Best Photo Managers With Face Recognition Feature&lt;/a&gt;. That is a honour for us to see our product in such good company that includes Adobe, ACDSee, Movavi and some other reputable companies. This is definitely a milestone in a growing success of our project.&lt;/p&gt;

&lt;p&gt;Big thanks to Rafal Reyzer's blog team, and I hope to have more news like that soon, as our product grows very fast, and adds a lot of innovative features, such as &lt;a href="https://dev.to/tonfotos/telegram-nodejs-bot-5e5e"&gt;Telegram Connector&lt;/a&gt; for example.&lt;/p&gt;

</description>
      <category>news</category>
    </item>
    <item>
      <title>Telegram + node.js - bot</title>
      <dc:creator>Andrey</dc:creator>
      <pubDate>Sat, 16 Jul 2022 08:37:38 +0000</pubDate>
      <link>https://dev.to/tonfotos/telegram-nodejs-bot-5e5e</link>
      <guid>https://dev.to/tonfotos/telegram-nodejs-bot-5e5e</guid>
      <description>&lt;p&gt;You can easily find tons of articles about creating bot for Telegram, including ones based on node.js. We at &lt;a href="https://tonfotos.com"&gt;Tonfotos&lt;/a&gt; faced completely different task - we needed to build a Telegram client into our application.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why Telegram client, not a bot?
&lt;/h1&gt;

&lt;p&gt;Tonfotos is an application that takes care of personal or family photo archive. And as such, it has to take care not only about storing, indexing and viewing photos and videos, it also has to simplify photos sharing. And these days people do not share their photos on USB sticks any more. Majority of photos got shared using messengers, and Telegram is one of them. There is wide spread belief among users that Telegram does not over-compress photos, unlike other messenger app, such as Viber for example.&lt;/p&gt;

&lt;p&gt;As a result, we have implemented &lt;a href="https://tonfotos.com/telegram.html"&gt;Telegram connector&lt;/a&gt; feature into our application. Once user connects Tonfotos to his or her Telegram account, all images that are sent to user by friends got saved into image archive, fully automated.&lt;/p&gt;

&lt;h1&gt;
  
  
  Choosing the library
&lt;/h1&gt;

&lt;p&gt;There are several requirements that pretty much narrow down a list of possible Telegram libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tonfotos is a cross-platform application using Electron that supports Windows, Linux and macOS. The library should work on all of them.&lt;/li&gt;
&lt;li&gt;Application is not open-source, so no GPL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those requirements ruled out many implementations, including ones based on official TDLib library. So we ended up using &lt;a href="https://www.npmjs.com/package/telegram-mtproto"&gt;telegram-mtproto&lt;/a&gt; library with MIT license. This is JS-native implementation of MT protocol. Thanks to that there is no native code dependencies, and impact on distribution size is negligible.&lt;/p&gt;

&lt;p&gt;Downside is though, this library is not supported anymore and repository is not accepting PR's with fixes. So all bug fixes we had to keep as patches. This includes update of MTproto schema to up-to-date one, which is basically a replacement of schema file.&lt;/p&gt;

&lt;h1&gt;
  
  
  Architecture
&lt;/h1&gt;

&lt;p&gt;The disadvantage of the chosen library is that it cannot deinitialize and free up all the used memory. Therefore we had to run it always in a separate process that we would spawn using &lt;code&gt;child_process.fork&lt;/code&gt;, and killing this process when it is not needed anymore. &lt;/p&gt;

</description>
      <category>telegram</category>
      <category>node</category>
      <category>electron</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Is the dusk of the cloud era approaching?</title>
      <dc:creator>Andrey</dc:creator>
      <pubDate>Wed, 25 May 2022 10:08:41 +0000</pubDate>
      <link>https://dev.to/tonfotos/is-the-dusk-of-the-cloud-era-approaching-3d44</link>
      <guid>https://dev.to/tonfotos/is-the-dusk-of-the-cloud-era-approaching-3d44</guid>
      <description>&lt;p&gt;Not that long ago, companies were faced with the choice of “be in the cloud or perish.” Investors pressure on the business was unprecedented, because the "cloudiness" was believed to increase the capitalisation manifold.&lt;/p&gt;

&lt;p&gt;It was not long since managers were able to breath freely after the rush associated with the forcible transfer of business to the cloud rails, a new challenge is approaching from where they did not expect.&lt;/p&gt;

&lt;p&gt;Reality has changed again. "Thanks" to politicians, we no longer live in one world. After decades of centralisation and globalisation, thanks to which clouds flourished, invisible walls are reappearing that divide the world into separate camps, and the economic ties between these camps are crumbling before our eyes. And each of the camps has its own advantages - access to capital, availability of vacant market niches, access to resources, access to inexpensive talents, strong technological infrastructure, convenient regulatory environment, government support programs and tax incentives, a large number of potential users - now suddenly it turns out that not all of these important components can be found on one side of these walls. The situation is different for different types of businesses, but quite often these components are scattered around different parts of the world.&lt;/p&gt;

&lt;p&gt;Corporations themselves, although with difficulty, are trying to adapt to the new reality, showing miracles in the field of corporate structuring. Politicians and public opinion force them to choose which part of the no longer unified world they belong to, but no one wants to lose the advantages of being global. One of the typical situations is an attempt to maintain access to cheap talent on one side of the wall, while not losing the market on the other.&lt;/p&gt;

&lt;p&gt;When it comes to cloud infrastructure, the dark magic of repainting logos and obfuscating ownership structure won't help. Clouds are very visible and under the direct attention of regulators on all sides of a fractured world. Especially when we talk about B2C services.&lt;/p&gt;

&lt;p&gt;Suddenly we come to a situation where there will no longer be such familiar things as THE cloud for videos, THE cloud for your music, THE cloud for your photos. The current leaders will be able to maintain their monopoly only in one of the pieces of the split world, and new and very strong competitors will appear very quickly on the other pieces. And they will constantly try to seep into the neighboring territory through cracks in the walls.&lt;/p&gt;

&lt;p&gt;Apparently, the current split is not a temporary phenomenon. Politicians do not seem to have any intention of returning the old united world for us, they are only concerned with raising the stakes in this dangerous game every day. Now this is our new reality for decades to come.&lt;/p&gt;

&lt;p&gt;This means that we, as consumers, will have to get used to the fragmentation and marginalisation of cloud services.&lt;/p&gt;

&lt;p&gt;And the services will have to get used to the new reality, when they no longer control the whole world, and whatever they do, they will have to put up with a couple of new very strong competitors, who they will not be able to defeat by just good old competition.&lt;/p&gt;

&lt;p&gt;And this will lead to the fact that financial models will have to be seriously revised. Earlier it was possible to invest huge money in improving the service in anticipation of future world domination and fantastic profits, this dream is unattainable anymore. This option just no longer exists. This means that there will be much more careful investment in buying our (users') loyalty.&lt;/p&gt;

&lt;p&gt;There are also few unexpected findings for IT companies - in the past the thesis “in the future everything will be in the cloud” was beyond doubt, and this had a significant impact on our architecture decisions. Now, when it comes to the fact that there will be no single and main cloud for some sort of need, our users will live in a situation “clouds are an option”. It is time for us to think about designing processes with a significant emphasis on “cloudlessness”.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>strategy</category>
      <category>cloudless</category>
    </item>
    <item>
      <title>Try this Arkanoid-like game in your browser</title>
      <dc:creator>Andrey</dc:creator>
      <pubDate>Thu, 19 May 2022 10:13:12 +0000</pubDate>
      <link>https://dev.to/tonfotos/try-this-arkanoid-like-game-in-your-browser-2d0c</link>
      <guid>https://dev.to/tonfotos/try-this-arkanoid-like-game-in-your-browser-2d0c</guid>
      <description>&lt;p&gt;This genre will never die, and even after decades, we still like to get stuck in bouncing the ball from the platform from time to time. A great game to get distracted for 10-15 minutes, clear your mind and get back into a working mood to take on the next task.&lt;/p&gt;

&lt;p&gt;The program is written in pure HTML + Javascript Canvas API, no frameworks and even no sprites - all sprites are drawn programmatically on the fly. Only the sounds are prepared as separate mp3 files. Without them, the whole program takes only 15Kb (minified code).&lt;/p&gt;

&lt;p&gt;I invite everyone to the game: &lt;a href="https://play.arkanoid.online/?lang=en"&gt;play.arkanoid.online&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>gamedev</category>
      <category>gaming</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
