Improving Skype chat images (updated)
Foreword
On January 17th, like many others, they sent me a link to a zhovner article about Skype chat pictures - http://habrahabr.ru/blogs/skype/136395/ , and it started!
It’s a cool idea, we immediately started exchanging pictures generated by the img4skype.com service , but it turned out that for many they are displayed stretched out.

After reviewing the zhovner code snippet, we quickly found that this could be easily fixed by removing one whitespace character.
You just need to fix this code:
$out .= '███';
like this:
$out .= '██';
Therefore, the local version of the service was quickly made, allowing you to choose the number of whitespace per pixel - 2 or 3.
* However, two whitespace characters instead of three still change the image size (instead of 1: 1 it turns out 4: 3), so later we added compression to the original pictures (1: 1 => 3: 4, after distortion 4: 3 again we get 1: 1) if 2 spaces per pixel are selected.
Optimization
1. Combining similar colors
The idea that lies on the surface and voiced by zhovner himself is a combination of similar colors.
If two red pixels go in a row, then the following code is generated:
██████
It is quite obvious that this can be simplified:
██████
This way we will save space in the message occupied by the code, which will free us 29 characters, which is 9 or 14 pixels (depending on the number of spaces per pixel).
This is very important because the size of the image is limited by the maximum message length in Skype.
This optimization has already been implemented by several Habrausers, so I see no reason to bring its entire code again.
I will describe in more detail only the comparison of colors.
Experimentally, we came to the following function:
// compare colors
function compare_clr( $c1, $c2, $max_dif, $img_px_qs )
{
$r1 = ( $c1 >> 16 ) & 0xFF;
$g1 = ( $c1 >> 8 ) & 0xFF;
$b1 = $c1 & 0xFF;
$r2 = ( $c2 >> 16 ) & 0xFF;
$g2 = ( $c2 >> 8 ) & 0xFF;
$b2 = $c2 & 0xFF;
$r_dif = abs( $r1 - $r2 );
$g_dif = abs( $g1 - $g2 );
$b_dif = abs( $b1 - $b2 );
$k = 1;
if( $img_px_qs == 1 ) // max quality
{
$def_k = 0.65;
// check difference in color channels
$dr = ( $r_dif > 0 ) ? $def_k : 0;
$dg = ( $g_dif > 0 ) ? $def_k : 0;
$db = ( $b_dif > 0 ) ? $def_k : 0;
$k = $dr + $dg + $db;
if( $k < 1 )
{
$k = 1;
}
}
else // max size
{
$k = 1;
}
$rv = true;
if( ( $r_dif*$k > $max_dif ) || ( $g_dif*$k > $max_dif ) || ( $b_dif*$k > $max_dif ) )
{
$rv = false;
}
return $rv;
}
The first two parameters are colors, the 3rd parameter is the comparison threshold, the maximum difference between color channels (0-255), the 4th parameter is maximum quality or maximum size.
If we compare the whole colors with each other, without making a difference between the channels (r, g, b), then the picture quality leaves much to be desired. The picture is very “smeared” very quickly.
Therefore, we compare individual channels. If the color difference in at least one channel exceeds the threshold, the colors are considered different.
The formula with coefficients gives the best quality and best removes blur. It is better suited for complex multi-color pictures (photo).
A simple comparison gives a larger size, but in complex pictures, blur appears even on small comparison thresholds. But this formula allows you to generate larger images for simple emoticons and black and white troll faces.
2. Primary color
Another important optimization that also lies on the surface is the background color.
Quote:
“You can still not color the black pixel, because it is already black.”
The black pixel is actually not black, but default. Its color is set by the first tag in the code, which img4skype has no color and therefore default (almost black):
...
If you add the font color to the first tag, then it will be the default color for the whole picture:
...
And then for each red pixel or their sequence there is no need to insert a tag, just close it from the previous color and write whitespace without tags.
If the picture is a logo / emoticon / picture on a uniform background, then this optimization gives a very large increase in size.
So, before generating the image code, you must first go through all the pixels and find the most common color:
imagecopyresampled( $newimg, $img, 0, 0, 0, 0, $neww, $newh, $imgw, $imgh );
// find most popular color
$c_arr = array();
for( $j = 0; $j < $newh; $j++ )
{
for( $i = 0; $i < $neww; $i++ )
{
$cur_clr = imagecolorat( $newimg, $i, $j );
if( isset( $c_arr[$cur_clr] ) )
{
$c_arr[$cur_clr]++;
$found = true;
}
else
{
$c_arr[$cur_clr] = 1;
}
}
}
$max_cnt = 0;
$def_clr = 0; // most popular color
foreach( $c_arr as $key => $val )
{
if( $val > $max_cnt )
{
$max_cnt = $val;
$def_clr = $key;
}
}
3. Maximum size
Further more, it was quickly discovered that people wanted to play around with the sizes and change the constant 800 in this formula:
$newh = floor(sqrt(800 / $ratio));
Some pictures can be made larger, the code for them is placed on Skype if you replace 800 with 1000 or 1200, and some cannot even fit at 800.
Therefore, the next step is to make this constant a variable that the user can select.
But this is half measure, because now you have to painstakingly tinker with the parameters to make the picture as large as possible in size and quality.
Therefore, we immediately generate the maximum possible picture. Using the method of dividing the segment in half, we generate the code until we get the result with the maximum value of the constant in the formula above and the maximum possible length that fits in the Skype message.
Now users should only care about quality that only the human eye can evaluate.
Everything else we do for them.
PS
Having discovered that img4skype.com is not developing (even implemented ideas with ready-made code are not added), we decided to create our own analogue - skypeimg.com . Everything that is written about in this article is implemented here.
All functions are “time-tested” - they have been working on our service since 01/20/2012.
Here are a couple of examples of the work of our generator (screenshots from Skype on a 1: 1 scale):

I would like to say thanks to zhovner for the original idea, and wish to fully implement simple and self-evident functionality in the future, so as not to provoke the emergence of competitors!
UPD Comments have been taken into account, the site has been updated, all questionable content has been removed. The gallery no longer shows what users generate, only pictures from albums.