Jan 052017
Couldn't add widget removed

Couldn’t add widget removed


After having spent more than a day on the matter, I have finally figured out how to remove the Couldn’t add widget block in the Overview Screen. This is the block which appears in place of the Google search bar on top of the recent apps list after you have disabled the Google app.

Step by step

  1. Open the Play Store.
  2. Install KISS Launcher.
  3. Enable the Google app.
  4. Update the Google app.
  5. Touch the Home button.
  6. Set the KISS Launcher as default launcher.
  7. Reboot in Safe Mode (the process may differ on your Android OS):
    1. press the power button,
    2. long touch on the Power Off button,
    3. touch OK.
  8. When the reboot is done, the Google bar should have returned in the Overview Screen.
    • On this step, the bar wasn’t interactable on my phone.
  9. Power off normally your device.
  10. Power on your device.
  11. When the reboot is done, the Google bar should still be in the Overview Screen.
  12. Go to Settings > Apps > ALL.
  13. Disable the Google app. Accept everything when it says it will uninstall updates and data.
  14. Touch the Home button.
  15. Wait a few seconds.
  16. Open the Overview Screen.
  17. Enjoy!

Additional Notes

  • I have succeeded two times on a nearly fresh install of Android 5.1 (Lollipop) on a Moto E.
  • I have updated a lot of native apps until the internal storage was full (yes, on the 1st gen Moto E 4GB, you cannot have all the default apps up to date with the tiny internal storage space).
  • Please refer to your device manual for Safe Mode reboot.
  • A lot of websites and user feedback will tell you to just restart in Safe Mode to remove the bar. It did not do the trick on my phone for some reason.
  • I had to try a lot of possibilities so I don’t remember exactly what are the triggers for the bar removal. My guess is a combination of the KISS Launcher as default launcher app, a Google App up to date before disabling, and reboots between Safe Mode and normal mode, and maybe a full internal memory.
  • The only apps disabled when the bar removed itself after the disabling were:
    • Assist (by Motorola)
    • Motorola Alert
    • Motorola Migrate
    • Help (by Motorola)
    • Email (the default Android app)
  • The only apps enabled but not up to date were:
    • Google Play Books
    • Google Play Movies & TV
    • Google Play Music
    • Google Play Newsstand
    • Google Street View
    • Maps – Navigation & Transit
    • Motorola Camera
    • Motorola FM Radio
  • The remaining apps were up to date.
  • Third party apps installed from the Play Store:
    • Amaze File Manager
    • SuperSU
  • Third party apps installed from the SD Card includes:
  • I did not remove KISS Launcher afterwards because I like it. But feel free to change to another launcher. I guess it will work.
  • Pour les francophones, la méthode démontrée ci-dessus indique comment retirer le bloc avec le message « Impossible d’ajouter le widget » dans l’écran « Overview » qui affiche la liste des applications récentes (gestionnaire de tâches).
  • The step by step needs to be more accurate so I am wishing to get some feedback.
Déc 162016

The code

