📜 ⬆️ ⬇️

Creating a brickwork for the site

The company Sidzheko is engaged in supporting the website of the organization Reconstroy , which sells and delivers brick, tile, architectural decor and many other building materials in the Central Black Earth Region.

In the process of working on the site, the idea of ​​a brickwork appeared.

The German concern " Feldhaus Klinker " has model series of brick "Vascu Mix" and "Sintra Mix", which are specifically designed to mix in different proportions and create a unique pattern of masonry. There are a number of “Quick Mix” putties applied to them, when the joints of masonry joints between bricks are plastered over. To demonstrate this approach, we decided to make a brickwork constructor, which I haven’t seen yet in the runet (I will be happy with examples).
')




On the bricks and seams, shadows and scratches are superimposed to bring the drawing as close to life as possible. Switches decided to stylize a touch device. For the designer, hundreds of images were processed: photos of clutches, bricks, putties for seams, etc.

Mode "Drunk Master" - fun for:

« »



Process


We leave the designer with the pictures (in fact, the amount of work there is disproportionately more than the programmer side of the matter), Dima's fronterer does nicely on the client side, I try to make it to his skill on the backend.

So…

Basic steps


We take all the possible photos of the clutches that we could only find in the company's promotional materials, add our photos.

Cut bricks, we clipping them with transparent fields.

We bring images of bricks to one size. From each model we need a few real photos, so that as a result it would be boring.



Virtual clutch is not built in the same sequence as the real one :-)
So, first fill the entire field with a picture of the seam, propagating it to the desired size of the picture.

image

Then we fill a layer of bricks in which different models of a ruler are mixed in the necessary proportion. Even rows are shifted horizontally by half a half from odd ones. (There are other drawings of clutches for business lovers, but so far it has been decided to focus on the classic in order to meet the deadlines.)

image

It would be possible to stop, but it looks too refined. Reality is always better: rubbing, scratching - the appearance of each thing reflects its history. It is necessary to artificially “wear out” the image with noises.

You can make noise simply by randomly changing each pixel of the image. But it works for a long time, and it doesn't look very good: we, after all, want to emulate the real texture of materials, and not the ISO-noise of the camera.

//  () for ($x = 0; $x < $allWidth; $x++) for ($y = 0; $y < $allHeight; $y++) imagesetpixel($image, $x, $y, imagecolorallocatealpha($image, 0xff, 0xff, 0xff, MyRand::rand(115, 127))); 

Random noise

Let's go in a more interesting way (which, moreover, will greatly save the time of image generation) - apply “scratches”.

Scratches are essentially lines of white and black with random length, inclination and transparency. If the upper part of the line is light and the lower part is dark, it looks like a bulge in the image, if the upper part is dark and the lower light looks like a scratch (bulge, yes).

 //   () //    for ($x = 0; $x < 5000; $x++) { $dotX = MyRand::rand(0, $allWidth); $dotY = MyRand::rand(0, $allHeight); $scratchWidth = MyRand::rand(1, 8); // 80% - (+1)  20%  (-1) $scratchAdj = MyRand::rand(0, 10) > 8 ? -1 : +1; for ($i = 0; $i < $scratchWidth; $i++) { imagesetpixel($image, $dotX+$i, $dotY+$scratchAdj, imagecolorallocatealpha($image, 0xff, 0xff, 0xff, MyRand::rand(95, 110))); imagesetpixel($image, $dotX+$i, $dotY, imagecolorallocatealpha($image, 0x00, 0x00, 0x00, MyRand::rand(95, 110))); } } 



Without noise and with them:



It remains to apply the copyright. Load the font (Ubuntu will do).

 imagettftext($image, 10, 90, $allWidth - 7, $allHeight - 7, imagecolorallocatealpha($image, 0, 0, 0, 90), 'font/ubuntu-r.ttf', 'Sijeko Brick Generator ' . GENERATOR_VERSION); 



Done!

The output constructor can produce both JPEG and PNG (all source images in PNG24), but due to the large size of the resulting PNG, we stopped at JPEG.

Caching and URLs

The second time to build an image with the same input parameters is not necessary, we will spare the processor and the user; save the image at the first call and issue it from the cache on subsequent ones.

The ID of the image cache (the same - the file name) must be the same for any order of variables in the GET part of the URL. Therefore, we first delete all unnecessary variables (keys and values ​​that can be manually substituted into the URL), and then sort the $_GET global array by keys:

 //   (         ) ksort($_GET); 

Then we get the rest of the identifier:

 $fileIdentifier = 'images/cache/' . $randSeed; $fileIdentifier .= sprintf( '/lineup-%s_color-%d_drunk-%s_', $lineup, $backFile, $isDrunk ? 'on' : 'off' ); foreach ($_GET as $key => $value) { if (!empty($value)) $fileIdentifier .= preg_replace('/[^a-z0-9_-]/ui', '', $key) . '-' . preg_replace('/[^a-z0-9_-]/ui', '', $value) . '_'; } $fileIdentifier = rtrim($fileIdentifier, '_'); $fileIdentifier .= '.' . OUTPUT_FORMAT; 


Do not forget about HTTP headers associated with caching:

 header('Cache-Control: Public'); header('Pragma: Public'); header('Last-Modified: ' . gmdate('D, d MYH:i:s', $time) . ' GMT'); header('Expires: ' . gmdate('D, d MYH:i:s', $time + 30*24*60*60) . ' GMT'); 


Random number generator

To fully follow the url philosophy, the same picture should always be displayed for each link. But we have a lot of random factors in the system (noise, unevenness). To be extremely precise, we need not a pseudo-random number generator (PRNG), but a pseudo-random sequence generator (PRN). Each sequence defined by a certain identifier ( seed ) must be unique and repeatable.

In new versions of PHP (≥5.2.1), the mt_rand() generator stopped issuing the same sequences with the same mt_srand($seed) parameter mt_srand($seed) at least, it is recommended not to count on this behavior). Let's write your bike. Since we do not need cryptographic security from the generator, we will use one of the most popular and simple methods - multiplication with transfer.

 /** *        . * @param integer $min * @param integer $max * @return integer */ public static function rand($min = 0, $max = 0xffffffff) { self::$m_z = 36969 * (self::$m_z & 65535) + (self::$m_z >> 16); self::$m_w = 18000 * (self::$m_w & 65535) + (self::$m_w >> 16); $res = ((self::$m_z << 16) + self::$m_w) & 0xffffffff; $res = $res > 0 ? $res : ~$res; //var_dump($res, PHP_INT_MAX, 0xffffffff); die; return intval($min + floor(($res / doubleval(0xffffffff)) * ($max - $min + 1))); } 

Where self::$m_z and self::$m_w are static fields of the current state of the generator. For the same given set of self::$m_z and self::$m_w generator will produce the same pseudo-random sequences of integers.

Drunk Master Mode

Turn each brick to a random angle in a narrow range of inclination, and the drunk master is already working on your wall.

Varying the range of inclination in degrees, you can change the amount and degree drunk (sorry for the pun). I stopped at ± 3.2 °.

Links


Source: https://habr.com/ru/post/203840/


All Articles