In the last article, we have learned many functions in GraphicsMagick, and also said that GraphicsMagick is a branch of ImageMagick, so many of their functions are used in the same way and effect. We will not say more about similar content. Interested friends can directly consult the official documents.
In this article, we are going to study a specific case, and it is also a case that I have come into contact with in actual business development. The specific effect is that for WeChat mini-games and mini-programs, dynamic Gif pictures cannot be used directly. A Gif picture will not move in mini-games or mini-programs. Therefore, in our company’s game development, we need a picture of each frame of the entire Gif animation to be assembled into a sprite image and handed over to the front end, and they will use the ability of JS+CSS to dynamically cycle after the frame is removed. , Thus forming the effect of moving pictures.
Business requirements are such a situation, of course, the final solution is also implemented using ImageMagick. Not much to say, let's look at the code first.
GIF picture unframed
The original picture is an animated picture like this:
$imgPath = '../img/4.gif';
$imagick = new \Imagick($imgPath);
$imagick = $imagick->coalesceImages();
$imageCount = $imagick->count();
echo 'image count:', $imageCount, PHP_EOL; // image count:51
$imgAttrs = [
'width' => $imagick->getImageWidth(),
'height' => $imagick->getImageHeight(),
'frame_count' => $imageCount,
];
$column = 5;
if ($imageCount < $column) {
$column = $imageCount;
}
$row = ceil($imageCount / $column);
$spImgWidth = $imgAttrs['width'] * $column;
$spImgHeight = $imgAttrs['height'] * $row;
// 创建图片
$spImg = new \Imagick();
$spImg->setSize($spImgWidth, $spImgHeight);
$spImg->newImage($spImgWidth, $spImgHeight, new \ImagickPixel('#ffffff00'));
$spImg->setImageFormat('png');
$i = 0;
$h = 0;
$cursor = 0;
do {
if ($i == $column) {
$i = 0;
$h++;
}
if($cursor == 0){ // 保存第一帧图片
$imagick->writeImage($imgPath . '.first.png');
}
// 保存全部的图片帧到一张 png 图片中
$spImg->compositeImage($imagick, \Imagick::COMPOSITE_DEFAULT, $i * $imgAttrs['width'], $h * $imgAttrs['height']);
$i++;
$cursor++;
} while ($imagick->nextImage());
$spImg->writeImage($imgPath . '.png');
Needless to say when instantiating the Imagick object, we first call the coalesceImages() method. Its role is to return the synthesized Imagick object. Through this method, we get all the information of each frame in the entire GIF image. At this time, using the count() method, you can get the number of all picture frames in the picture. For example, the picture we tested has 51 frames.
Then calculate the rows and columns of the sprite image and the corresponding width and height. For example, we take 5 columns as the benchmark, that is, put five unframed pictures in one row, so that a total of 11 rows are needed to put the final generated sprite image. In the same way, the width and height of the picture are multiplied by the corresponding number of columns and rows.
Then, generate a new picture according to the calculated width and height, as the background image of the sprite, use the newImage() function to set the width and height of the picture and the background transparency. Use the setImageFormat() method to set the image format to PNG format. PNG is used mainly for transparency. In fact, for images that are closely arranged like ours, it is not necessary to be transparent. However, in some applications such as the sprite image required by the front end of the website may be different Before the pictures need a certain interval, so generally use a transparent base map.
Then there is a loop, which is to loop the 51 unframed pictures, use nextImage() to continuously get the next picture in the original GIF picture, and save them in the newly created background picture above, each frame The position of the picture is also calculated by the width, height and rank of the single frame picture. In this code, we also save the picture of the first frame. Of course, this is also a business need. You can save any picture of each frame at any time.
Finally, use writeImage() to save the image. The output picture looks like this:
Combine into a dynamic GIF image
The above business functions are the functions that I have actually used in the development. Of course, in addition to deframing the GIF image, we can also combine multiple images into a dynamic GIF image.
$gifImagek = new Imagick();
$gifImagek->setFormat('GIF');
for($i=1;$i<=5;$i++){
$img = new Imagick('../img/3'.$i.'.jpeg');
$img->setImageDelay(100);
$gifImagek->addImage($img);
}
$gifImagek->writeImages("../img/5.gif", true);
$gifImagek->writeImages("../img/52.gif", false);
This code is relatively simple, still create a picture, and specify the format as a GIF picture. Then add pictures in a loop, here we use the pictures that were manipulated in GraphicsMagick in the previous article. setImageDelay() is used to set the picture display interval, here we set it to 100 milliseconds, and then use addImage() to add the picture to our newly created GIF picture canvas.
When you finally save the picture, you need to use writeImages() to save it. Its function is to save this continuous multiple pictures. Its second parameter is to specify whether to save the picture in a picture, if it is false, it is similar to the effect of frame splitting, but the pictures will be saved one by one, such as 52-1.gif, 52-2.gif like this.
The final animation is like this:
Summarize
Today’s content is interesting. It’s not functions like zooming, watermarking, and verification codes, but more fun operations on GIF images. To be honest, there are still many similar business scenarios in business development. The function of automatically generating sprite graphs can be implemented using ImageMagick, and it can be done with the functions that come with the ImageMagick extension, which is very convenient.
Test code:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202012/source/5. Use ImageMagick to operate
Reference documents:
https://www.php.net/manual/zh/book.imagick.php
Searchable on each media platform【Hardcore Project Manager】
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。