this function is designed to support animated gifs, although stb_image doesn't support it two back is the image from two frames ago, used for a very specific disposal format
| 6776 | // this function is designed to support animated gifs, although stb_image doesn't support it |
| 6777 | // two back is the image from two frames ago, used for a very specific disposal format |
| 6778 | static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) |
| 6779 | { |
| 6780 | int dispose; |
| 6781 | int first_frame; |
| 6782 | int pi; |
| 6783 | int pcount; |
| 6784 | STBI_NOTUSED(req_comp); |
| 6785 | |
| 6786 | // on first frame, any non-written pixels get the background colour (non-transparent) |
| 6787 | first_frame = 0; |
| 6788 | if (g->out == 0) { |
| 6789 | if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header |
| 6790 | if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) |
| 6791 | return stbi__errpuc("too large", "GIF image is too large"); |
| 6792 | pcount = g->w * g->h; |
| 6793 | g->out = (stbi_uc *) stbi__malloc(4 * pcount); |
| 6794 | g->background = (stbi_uc *) stbi__malloc(4 * pcount); |
| 6795 | g->history = (stbi_uc *) stbi__malloc(pcount); |
| 6796 | if (!g->out || !g->background || !g->history) |
| 6797 | return stbi__errpuc("outofmem", "Out of memory"); |
| 6798 | |
| 6799 | // image is treated as "transparent" at the start - ie, nothing overwrites the current background; |
| 6800 | // background colour is only used for pixels that are not rendered first frame, after that "background" |
| 6801 | // color refers to the color that was there the previous frame. |
| 6802 | memset(g->out, 0x00, 4 * pcount); |
| 6803 | memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) |
| 6804 | memset(g->history, 0x00, pcount); // pixels that were affected previous frame |
| 6805 | first_frame = 1; |
| 6806 | } else { |
| 6807 | // second frame - how do we dispose of the previous one? |
| 6808 | dispose = (g->eflags & 0x1C) >> 2; |
| 6809 | pcount = g->w * g->h; |
| 6810 | |
| 6811 | if ((dispose == 3) && (two_back == 0)) { |
| 6812 | dispose = 2; // if I don't have an image to revert back to, default to the old background |
| 6813 | } |
| 6814 | |
| 6815 | if (dispose == 3) { // use previous graphic |
| 6816 | for (pi = 0; pi < pcount; ++pi) { |
| 6817 | if (g->history[pi]) { |
| 6818 | memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); |
| 6819 | } |
| 6820 | } |
| 6821 | } else if (dispose == 2) { |
| 6822 | // restore what was changed last frame to background before that frame; |
| 6823 | for (pi = 0; pi < pcount; ++pi) { |
| 6824 | if (g->history[pi]) { |
| 6825 | memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); |
| 6826 | } |
| 6827 | } |
| 6828 | } else { |
| 6829 | // This is a non-disposal case eithe way, so just |
| 6830 | // leave the pixels as is, and they will become the new background |
| 6831 | // 1: do not dispose |
| 6832 | // 0: not specified. |
| 6833 | } |
| 6834 | |
| 6835 | // background is what out is after the undoing of the previou frame; |
no test coverage detected