| 105 | TextureSourceJPEG::~TextureSourceJPEG() = default; |
| 106 | |
| 107 | bool TextureSourceJPEG::InitFromMemory(const uint8_t* data, size_t size, const char* nameForErrors) |
| 108 | { |
| 109 | int w = 0, h = 0, channels = 0; |
| 110 | stbi_uc* pixels = stbi_load_from_memory(data, static_cast<int>(size), &w, &h, &channels, 4 /*force RGBA*/); |
| 111 | if (!pixels) |
| 112 | { |
| 113 | LOG_DEBUG(Graphics, "stbi_load_from_memory failed for {}: {}", nameForErrors ? nameForErrors : "?", |
| 114 | stbi_failure_reason()); |
| 115 | return false; |
| 116 | } |
| 117 | |
| 118 | if (!IsPow2(w) || !IsPow2(h)) |
| 119 | { |
| 120 | Poseidon::Foundation::WarningMessage("Image %s: dimensions %dx%d not 2^n", nameForErrors ? nameForErrors : "?", |
| 121 | w, h); |
| 122 | stbi_image_free(pixels); |
| 123 | return false; |
| 124 | } |
| 125 | |
| 126 | _w = w; |
| 127 | _h = h; |
| 128 | _rgba0.assign(pixels, pixels + static_cast<size_t>(w) * static_cast<size_t>(h) * 4); |
| 129 | stbi_image_free(pixels); |
| 130 | |
| 131 | int maxDim = std::max(_w, _h); |
| 132 | _mipmaps = Log2i(maxDim) + 1; |
| 133 | // Keep a small floor — mip dimensions below 4 pixels carry no detail and the |
| 134 | // old IJL path also skipped them. |
| 135 | while (_mipmaps > 1 && ((_w >> (_mipmaps - 1)) < 4 || (_h >> (_mipmaps - 1)) < 4)) |
| 136 | --_mipmaps; |
| 137 | |
| 138 | _avgColor = ComputeAverage(_rgba0.data(), _w, _h); |
| 139 | return true; |
| 140 | } |
| 141 | |
| 142 | bool TextureSourceJPEG::Init(const char* name, PacLevelMem* mips, int maxMips) |
| 143 | { |
no test coverage detected