mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-27 07:20:49 +00:00
Texture replacer: Faster way to get width/height from a png
This commit is contained in:
parent
81817faf1d
commit
76c6058abe
@ -59,3 +59,14 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in
|
||||
png_image_finish_read(&png, NULL, *image_data_ptr, stride, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool PNGHeaderPeek::IsValidPNGHeader() const {
|
||||
if (magic != 0x474e5089 || ihdrTag != 0x52444849) {
|
||||
return false;
|
||||
}
|
||||
// Reject crazy sized images, too.
|
||||
if (Width() > 32768 && Height() > 32768) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
#ifndef _PNG_LOAD_H
|
||||
#define _PNG_LOAD_H
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "Common/BitSet.h"
|
||||
|
||||
// *image_data_ptr should be deleted with free()
|
||||
// return value of 1 == success.
|
||||
@ -9,4 +12,20 @@ int pngLoad(const char *file, int *pwidth,
|
||||
int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth,
|
||||
int *pheight, unsigned char **image_data_ptr);
|
||||
|
||||
#endif // _PNG_LOAD_H
|
||||
// PNG peeker - just read the start of a PNG straight into this struct, in order to
|
||||
// look at basic parameters like width and height. Note that while PNG is a chunk-based
|
||||
// format, the IHDR chunk is REQUIRED to be the first one, so this will work.
|
||||
struct PNGHeaderPeek {
|
||||
uint32_t magic;
|
||||
uint32_t ignore0;
|
||||
uint32_t ignore1;
|
||||
uint32_t ihdrTag;
|
||||
uint32_t be_width; // big endian
|
||||
uint32_t be_height;
|
||||
uint8_t bitDepth; // bits per channel, can be 1, 2, 4, 8, 16
|
||||
uint8_t colorType; // really, pixel format. 0 = grayscale, 2 = rgb, 3 = palette index, 4 = gray+alpha, 6 = rgba
|
||||
|
||||
bool IsValidPNGHeader() const;
|
||||
int Width() const { return swap32(be_width); }
|
||||
int Height() const { return swap32(be_height); }
|
||||
};
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "Common/Data/Convert/ColorConv.h"
|
||||
#include "Common/Data/Format/IniFile.h"
|
||||
#include "Common/Data/Format/ZIMLoad.h"
|
||||
#include "Common/Data/Format/PNGLoad.h"
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/Data/Text/Parsers.h"
|
||||
#include "Common/File/FileUtil.h"
|
||||
@ -645,27 +646,15 @@ bool TextureReplacer::PopulateLevelFromZip(ReplacedTextureLevel &level, bool ign
|
||||
good = (flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888;
|
||||
}
|
||||
} else if (imageType == ReplacedImageType::PNG) {
|
||||
png_image png = {};
|
||||
png.version = PNG_IMAGE_VERSION;
|
||||
|
||||
// TODO: Use some way to stream data into libpng. Better than the IO lookups on Android...
|
||||
zip_uint64_t zsize = ZipFileSize(level.zinfo->z, level.zi);
|
||||
std::string pngdata;
|
||||
if (zsize != INVALID_ZIP_SIZE)
|
||||
pngdata.resize(zsize);
|
||||
if (!pngdata.empty()) {
|
||||
pngdata.resize(zip_fread(zf, &pngdata[0], pngdata.size()));
|
||||
}
|
||||
|
||||
if (png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) {
|
||||
// We pad files that have been hashrange'd so they are the same texture size.
|
||||
level.w = png.width;
|
||||
level.h = png.height;
|
||||
PNGHeaderPeek headerPeek;
|
||||
good = zip_fread(zf, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek);
|
||||
if (headerPeek.IsValidPNGHeader()) {
|
||||
level.w = headerPeek.Width();
|
||||
level.h = headerPeek.Height();
|
||||
good = true;
|
||||
} else {
|
||||
ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", level.file.ToVisualString().c_str(), png.message);
|
||||
ERROR_LOG(G3D, "Could not get PNG dimensions: %s (zip)", level.file.ToVisualString().c_str());
|
||||
}
|
||||
png_image_free(&png);
|
||||
} else {
|
||||
ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format (zip)", level.file.ToVisualString().c_str());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user