static int cb_image_menu_generic(nbio_handle_t *nbio) { unsigned width = 0, height = 0; int retval; if (!nbio) return -1; if (!rpng_is_valid(nbio->image.handle)) return -1; retval = rpng_nbio_load_image_argb_process(nbio->image.handle, &nbio->image.ti.pixels, &width, &height); nbio->image.ti.width = width; nbio->image.ti.height = height; if (retval == IMAGE_PROCESS_ERROR) return -1; if (retval == IMAGE_PROCESS_ERROR_END) return -1; nbio->image.is_blocking_on_processing = true; nbio->image.is_finished = false; return 0; }
static bool rpng_load_image_argb(const char *path, uint32_t **data, unsigned *width, unsigned *height) { int retval; size_t file_len; bool ret = true; rpng_t *rpng = NULL; void *ptr = NULL; struct nbio_t* handle = (struct nbio_t*)nbio_open(path, NBIO_READ); if (!handle) goto end; nbio_begin_read(handle); while (!nbio_iterate(handle)); ptr = nbio_get_ptr(handle, &file_len); if (!ptr) { ret = false; goto end; } rpng = rpng_alloc(); if (!rpng) { ret = false; goto end; } if (!rpng_set_buf_ptr(rpng, (uint8_t*)ptr)) { ret = false; goto end; } if (!rpng_start(rpng)) { ret = false; goto end; } while (rpng_iterate_image(rpng)); if (!rpng_is_valid(rpng)) { ret = false; goto end; } do { retval = rpng_process_image(rpng, (void**)data, file_len, width, height); }while(retval == IMAGE_PROCESS_NEXT); if (retval == IMAGE_PROCESS_ERROR || retval == IMAGE_PROCESS_ERROR_END) ret = false; end: if (handle) nbio_free(handle); if (rpng) rpng_free(rpng); rpng = NULL; if (!ret) free(*data); return ret; }
static bool rpng_load_image_argb_iterate(FILE **fd, rpng_t *rpng) { struct png_chunk chunk = {0}; FILE *file = *fd; if (!read_chunk_header_fio(fd, &chunk)) return false; switch (png_chunk_type(&chunk)) { case PNG_CHUNK_NOOP: default: if (fseek(file, chunk.size + sizeof(uint32_t), SEEK_CUR) < 0) return false; break; case PNG_CHUNK_ERROR: return false; case PNG_CHUNK_IHDR: if (rpng_is_valid(rpng)) return false; if (!png_parse_ihdr_fio(fd, &chunk, &rpng->ihdr)) { png_free_chunk(&chunk); return false; } if (!png_process_ihdr(&rpng->ihdr)) { png_free_chunk(&chunk); return false; } png_free_chunk(&chunk); rpng->has_ihdr = true; break; case PNG_CHUNK_PLTE: { uint8_t buf[256 * 3]; unsigned entries = chunk.size / 3; if (!rpng->has_ihdr || rpng->has_plte || rpng->has_iend || rpng->has_idat) return false; if (chunk.size % 3) return false; if (entries > 256) return false; if (fread(rpng->palette, 3, entries, *fd) != entries) return false; if (!png_read_plte(&buf[0], rpng->palette, entries)) return false; if (fseek(*fd, sizeof(uint32_t), SEEK_CUR) < 0) return false; rpng->has_plte = true; } break; case PNG_CHUNK_IDAT: if (!rpng->has_ihdr || rpng->has_iend || (rpng->ihdr.color_type == PNG_IHDR_COLOR_PLT && !rpng->has_plte)) return false; if (!png_realloc_idat(&chunk, &rpng->idat_buf)) return false; if (fread(rpng->idat_buf.data + rpng->idat_buf.size, 1, chunk.size, file) != chunk.size) return false; if (fseek(file, sizeof(uint32_t), SEEK_CUR) < 0) return false; rpng->idat_buf.size += chunk.size; rpng->has_idat = true; break; case PNG_CHUNK_IEND: if (!rpng->has_ihdr || !rpng->has_idat) return false; if (fseek(file, sizeof(uint32_t), SEEK_CUR) < 0) return false; rpng->has_iend = true; break; } return true; }