preface
“How can we chat without emojis?”
As the ultimate antidote to human communication dilemmas, there’s no scene that a meme can’t express. Imagine, when you are opening N VSCode frantically at the same time, a loud DING~, the product manager sent a message: have you fixed the bugs mentioned yesterday?
Based on the principle of “if you can send pictures, don’t type”, it’s time to make a favorite folder with a big killer ↓
Simple giFs create a space for communication, and these are the giFs we all use.
Business background
However, in the scenario of risk control, the black gray industry uses the multi-frame features of GIF pictures to inject illegal pictures into them, and then disguises ordinary pictures by manually modifying file extensions, which undoubtedly increases the difficulty of risk prevention and control. Flash through the illegal master map, so that the operation of small two cannot be prevented; The picture is finally fixed on the last frame that seems to have no problem, which makes it difficult for the operator to capture the effective key information.
GIF images have the nature of “motion”, but in the Web is treated as an image processing without any special treatment API, so there is no control over GIF image playback, pause, end listening events **. ** So is there a way to animate a GIF that flashes by and freezes at the end of the frame? Let’s dig deeper and disentangle what’s in a GIF.
GIF Format
Graphics Interchange Format, for short, is a bit-graphics file Format that recreates true-color images in 8 bit colors (256 colors). Internally, GIF files are divided into blocks that store multiple images or control blocks that determine the behavior of images. For animation and interactive applications. GIF has two versions, GIF87a and GIF89a.
GIF is a bitmap. The rough idea behind bitmaps is that an image is made up of many pixels, each assigned a color, that together make up the image. The 8-bit “bit” is the color depth, which is determined by the bit depth of an image and is simply how many colors can be supported (for example, a pixel with bit depth of 1 has two values: black and white. The greater the bit depth, the more colors the image can contain and the more accurate the color representation, 8-bit GIF image can contain up to 256 colors)
The GIF87a version, introduced in 1987, stores one image per file and strictly does not support transparent pixels; GIF87a adopts LZW compression algorithm, which can compress image size by 20 to 25 percent on the premise of maintaining image quality.
GIF89a version is a very distinctive version introduced in 1989. This version allows multiple images to be stored in a file, can be animated, and allows certain pixels to be transparent. In this version, the GIF document has expanded the graphics control block, remarks, instructions, application programming interface four blocks, and provides transparent color and multi-frame animation support, if these images are continuously played out, can form the simplest animation. Therefore, it is often used to store “dynamic pictures”, which are usually short in time, small in size, simple in content and relatively clear in imaging. The current GIF version is 89A.
GIF file structure disassembled
To understand how a picture “moves”, first understand how it is stored. Let’s take a look at the GIF image file structure using an image from the web:
What’s In A GIF
GIF files are stored in blocks, which are divided into three parts:
- File Header
- GIF Data Stream
- Trailer end
Among them, the data flow of text Extension, application Extension and comment Extension we skip without looking at, let the picture “move” the secret is in Graphic Control Extension. Let’s use a chestnut to find out.
The sample preparation
The sample images
This paper analyzes the data, all based on the sample picture.
Hex converter
portal
The file header
The first 6 bytes of the GIF file are the signature and version number of the GIF. Through the console printing, we can get:
We can get 47, 49, 46, 38, 39, 61 for GIF 89A
Simple! Continue reading ↓
GIF data flow
Graphical control extension
It is not difficult for us to find through observation that the image will flash instantaneously. Compared with the emoticon picture at the beginning of the article, why can some GIFs be played in a loop all the time while others flash instantaneously and then freeze in the second frame?
In version 89A, GIF added a graphical control extension block, which was placed before an Image Descriptor to control the display of the first Image immediately following it. The structure of the graphical control extension block is shown below:
As can be seen from the figure above, the structure of the whole extension block is as follows:
describe | The length of the |
---|---|
Extension block identifier | 1 byte, fixed value 0x21 |
Extension block identification | 1 byte, fixed value 0xF9 |
Extension block Indicates the length of the extension block | 1 byte |
Keep a | three |
The disposal method | three |
User input flag | 1 a |
Transparent color mark | 1 a |
Delay time | 2 – |
Transparent color index | 1 byte |
Extended piece of tail | 1 byte, fixed value 0x00 |
Found it! The culprit is ** latency! ** Delay time indicates the need to pause the delay time before continuing to process the data stream. Here, it can be understood as the dwell time of each frame in the GIF, and the unit is 1/100 second.
At this point in the analysis, there is a sense of clarity. Back in the code, we can see from the console that the data parsed from the original image looks like this:
Delay time: 00 00, hexadecimal to decimal: 0
By manually setting the delay time, we can make the flash image “move” :
Manually changed delay time: 32 00 (800 in hexadecimal format)
The core code is as follows:
let p = 0; // The current Buffer processes the corresponding subscript
while (notEndOfFile && p < contentBuffer.length) {
...
switch (contentBuffer[p++]) {
case 0xf9: // Graphics Control Extension
if(contentBuffer[p++] ! = =0x4 || contentBuffer[p+4]! = =0)
throw new Error("Invalid graphics extension block.");
p++; // graphicPackedFiled
if (delay) {
const delayArr = numberToByteArr(delay);
contentBuffer[p] = delayArr[delayArr.length - 1];
contentBuffer[p+1] = delayArr[delayArr.length - 2] | |0;
}
p = p + 4; // Skip delay 2 bytes, transparentIndex 1 byte, end symbol 1 byte
break; }}Copy the code
At the end of file
When all of the subimage data has been parsed, the end of the file is encountered, where a single byte with a value of 0 marks the end of a GIF file. The end of the file is 0x3B
Write in the last
In the last article to solve the problem of cross-domain image, the author has introduced that with the help of the team Serverless ability to build cross-domain image forwarding server, the GIF file parsing scheme is built on the original BFF layer basic ability.
Octopus Picture forwarding service details
Request address: HTTPS://xxx.fc.alibaba-inc.com/gifTransformerRequest method: GET Parameter: URL: mandatory, address of the image to be parsed Loop: non-mandatory, number of GIF loops Delay: non-mandatory, playback time of each frame (ms) of a GIF Result: parsed GIFCopy the code
GIF figure analysis final landing risk investigation business, to solve the business has been a headache of black ash production illegal master map difficult to determine the problem, interested students might as well start to try.
Refer to the link
- What’s In A GIF
Author: ES2049 | black eyed peas
The article can be reproduced at will, but please keep the original link.
You are welcome to join ES2049 Studio. Please send your resume to [email protected].