Skip to content

Commit 3d20ef0

Browse files
committed
texture: Clean up texture code and do not recalculate size when loading images
1 parent 00ee2d6 commit 3d20ef0

4 files changed

Lines changed: 105 additions & 86 deletions

File tree

app/include/textures.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ extern g2dTexture *file_icons[NUM_FILE_ICONS], *icon_dir[NUM_THEMES], *icon_chec
1919
namespace Textures {
2020
g2dTexture *LoadImageBufferJPEG(unsigned char *data, int size);
2121
g2dTexture *LoadImageBufferPNG(unsigned char *data, int size);
22-
g2dTexture *LoadImage(const std::string &path);
22+
g2dTexture *LoadImage(const std::string &path, int size);
2323
void Load(void);
2424
void Free(void);
2525
}

app/source/gui/filebrowser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ namespace GUI {
131131
break;
132132

133133
case FileTypeImage:
134-
item.texture = Textures::LoadImage(path.c_str());
134+
item.texture = Textures::LoadImage(path.c_str(), item.entries[item.selected].d_stat.st_size);
135135
if (item.texture)
136136
item.state = MENU_STATE_IMAGEVIEWER;
137137
break;

app/source/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
PSP_MODULE_INFO("CMFileManager", 0x800, VERSION_MAJOR, VERSION_MINOR);
1313
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
14+
PSP_HEAP_THRESHOLD_SIZE_KB(1024);
1415
PSP_HEAP_SIZE_KB(-2048);
1516

1617
bool g_running = true;

app/source/textures.cpp

Lines changed: 102 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -59,59 +59,49 @@ g2dTexture *file_icons[NUM_FILE_ICONS], *icon_dir[NUM_THEMES], *icon_check[NUM_T
5959
*bg_header, *icon_sd[NUM_THEMES], *icon_secure[NUM_THEMES], *ic_play_btn, *ftp_icon[NUM_THEMES], *sort_icon[NUM_THEMES], \
6060
*dark_theme_icon[NUM_THEMES], *dev_options_icon[NUM_THEMES], *about_icon[NUM_THEMES];
6161

62-
namespace BMP {
63-
static void *bitmap_create(int width, int height, [[maybe_unused]] unsigned int state) {
62+
namespace Image {
63+
static void *Create(int width, int height, [[maybe_unused]] unsigned int state) {
6464
/* ensure a stupidly large (>50Megs or so) bitmap is not created */
65-
if ((static_cast<long long>(width) * static_cast<long long>(height)) > (MAX_IMAGE_BYTES/BYTES_PER_PIXEL))
65+
if ((static_cast<long long>(width) * static_cast<long long>(height)) > (MAX_IMAGE_BYTES/BYTES_PER_PIXEL)) {
6666
return nullptr;
67+
}
6768

6869
return std::calloc(width * height, BYTES_PER_PIXEL);
6970
}
7071

71-
static unsigned char *bitmap_get_buffer(void *bitmap) {
72-
assert(bitmap);
73-
return static_cast<unsigned char *>(bitmap);
74-
}
75-
76-
static size_t bitmap_get_bpp([[maybe_unused]] void *bitmap) {
77-
return BYTES_PER_PIXEL;
78-
}
79-
80-
static void bitmap_destroy(void *bitmap) {
81-
assert(bitmap);
82-
std::free(bitmap);
83-
}
84-
}
85-
86-
namespace GIF {
87-
static void *bitmap_create(int width, int height) {
72+
static void *Create(int width, int height) {
8873
/* ensure a stupidly large bitmap is not created */
89-
if ((static_cast<long long>(width) * static_cast<long long>(height)) > (MAX_IMAGE_BYTES/BYTES_PER_PIXEL))
74+
if ((static_cast<long long>(width) * static_cast<long long>(height)) > (MAX_IMAGE_BYTES/BYTES_PER_PIXEL)) {
9075
return nullptr;
76+
}
9177

9278
return std::calloc(width * height, BYTES_PER_PIXEL);
9379
}
9480

95-
static void bitmap_set_opaque([[maybe_unused]] void *bitmap, [[maybe_unused]] bool opaque) {
81+
static void SetOpaque([[maybe_unused]] void *bitmap, [[maybe_unused]] bool opaque) {
9682
assert(bitmap);
9783
}
9884

99-
static bool bitmap_test_opaque([[maybe_unused]] void *bitmap) {
85+
static bool TestOpaque([[maybe_unused]] void *bitmap) {
10086
assert(bitmap);
10187
return false;
10288
}
10389

104-
static unsigned char *bitmap_get_buffer(void *bitmap) {
90+
static unsigned char *GetBuffer(void *bitmap) {
10591
assert(bitmap);
10692
return static_cast<unsigned char *>(bitmap);
10793
}
10894

109-
static void bitmap_destroy(void *bitmap) {
95+
static void Destroy(void *bitmap) {
11096
assert(bitmap);
11197
std::free(bitmap);
11298
}
99+
100+
static size_t GetBPP([[maybe_unused]] void *bitmap) {
101+
return BYTES_PER_PIXEL;
102+
}
113103

114-
static void bitmap_modified([[maybe_unused]] void *bitmap) {
104+
static void Modified([[maybe_unused]] void *bitmap) {
115105
assert(bitmap);
116106
return;
117107
}
@@ -120,10 +110,10 @@ namespace GIF {
120110
namespace Textures {
121111
static g2dTexture *LoadImageBufferBMP(unsigned char *data, int size) {
122112
bmp_bitmap_callback_vt bitmap_callbacks = {
123-
BMP::bitmap_create,
124-
BMP::bitmap_destroy,
125-
BMP::bitmap_get_buffer,
126-
BMP::bitmap_get_bpp
113+
Image::Create,
114+
Image::Destroy,
115+
Image::GetBuffer,
116+
Image::GetBPP
127117
};
128118

129119
bmp_result code = BMP_OK;
@@ -160,12 +150,12 @@ namespace Textures {
160150

161151
static g2dTexture *LoadImageBufferGIF(unsigned char *data, int size) {
162152
gif_bitmap_callback_vt bitmap_callbacks = {
163-
GIF::bitmap_create,
164-
GIF::bitmap_destroy,
165-
GIF::bitmap_get_buffer,
166-
GIF::bitmap_set_opaque,
167-
GIF::bitmap_test_opaque,
168-
GIF::bitmap_modified
153+
Image::Create,
154+
Image::Destroy,
155+
Image::GetBuffer,
156+
Image::SetOpaque,
157+
Image::TestOpaque,
158+
Image::Modified
169159
};
170160

171161
gif_animation gif;
@@ -195,87 +185,114 @@ namespace Textures {
195185
g2dTexture *LoadImageBufferJPEG(unsigned char *data, int size) {
196186
struct jpeg_decompress_struct info;
197187
struct jpeg_error_mgr err;
198-
188+
199189
info.err = jpeg_std_error(&err);
200190
jpeg_create_decompress(&info);
201191
jpeg_mem_src(&info, data, size);
202-
jpeg_read_header(&info, TRUE);
203-
192+
193+
if (jpeg_read_header(&info, TRUE) != JPEG_HEADER_OK) {
194+
Log::Error("%s(jpeg_read_header) failed\n", __func__);
195+
jpeg_destroy_decompress(&info);
196+
return nullptr;
197+
}
198+
204199
info.out_color_space = JCS_EXT_RGBA;
205200
jpeg_start_decompress(&info);
206-
207-
u8 *buffer = new u8[info.output_width * info.output_height * 4];
208-
int stride = info.output_width * 4;
209201

202+
if (info.output_width > 512 || info.output_height > 512) {
203+
Log::Error("%s g2d does not support images greater than 512x512\n", __func__);
204+
jpeg_destroy_decompress(&info);
205+
return nullptr;
206+
}
207+
208+
int stride = info.output_width * 4;
209+
u8 *buffer = static_cast<u8 *>(std::malloc(stride * info.output_height));
210+
if (!buffer) {
211+
Log::Error("%s failed to allocate buffer\n", __func__);
212+
jpeg_destroy_decompress(&info);
213+
return nullptr;
214+
}
215+
210216
while (info.output_scanline < info.output_height) {
211-
u8 *ptr = &buffer[stride * info.output_scanline];
217+
u8 *ptr = buffer + stride * info.output_scanline;
212218
jpeg_read_scanlines(&info, &ptr, 1);
213219
}
214-
215-
jpeg_finish_decompress(&info);
220+
216221
g2dTexture *tex = g2dTexLoad(buffer, info.output_width, info.output_height, G2D_SWIZZLE);
222+
223+
jpeg_finish_decompress(&info);
217224
jpeg_destroy_decompress(&info);
218-
delete[] buffer;
225+
std::free(buffer);
226+
219227
return tex;
220-
}
228+
}
221229

222230
g2dTexture *LoadImageBufferPNG(unsigned char *data, int size) {
223231
g2dTexture *tex = nullptr;
224232
png_image image;
225-
std::memset(&image, 0, (sizeof image));
233+
std::memset(&image, 0, sizeof(png_image));
226234
image.version = PNG_IMAGE_VERSION;
227-
228-
if (png_image_begin_read_from_memory(&image, data, size) != 0) {
229-
png_bytep buffer;
230-
image.format = PNG_FORMAT_RGBA;
231-
buffer = new png_byte[PNG_IMAGE_SIZE(image)];
232-
233-
if (buffer != nullptr && png_image_finish_read(&image, nullptr, buffer, 0, nullptr) != 0) {
234-
tex = g2dTexLoad(buffer, image.width, image.height, G2D_SWIZZLE);
235-
delete[] buffer;
236-
png_image_free(&image);
237-
}
238-
else {
239-
if (buffer == nullptr) {
240-
Log::Error("png_byte buffer: returned nullptr\n");
241-
png_image_free(&image);
242-
}
243-
else {
244-
Log::Error("png_image_finish_read failed: %s\n", image.message);
245-
delete[] buffer;
246-
}
247-
}
235+
236+
if (!png_image_begin_read_from_memory(&image, data, size)) {
237+
Log::Error("%s(png_image_begin_read_from_memory) failed: %s\n", __func__, image.message);
238+
return nullptr;
248239
}
249-
else
250-
Log::Error("png_image_begin_read_from_memory failed: %s\n", image.message);
251-
240+
241+
image.format = PNG_FORMAT_RGBA;
242+
243+
if (image.width > 512 || image.height > 512) {
244+
Log::Error("%s g2d does not support images greater than 512x512\n", __func__);
245+
png_image_free(&image);
246+
return nullptr;
247+
}
248+
249+
const png_alloc_size_t imageSize = PNG_IMAGE_SIZE(image);
250+
png_bytep buffer = static_cast<png_bytep>(std::malloc(imageSize));
251+
if (!buffer) {
252+
Log::Error("%s failed to allocate buffer\n", __func__);
253+
png_image_free(&image);
254+
return nullptr;
255+
}
256+
257+
if (png_image_finish_read(&image, nullptr, buffer, 0, nullptr)) {
258+
tex = g2dTexLoad(buffer, image.width, image.height, G2D_SWIZZLE);
259+
}
260+
else {
261+
Log::Error("%s(png_image_finish_read) failed: %s\n", __func__, image.message);
262+
}
263+
264+
std::free(buffer);
265+
png_image_free(&image);
252266
return tex;
253-
}
267+
}
254268

255-
g2dTexture *LoadImage(const std::string &path) {
269+
g2dTexture *LoadImage(const std::string &path, int size) {
256270
int ret = 0;
257-
u64 size = FS::GetFileSize(path);
258-
unsigned char *data = new unsigned char[size];
271+
unsigned char *data = static_cast<unsigned char *>(std::malloc(size));
259272

260273
if (R_FAILED(ret = FS::ReadFile(path, data, size))) {
261-
Log::Error("LoadImage FS::ReadFile failed 0x%08x\n", ret);
262-
delete[] data;
274+
Log::Error("%s(FS::ReadFile) failed: 0x%08x\n", __func__, ret);
275+
std::free(data);
263276
return nullptr;
264277
}
265278

266279
g2dTexture *tex = nullptr;
267280
std::string ext = FS::GetFileExt(path);
268281

269-
if (ext == ".BMP")
282+
if (ext == ".BMP") {
270283
tex = Textures::LoadImageBufferBMP(data, size);
271-
else if (ext == ".GIF")
284+
}
285+
else if (ext == ".GIF") {
272286
tex = Textures::LoadImageBufferGIF(data, size);
273-
else if ((ext == ".JPEG") || (ext == ".JPG"))
287+
}
288+
else if ((ext == ".JPEG") || (ext == ".JPG")) {
274289
tex = Textures::LoadImageBufferJPEG(data, size);
275-
else if (ext == ".PNG")
290+
}
291+
else if (ext == ".PNG") {
276292
tex = Textures::LoadImageBufferPNG(data, size);
293+
}
277294

278-
delete[] data;
295+
std::free(data);
279296
return tex;
280297
}
281298

@@ -391,8 +408,9 @@ namespace Textures {
391408
g2dTexFree(&icon_dir[i]);
392409
}
393410

394-
for (int i = 0; i < NUM_FILE_ICONS; i++)
411+
for (int i = 0; i < NUM_FILE_ICONS; i++) {
395412
g2dTexFree(&file_icons[i]);
413+
}
396414

397415
for (int i = 0; i < NUM_BATT_ICONS; i++) {
398416
g2dTexFree(&battery_charging[i]);

0 commit comments

Comments
 (0)