diff options
Diffstat (limited to 'src/file_aseprite.c')
| -rw-r--r-- | src/file_aseprite.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/file_aseprite.c b/src/file_aseprite.c new file mode 100644 index 00000000..09721094 --- /dev/null +++ b/src/file_aseprite.c @@ -0,0 +1,132 @@ +/* + + File: file_aseprite.c + + Copyright (C) 2006-2009,2021 Christophe GRENIER <grenier@cgsecurity.org> + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ + +#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_aseprite) +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#include <stdio.h> +#include "types.h" +#include "filegen.h" +#include "common.h" + +#ifdef DEBUG_ASEPRITE +#include "log.h" +#endif + +/* file format spec: https://github.com/aseprite/aseprite/blob/main/docs/ase-file-specs.md */ + +/*@ requires valid_register_header_check(file_stat); */ +static void register_header_check_aseprite(file_stat_t *file_stat); + +const file_hint_t file_hint_aseprite= { + .extension="aseprite", + .description="LibreSprite/Aseprite .ase/.aseprite Files.", + .max_filesize=PHOTOREC_MAX_FILE_SIZE, + .recover=1, + .enable_by_default=1, + .register_header_check=®ister_header_check_aseprite +}; + +struct aseprite_file_header +{ + uint32_t file_size; + uint16_t magic; /* must be 0xA5E0 */ + uint16_t frames; /* number of frames */ + uint16_t width; /* Width in pixels */ + uint16_t height; /* Height in pixels */ + uint16_t color_depth; /* Bits per pixel (32 bpp = RGBA; 16 bpp GRAYSCALE; 8 bpp INDEXED;) */ + uint32_t flags; /* flags */ + uint16_t speed; /* speed (miliseconds between frames) + DEPRECATED: frame's frame duration field used instead. */ + uint32_t reserved1; /* must be 0 */ + uint32_t reserved2; /* must be 0 */ + uint8_t pallete; /* Pallete entry (index). Only for indexed sprites. */ + uint8_t reserved3[3]; /* must be 0 */ + uint16_t ncolors; /* Number of colors (0 means 256 for old sprites) */ + uint8_t pixel_width; /* Pixel ratio = pixel_width/pixel_height; + If this or pixel_height equals to 0, pixel ratio = 1:1 */ + uint8_t pixel_height; /* Pixel Height */ + int16_t x_grid; /* X position on grid. */ + int16_t y_grid; /* Y position on grid. */ + uint16_t grid_w; /* Grid width. Zero if no grid. */ + uint16_t grid_h; /* Grid Height. Zero if no grid. */ + uint8_t reserved4[84]; /* For future. Set to zero (0). */ +} __attribute__ ((gcc_struct, __packed__)); + +/*@ + @ requires buffer_size >= sizeof(struct aseprite_file_header); + @ requires separation: \separated(&file_hint_aseprite, buffer+(..), file_recovery, file_recovery_new); + @ requires valid_header_check_param(buffer, buffer_size, safe_header_only, file_recovery, file_recovery_new); + @ ensures valid_header_check_result(\result, file_recovery_new); + @ assigns *file_recovery_new; +*/ +static int header_check_aseprite(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) +{ + const struct aseprite_file_header *hdr= (const struct aseprite_file_header *)buffer; + + const unsigned int file_size = le32(hdr->file_size); + const unsigned int frames = le16(hdr->frames); + const unsigned int width = le16(hdr->width); + const unsigned int height = le16(hdr->height); + const unsigned int reserved1 = le32(hdr->reserved1); + const unsigned int reserved2 = le32(hdr->reserved2); + const unsigned int color_depth = le16(hdr->color_depth); + +#ifdef DEBUG_ASEPRITE + log_info("file size %u\n", file_size); + log_info("frames %u\n", frames); + log_info("height %u\n", height); + log_info("width %u\n", width); + log_info("depth %u\n", color_depth); +#endif + + if (file_size < sizeof(struct aseprite_file_header) || + frames==0 || frames > 65535 || + width==0 || width > 65535 || + height==0 || height > 65535 || + reserved1!=0 || reserved2!=0 || + (color_depth!=8 && color_depth!=16 && color_depth!=32) + ) + return 0; + + reset_file_recovery(file_recovery_new); + file_recovery_new->extension=file_hint_aseprite.extension; + file_recovery_new->calculated_file_size=file_size; + file_recovery_new->data_check=&data_check_size; + file_recovery_new->file_check=&file_check_size; + return 1; +} + +/* + Will register specific file header check function. +*/ +static void register_header_check_aseprite(file_stat_t *file_stat) +{ + static const unsigned char aseprite_header[2]={ 0xE0, 0xA5 }; + register_header_check(4, aseprite_header,sizeof(aseprite_header), &header_check_aseprite, file_stat); +} + +#endif |
