static size_t tga2rgb(ss_t **rgb, struct RGB_Info *ri, const ss_t *tga) { const char *t = ss_get_buffer_r(tga); const size_t ts = ss_size(tga); RETURN_IF(ts < TGA_RGBHDR || !valid_tga(t), 0); set_rgbi(ri, S_LD_LE_U16(t + TGA_W), S_LD_LE_U16(t + TGA_H), t[TGA_BPP], t[TGA_TYPE] == TGA_RAW_GRAY ? 1 : t[TGA_BPP]/8); RETURN_IF(!valid_rgbi(ri), 0); size_t rgb_bytes = ri->row_size * ri->height; RETURN_IF(ts < rgb_bytes + TGA_RGBHDR, 0); RETURN_IF(ss_reserve(rgb, rgb_bytes) < rgb_bytes, 0); if ((t[TGA_DESC] & TGA_TOP_LEFT) != 0) { if (ri->chn == 1) ss_cpy_cn(rgb, t + TGA_RGBHDR, rgb_bytes); else tga_rgb_swap(ri->bpp, rgb_bytes, ss_get_buffer_r(tga) + TGA_RGBHDR, ss_get_buffer(*rgb)); } else { ss_set_size(*rgb, 0); ssize_t i = (ssize_t)(ri->height - 1) * ri->row_size; for (; i >= 0; i -= ri->row_size) if (ri->chn == 1) ss_cat_cn(rgb, t + TGA_RGBHDR + i, ri->row_size); else tga_rgb_swap(ri->bpp, ri->row_size, t + TGA_RGBHDR + i, ss_get_buffer(*rgb) + i); } ss_set_size(*rgb, rgb_bytes); return rgb_bytes; }
ss_t *ss_cpy_cn(ss_t **s, const char *src, const size_t src_size) { ASSERT_RETURN_IF(!s, ss_void); ASSERT_RETURN_IF(!src || !src_size, ss_clear(s)); /* BEHAVIOR: empty */ if (*s) ss_clear(s); ss_cat_cn(s, src, src_size); return ss_check(s); }
static void aux_png_write(png_structp s, png_bytep d, png_size_t ds) { ss_cat_cn((ss_t **)png_get_io_ptr(s), (char *)d, ds); }