/// <summary>
/// Gets the coordinates of the intersection point of two lines.
/// </summary>
/// <param name="A1">A point on the first line.</param>
/// <param name="A2">Another point on the first line.</param>
/// <param name="B1">A point on the second line.</param>
/// <param name="B2">Another point on the second line.</param>
/// <param name="found">Is set to false of there are no solution. true otherwise.</param>
/// <returns>The intersection point coordinates. Returns Vector2.zero if there is no solution.</returns>
public Vector2 GetIntersectionPointCoordinates(Vector2 A1, Vector2 A2, Vector2 B1, Vector2 B2, out bool found)
    float tmp = (B2.x - B1.x) * (A2.y - A1.y) - (B2.y - B1.y) * (A2.x - A1.x);
    if (tmp == 0)
        // No solution!
        found = false;
        return Vector2.zero;
    float mu = ((A1.x - B1.x) * (A2.y - A1.y) - (A1.y - B1.y) * (A2.x - A1.x)) / tmp;
    found = true;
    return new Vector2(
        B1.x + (B2.x - B1.x) * mu,
        B1.y + (B2.y - B1.y) * mu

The maths behind

To get the point where two lines intersect, we will do some maths. To the mathematicians who will come across this post, I’m truly sorry for the heart attacks or strokes you may experience by reading this post.

Ok, let’s take a look on the figure:

Study case. We can see two lines crossing in an 2D Euclidian space.

Figure 1

First, sorry, I was too lazy to make a proper figure using computer tools so I just put a scan. XD

Next, here are the definitions:

  • A & B: the two lines,
  • A_1, B_1: the arbitrary starting points of the two lines,
  • A_2, B_2: the arbitrary points which tells the direction of the two lines,
  • X: the intersection point,
  • O: the origin point.

Kewl. Now, what we want is the intersection point X between those two lines. In other words, we want to know the position which starts from either lines’ arbitrary starting point, added by the direction of the line multiplied by a scalar value. So in our figure 1, the X position is:

  • the A_1 position added by the components of \overrightarrow{A_1A_2} multiplied by an unknown which I named \lambda
  • the B_1 position added by the components of \overrightarrow{B_1B_2} multiplied by an unknown which I named \mu

In this case, it is clear that \lambda = \mu = 0.5 so it will be easy to check if our final formula is correct. 🙂

At the point of intersection, we know that:
\begin{array}{rcl} \overrightarrow{OX} = \overrightarrow{OA_1} + \lambda\times\overrightarrow{A_1A_2} & and & \overrightarrow{OX} = \overrightarrow{OB_1} + \mu\times\overrightarrow{B_1B_2} \end{array}

… which gives us:
\begin{array}{rcl} \overrightarrow{OA_1} + \lambda\times\overrightarrow{A_1A_2} & = & \overrightarrow{OB_1} + \mu\times\overrightarrow{B_1B_2} \\ \overrightarrow{OA_1} - \overrightarrow{OB_1} & = & \mu\times\overrightarrow{B_1B_2} - \lambda\times\overrightarrow{A_1A_2} \end{array}

But we can’t use this statement exactly like this to solve our equation as we cannot multiply and divide vectors in this raw format. Also we need to reduce the unkowns count to 1. So we will separate our equation into two equations with the magic of matrices (which I don’t understand well at the moment), one for the x component and one for the y:
\left\{\begin{array}{c}  \overrightarrow{OA_1}_x - \overrightarrow{OB_1}_x = \mu\times\overrightarrow{B_1B_2}_x - \lambda\times\overrightarrow{A_1A_2}_x \\   \overrightarrow{OA_1}_y - \overrightarrow{OB_1}_y = \mu\times\overrightarrow{B_1B_2}_y - \lambda\times\overrightarrow{A_1A_2}_y  \end{array}\right.

To make our equation more readable, we will use some shorthands:
\begin{array}{r}A_\alpha = \overrightarrow{A_1A_2}\end{array}\\  \begin{array}{r}B_\alpha = \overrightarrow{B_1B_2}\end{array}\\  \begin{array}{r}C = \overrightarrow{OA_1} - \overrightarrow{OB_1}\end{array}

… so:
\left\{\begin{array}{c}  C_x = \mu B_{\alpha x} - \lambda A_{\alpha x} \\   C_y = \mu B_{\alpha y} - \lambda A_{\alpha y}  \end{array}\right.

From this point, we can reduce the unknown count. In my case, I have chosen to keep \mu instead of \lambda:
\left\{\begin{array}{c}  C_x A_{\alpha y} = \mu B_{\alpha x} A_{\alpha y} - \lambda A_{\alpha x} A_{\alpha y} \\   C_y A_{\alpha x} = \mu B_{\alpha y} A_{\alpha x} - \lambda A_{\alpha y} A_{\alpha x}  \end{array}\right.\\  \begin{array}{rcl}  C_x A_{\alpha y} - C_y A_{\alpha x} & = & \mu B_{\alpha x} A_{\alpha y} - \lambda A_{\alpha x} A_{\alpha y} - (\mu B_{\alpha y} A_{\alpha x} - \lambda A_{\alpha y} A_{\alpha x}) \\  C_x A_{\alpha y} - C_y A_{\alpha x} & = & \mu B_{\alpha x} A_{\alpha y} - \lambda A_{\alpha x} A_{\alpha y} - \mu B_{\alpha y} A_{\alpha x} + \lambda A_{\alpha y} A_{\alpha x} \\  C_x A_{\alpha y} - C_y A_{\alpha x} & = & \mu B_{\alpha x} A_{\alpha y} - \mu B_{\alpha y} A_{\alpha x} \\  C_x A_{\alpha y} - C_y A_{\alpha x} & = & \mu (B_{\alpha x} A_{\alpha y} - B_{\alpha y} A_{\alpha x}) \\  \mu & = & \frac{C_x A_{\alpha y} - C_y A_{\alpha x}}{B_{\alpha x} A_{\alpha y} - B_{\alpha y} A_{\alpha x}}  \end{array}

And finally, you have to check if B_{\alpha x} A_{\alpha y} - B_{\alpha y} A_{\alpha x} = 0. This will happen if your two lines are parallel or if there is one line defined as a point such as A_1 = A_2 or B_1 = B_2; no solution exists in those cases.

Test 1

Kewl! Now let’s try it with the Figure 1:
\begin{array}{rcl}  \mu & = & \frac{(1 - 1) \times 1 - (2 - 4) \times 2}{2 \times 1 - (-3) \times 2} \\  \mu & = & \frac{4}{8} = 0.5  \end{array}

We can get the X position:
\left\{\begin{array}{l}  \overrightarrow{OX}_x = \overrightarrow{OB_1}_x + B_{\alpha x} \times \mu = 1 + 2 \times 0.5 = 2 \\  \overrightarrow{OX}_y = \overrightarrow{OB_1}_y + B_{\alpha y} \times \mu = 4 + (-3) \times 0.5 = 2.5  \end{array}\right.

Test 2

Ok done! Now let’s try with another figure:

Study case 2. We can see two lines crossing in an 2D Euclidian space.

Figure 2

\begin{array}{rcl}  \mu & = & \frac{((-2) - 2) \times (-1) - ((-2) - (-3)) \times 0}{(-1.5) \times (-1) - 1.5 \times 0} \\  \mu & = & \frac{4}{1.5} \approx 2.666  \end{array}

We can get the X position:
\left\{\begin{array}{l}  \overrightarrow{OX}_x = \overrightarrow{OB_1}_x + B_{\alpha x} \times \mu = 2 + (-1.5) \times 2.666 = -2 \\  \overrightarrow{OX}_y = \overrightarrow{OB_1}_y + B_{\alpha y} \times \mu = (-3) + 1.5 \times 2.666 = 1  \end{array}\right.

Nov 302016

Method 1: mega box collider

Use a single BoxCollider for all your planes. For example, if you have multiple aligned planes, remove their Collider component (Box, Mesh, whichever they have) and on only one of the planes, add a BoxCollider and adjust its center and size values in the component’s inspector to encapsulate all the planes.


  • Simple.


  • Supports only rectangular surfaces.

Method 2: generated colliders

If you are rolling your ball on a non rectangular surface, you will need to find a way to generate a mesh collider for all your planes. For this, choose one of the following:


  • Just works.


  • Uses noticeable CPU power when updating (baking) the colliding mesh in real time. Update sparingly.

Method 3: ramps as bridges

Create a set of meshes from a 3D software such as Blender to make invisible ramps which will be placed partly underground between your planes. They have to be large enough to make the transitions as smooth as possible. The height between the top of the bridge and the ground (the planes) should be approximately the value defined by the Default Contact Offset value in the Physics Manager.


  • No real improvement.


  • The ball may jump a little, especially at high speed.
  • Doesn’t work with small tiling (or when your successive planes are small): the longer the tiles, the longer bridges can be.
  • Requires a lot of testing.
  • Requires 3D software usage.
  • The result is not consistent.
  • Requires good workflow / toolchain.

Method 4: make custom extended planes’ colliders

This one should not work very well.

Create in a 3D software a planar mesh. Then, on its edges, extrude towards outside and lower down slightly the new edges. To put the words into image:

Photo of speed cushions.

Credits: Richard Drdul — cc-by-sa-2.0 (original)

Make them intersect, and hopefully the bouncing will be invisible.


  • Quite simple.


  • The ball may jump a little, especially at high speed.
  • Requires a lot of testing.
  • Requires 3D software usage.
  • The result is not consistent.
  • Requires good workflow / toolchain.

Method 5: turn slightly your planes’ colliders

Make your planes’ colliders slightly rotated so that, in the direction of movement, the end of a collider is slightly above the next plane’s collider. The height should be approximately the value defined by the Default Contact Offset value in the Physics Manager and hopefully no bouncing will occur.


  • Works flawlessly.


  • You will see the ball flying and falling a few units from one plane to another.

Method 6: do everything by script

Maybe the Physics is not what is the best for your gameplay. Write your own system with accelerations, collision detection. This is the old-fashioned way and is the choice of a lot of developers! ^^


  • Works flawlessly.
  • Permits game design driven gameplay and not by physics.


  • Not using the PhysX forces and gravity.
  • Requires to work (omg! 😉 ) to simulate fake physics.

Method 7: Make your ball much larger

By using a greater ball (x10, x100), this could lead to less edge detection.


  • May work.


  • The scale of the simulation would change: if you make everything at the same scale as the ball, objects falling by gravity will look like they fall in slow motion.
  • The result is not consistent.

Method 8: collision layers and raycast

This one is pretty cool.

  1. Keep single BoxColliders for each plane. Set the layer of the plane prefab to SinglePlanes (create the layer).
  2. Make a big Unity cube with a collider which encapsulates all the planes. Set the layer of the cube to ContinuousPlane.
  3. Create two layers: OnAPlane and NotOnAPlane.
  4. Set the ball prefab’s layer to OnAPlane.
  5. In Physics Manager, set the collision matrix so that:
    • NotOnAPlane and ContinuousPlane are not collidable (unchecked),
    • OnAPlane and SinglePlanes are not collidable (unchecked).
  6. On each Update(), do a raycast from the center of the ball towards Vector3.down on the layer SinglePlanes:
    if(!Physics.Raycast(ball.transform.position, Vector3.down, Mathf.Infinity, singlePlanesLayer))
        // Not on a floor anymore
  7. If the raycast returns false, the center of the ball is not on a plane. So now, we change the layer of the ball to NotOnAPlane. The ball will start to fall through the hole.
  8. If the raycast returns true, set the layer of the ball to OnAPlane.

For how to define a layer, please check the manual.


  • Works efficiently with dynamic floor layout.
  • You will learn how to deal with layers and Physics.


  • No real flaws.

Additional Information

  • Methods above may be combined.
  • You can adjust the physics project settings and / or set the physics materials to reduce the bounciness of your objects.
  • Make sure the thickness of the planes collision is not 0f. Make them 1f large or more.
  • There is a possibility to reduce the bounces, but I am not recommending it (may cause jittery and physics artifacts): set the Default Contact Offset to 0.0001. Again, I am not recommending it!
  • All of this post could be useless when the default PhysX embedded in Unity will be upgraded.
  • I originally posted this post as an answer on the Unity Answers website but none of the above methods have been considered as valid by the OP. Hence the removal from the answers website.
Nov 182016

Try to avoid naming your MonoBehaviour methods Main(). These would be triggered between Awake() and Start(). This Main() method supports IEnumerator flavors as much as Awake() and alike! But as useful as it could be, I would not recommend to use it as there is no official documentation entry in the manual. And usually, you should not need this method.

Évitez de nommer Main() les méthodes se situant dans vos MonoBehaviour. Celles-ci seraient déclenchées entre Awake() et Start(). Cette méthode Main() supporte la version en IEnumerator autant que Awake() et les autres ! Mais aussi utile que pourrait être cette méthode, je ne la recommanderais pas à l’usage puisqu’il n’existe aucune documentation officielle dans le manuel. Et normalement, vous ne devriez pas avoir recours à cette méthode.

Screenshot of Unity console

Awake() is fired, then Main() and finally Start(). But don’t use Main()!

Sep 132016

Partie française plus bas


If you are using Windows 10, you may want to pin the Photos live tile to the Start Menu. But some of the images from your pictures folders are not showing in the live tile, or even worse, no picture is displayed on the live tile.

You have tried (or not) the suggestions on the Microsoft forums like those on this thread: thread on Microsoft Answers website.


The last thing you could try before reinstalling or giving up (or switching to another OS) is this:

Pictures you want in the Photos live tile have to be 620px × 620px minimum.

I have spent a few hours to find the info about the problem on the internet but none of the websites I have visited have mentioned the size prerequisite. That’s why if you stumble upon my tip and your photos are now displaying correctly on your Photos live tile, do not hesitate to share this. 😉

Additional Notes

  • The images used by the Photos live tile are located here:

    You will find that your images have shrunk until the width or the height of the image was 620px.

  • If an image is not « compatible » with the live tile, it will not appear here.
  • When you update the contents of your images folders, it looks like there is a listener which will update automatically the images list of the Photos tile.

Partie française


Si vous utilisez Windows 10, vous pourriez avoir envie d’épingler la vignette dynamique de l’application Photos au Menu Démarrer. Mais certaines images de votre dossier d’images ne s’affichent pas dans la vignette dynamique, ou même pire, aucune image ne s’affiche dans cette vignette dynamique.

Vous avez essayé (ou pas) les suggestions des forums de Microsoft telles que celles sur ce fil de discussion : fil de discussion sur le site Microsoft Answers (anglais).


Voici une dernière chose que vous pouvez tester avant de réinstaller le PC ou d’abandonner (ou de changer d’OS) :

Les images que vous désirez voir apparaître dans la vignette dynamique de Photos doivent mesurer 620px × 620px minimum.

J’ai passé quelques heures à chercher l’information sur internet mais aucun des sites web n’avaient indiqué un quelconque prérequis concernant la taille. C’est pourquoi si vous tombez sur mon site et que vos photos apparaissent enfin dans votre vignette dynamique, n’hésitez pas à partager cette information. 😉

Notes additionnelles

  • Les images utilisées par l’application Photos se trouvent ici :

    Vous trouverez que vos images ont été rétrécies jusqu’à ce que la largeur ou la hauteur fait 620px.

  • Si votre image n’est pas compatible avec la vignette dynamique, elle n’apparaîtra pas ici.
  • Lorsque vous mettez à jour les contenus de vos dossiers d’images, il semblerait qu’il y ait un écouteur (listener) qui mettra à jour automatiquement la liste des images de la vignette dynamique de Photos.
Août 292016

When you install a new Linux alongside another one, your computer will likely use the last installed OS’s GRUB instead of the one from the previous install.

In my case, I have installed Debian, and a few days later, a Linux Mint on the same disk. But the thing is I prefer the Debian’s GRUB because it is prettier, with a nice image background! Also, I want to keep Debian as my default choice on boot. I could have modified the boot order via Grub Customizer (I will let you Google that) but still! The Debian’s GRUB is better than the Ubuntu’s (Linux Mint’s) dark and ugly one. 😛

Step by step

To use the old install’s GRUB, use those commands from the old OS (Debian for me):

  • sudo grub-install /dev/sdX

    … with the X corresponding to your disk of installation. For example: sudo grub-install /dev/sda

  • sudo update-grub
  • Then reboot and enjoy!

I hope this helps! I have found those steps on the Ubuntu’s documentation: https://help.ubuntu.com/community/Grub2/Installing

Août 282016


The japanese IME on Debian, when installed properly, works pretty much similarly to the Windows 7 one… I was quite surprised by the quality of this software piece.

Step by step

  1. Install those packages from official repositories: ibus and ibus-mozc (along with their dependencies, of course).
  2. Launch the Region & Language settings app.
  3. In Input Sources, click on the + sign.
  4. Search for the Japanese (Mozc) input source and add it.
  5. You are ready to use the IME. 🙂 Quickly switch between input sources with Super (Windows key) + Space.

Okay, it’s possible it will not work on your side. I have done some other steps but I am not sure if they were useful or not (I started from a near fresh install). If the steps above didn’t work, you may have to open the Input Method app. Then click on Yes, Yes. Select ibus and click OK. Then OK again. Then restart your computer. From there, you should be able to add the Japanese (Mozc) input source in the Region & Language settings app.

Some day, I will try to redo those steps in a virtual machine to make sure the steps are working… Until then, 幸運を祈ります!

Additional Notes

  • Use the keyboard layout selector widget in the GNOME’s top bar to change the input mode from Direct to Hiragana.
  • In the Region & Language app, click on the Options button and select Allow different sources for each window if you find this behavior more practical (it’s my case!).
Août 032016

I was doing an ingame video capture and I needed to have it in a GIF format. A few frames of the animation could be optimized as there were sometimes still images. So if I wanted to remove those unnecessary frames (while keeping the correct duration, of course), one can simply use ImageMagick.

How to

ImageMagick should be included by default in Debian and probably other distributions. So you just have to use the convert command. Here is an example:

convert "gifToOptimize.gif" -layers RemoveDups -layers OptimizeFrame "removedDups.gif"

It will remove duplicate frames and try to optimize frames by looking at similar areas of the pictures across the animation so they don’t appear twice.

Now, if you have specific needs, you better check the documentation here: http://www.imagemagick.org/Usage/anim_opt. There are some examples which will give you an idea of how to perform the best optimization.

Août 032016


I am writing a little tutorial here for creating a QRCode for a vCard file. As I don’t use it that much, it feels like I need a memo for it.


We will use a vCard file named test.vcf which contains the following:

N:Family Name;First Name;;;
FN:First Name Family Name
TITLE:Your job title
ADR;HOME:;;123, avenue des Champs-Élysées;Paris;Île-de-France;75008;France
TEL;TYPE=cell:+33 123456789

Result file

A vCard image QR encoded

A vCard QR encoded

Generating the image


  • qrencode package with its dependencies.

Step by step

  1. In the Terminal, execute the following:
    cat test.vcf | qrencode -o "test.vcf.png"

That’s all! A file named test.vcf.png will be created or overwritten if it already exists.

If you want to change or get rid of the margin, use the -m option with the size in pixels:

cat test.vcf | qrencode -o "test.vcf.png" -m 0

If you want to change the dots size, use the -s option with the size in pixels:

cat test.vcf | qrencode -o "test.vcf.png" -s 4

Please check the manual if you need more options such as output format (PNG, EPS, SVG, ASCII, etc.).

Additional Notes

The same thing with an UI

You can also use frontends to generate QR encoded files: qtqr package (available on Debian repository) seems interesting.

vCard syntax

  • If you want to add or remove your own fields, my advice would be to check the properties on the Wikipédia page: https://en.wikipedia.org/wiki/VCard#Properties
  • Make sure to use the right properties for the right vCard version. I am using 2.1 in my example.

Things to consider to prevent reading failures

  • Make sure the color contrast between the dots and the background is sufficient.
  • Dots should remain dark and the background should remain clear.
  • Make sure the dots are large enough if you want devices with fixed focus (such as my Moto E 1st Gen) to read the image. For instance, the example image was generated with a 4px dot size; 3px dot size was not readable by my Moto E on a 22″ 1920×1080 screen.
  • If you resize your image in a graphics software, it is best to use nearest neighbor interpolation algorithm to preserve sharp dots.
  • If your dot size is 1px, don’t shrink your image as it will lose information. (pretty obvious)
  • Make sure the QR code users will physically have access to the space right in front of the image / print. So don’t put a barrier in front of the image…
Juin 262016


We will use this file named texfile.tex as the .tex to convert:

\pagenumbering{gobble}% Remove page numbers (and reset to 1)
My first \TeX~document.
$s_n = (Ta)_n = \displaystyle\sum_{k=0}^\infty T_{nk} a_k$

Result file

PNG demonstration

PNG demonstration

Generating PNG images

Packages you need:

  • texlive (or any other TeX program, I guess)
  • dvipng

Step by step

  1. In the Terminal, go to the directory containing the .tex file.
  2. Execute this:
    $ latex texfile.tex
    • Output:
      This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2015/dev/Debian) (preloaded format=latex)
       restricted \write18 enabled.
      entering extended mode
      LaTeX2e <2014/05/01>
      Babel <3.9l> and hyphenation patterns for 2 languages loaded.
      Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
      (/usr/share/texlive/texmf-dist/tex/latex/base/size12.clo)) (./texfile.aux
      ) [1] (./texfile.aux) )
      Output written on texfile.dvi (1 page, 584 bytes).
      Transcript written on texfile.log.
  3. Convert to PNG at 150dpi (to get a larger image than default):
    $ dvipng texfile.dvi -D 150 -o texfile.png
    • Output:
      This is dvipng 1.14 Copyright 2002-2010 Jan-Ake Larsson
  4. Remove the border white spaces of the page and add some borders using imagemagick:
    $ convert texfile.png -trim -bordercolor white -border 5x5 texfile_trimmed.png
  5. Your file is ready as texfile_trimmed.png.


I have made a little script to automatize the conversion, with auto-remove of intermediary files:

if latex $1
	echo Base name is: $BASENAME
	dvipng $BASENAME.dvi -D 150 -o $BASENAME.png
	echo Output file name is: $OUTPUT_FILENAME
	convert $BASENAME.png -trim -bordercolor white -border 5x5 $OUTPUT_FILENAME
	if test $# = 2
		if test $2 != "-keeptempfiles"
			rm ${BASENAME}.{aux,dvi,log,png}
		rm ${BASENAME}.{aux,dvi,log,png}
exit 0
  1. Save the above script as tex2png, anywhere you want, usually near your .tex files for convenience.
  2. Make it executable: $ chmod +x tex2png.
  3. Syntax: tex2png filename [-keeptempfiles].
    • Example: $ tex2png texfile.tex.
    • Alternatively, you can omit the .tex extension: $ tex2png texfile but I would not recommend it.
    • If you want to keep the intermediary files (dvi, log, etc.), add the -keeptempfiles argument at the end: $ tex2png texfile.tex -keeptempfiles.
  4. The final image is named texfile_trimmed.png

Generating SVG images

Packages you need:

  • texlive

Step by step

  1. In the Terminal, go to the directory containing the .tex file.
  2. Execute this:
    $ latex texfile.tex
    • Output:
      This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2015/dev/Debian) (preloaded format=latex)
       restricted \write18 enabled.
      entering extended mode
      LaTeX2e <2014/05/01>
      Babel <3.9l> and hyphenation patterns for 2 languages loaded.
      Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
      (/usr/share/texlive/texmf-dist/tex/latex/base/size12.clo)) (./texfile.aux
      ) [1] (./texfile.aux) )
      Output written on texfile.dvi (1 page, 584 bytes).
      Transcript written on texfile.log.
  3. Convert to a SVG image with a 1.5 scale factor:
    $ dvisvgm texfile.dvi -TS1.5 --no-fonts
  4. Your file is ready as texfile.svg.


There is no padding in the SVG method. I have not found yet a method to add a little padding around the figure.

Also, the --no-fonts is necessary to prevent rendering issues about SVG fonts, especially with Firefox and the default SVG viewer of Debian. So the generated formula will not be selectable as a text, but at least, it will render correctly on every device with SVG support.


I needed to include some nice looking formulas on my new game design wiki. I am using MediaWiki but the math add-on was not working on my server (web hosting service, not mine). So I decided to create myself the images offline and upload them as regular image files, so that I don’t need to think too much about trying to set the add-on without having all the privileges I could have on a personal server.