37 #if JPEG_LIB_VERSION < 80
42 static char const*
const IMAGE_TYPES[] = {
"png",
"jpg",
nullptr };
44 #define TGA_UNMAP_COMP 10
60 png_bytep* row_pointers;
62 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
nullptr,
nullptr,
nullptr);
67 info_ptr = png_create_info_struct(png_ptr);
69 png_destroy_write_struct(&png_ptr, (png_infopp)
nullptr);
73 png_init_io(png_ptr, f->
f);
75 png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
76 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
78 png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
79 png_set_compression_mem_level(png_ptr, 9);
81 png_write_info(png_ptr, info_ptr);
83 row_pointers = (png_bytep*)malloc(height *
sizeof(png_bytep));
84 for (
int i = 0;
i < height;
i++)
85 row_pointers[
i] = buffer + (height - 1 -
i) * 3 * width;
87 png_write_image(png_ptr, row_pointers);
88 png_write_end(png_ptr, info_ptr);
90 png_destroy_write_struct(&png_ptr, &info_ptr);
95 #define TGA_CHANNELS 3
107 size_t block_length = 0;
120 header[12] = width & 255;
121 header[13] = (width >> 8) & 255;
123 header[14] = height & 255;
124 header[15] = (height >> 8) & 255;
129 FS_Write(header,
sizeof(header), f);
131 for (
int y = height - 1; y >= 0; y--) {
132 for (
size_t x = 0; x < width; x++) {
134 pixel_data[0] = buffer[index + 2];
135 pixel_data[1] = buffer[index + 1];
136 pixel_data[2] = buffer[
index];
138 if (block_length == 0) {
139 memcpy(block_data, pixel_data, TGA_CHANNELS);
145 if (memcmp(&block_data[(block_length - 1) * TGA_CHANNELS], pixel_data, TGA_CHANNELS) != 0) {
147 memcpy(&block_data[block_length * TGA_CHANNELS], pixel_data, TGA_CHANNELS);
152 if (block_length > 1) {
154 rle_packet = block_length - 2;
156 FS_Write(block_data, (block_length - 1) * TGA_CHANNELS, f);
159 memcpy(block_data, pixel_data, TGA_CHANNELS);
165 if (memcmp(block_data, pixel_data, TGA_CHANNELS) == 0) {
169 if (block_length > 1) {
171 rle_packet = block_length + 127;
173 FS_Write(block_data, TGA_CHANNELS, f);
176 memcpy(&block_data[block_length * TGA_CHANNELS], pixel_data, TGA_CHANNELS);
183 if (block_length == 128) {
184 rle_packet = block_length - 1;
187 FS_Write(block_data, 128 * TGA_CHANNELS, f);
191 FS_Write(block_data, TGA_CHANNELS, f);
202 rle_packet = block_length - 1;
214 strncpy(&footer[8] ,
"TRUEVISION-XFILE", 16);
217 FS_Write(footer,
sizeof(footer), f);
227 struct jpeg_compress_struct cinfo;
228 struct jpeg_error_mgr jerr;
232 cinfo.err = jpeg_std_error(&jerr);
233 jpeg_create_compress(&cinfo);
234 jpeg_stdio_dest(&cinfo, f->
f);
237 cinfo.image_width = width;
238 cinfo.image_height = height;
239 cinfo.in_color_space = JCS_RGB;
240 cinfo.input_components = 3;
241 cinfo.progressive_mode = TRUE;
243 jpeg_set_defaults(&cinfo);
244 jpeg_set_quality(&cinfo, quality, TRUE);
245 jpeg_start_compress(&cinfo, TRUE);
246 jpeg_write_marker(&cinfo, JPEG_COM, (
const byte*)
"UFOAI", (uint32_t) 5);
249 w3 = cinfo.image_width * 3;
250 offset = w3 * cinfo.image_height - w3;
251 while (cinfo.next_scanline < cinfo.image_height) {
252 s = &buffer[offset - (cinfo.next_scanline * w3)];
253 jpeg_write_scanlines(&cinfo, &s, 1);
257 jpeg_finish_compress(&cinfo);
258 jpeg_destroy_compress(&cinfo);
264 snprintf(path,
sizeof(path),
"%s.%s", name, suffix);
272 return SDL_CreateRGBSurface(0, width, height, 32,
273 #
if SDL_BYTEORDER == SDL_BIG_ENDIAN
274 0xFF000000U, 0x00FF0000U, 0x0000FF00U, 0x000000FFU
276 0x000000FFU, 0x0000FF00U, 0x00FF0000U, 0xFF000000U
287 static void readMem(png_struct*
const png, png_byte*
const dst, png_size_t
const size)
290 if (state.
end - state.
ptr < size) {
291 png_error(png,
"premature end of input");
293 memcpy(dst, state.
ptr, size);
300 SDL_Surface* res = 0;
303 if (png_struct* png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0)) {
304 png_info* info = png_create_info_struct(png);
307 png_set_read_fn(png, &state, &
readMem);
309 png_read_info(png, info);
315 png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, 0, 0, 0);
318 png_set_gray_to_rgb(png);
319 png_set_strip_16(png);
320 png_set_packing(png);
322 png_set_add_alpha(png, 255, PNG_FILLER_AFTER);
325 png_start_read_image(png);
327 png_byte* dst =
static_cast<png_byte*
>(s->pixels);
328 size_t const pitch = s->pitch;
329 for (
size_t n = height; n != 0; dst += pitch, --n) {
330 png_read_row(png, dst, 0);
333 png_read_end(png, info);
338 png_destroy_read_struct(&png, &info, 0);
347 #if JPEG_LIB_VERSION < 80
352 ERREXIT(cinfo, JERR_INPUT_EOF);
361 jpeg_source_mgr& src = *cinfo->src;
362 if (src.bytes_in_buffer < (
size_t)num_bytes)
363 ERREXIT(cinfo, JERR_INPUT_EOF);
365 src.next_input_byte += num_bytes;
366 src.bytes_in_buffer -= num_bytes;
372 SDL_Surface* res = 0;
375 jpeg_decompress_struct cinfo;
378 cinfo.err = jpeg_std_error(&jerr);
379 jpeg_create_decompress(&cinfo);
381 #if JPEG_LIB_VERSION < 80
383 src.next_input_byte =
buf;
384 src.bytes_in_buffer =
len;
388 src.resync_to_restart = &jpeg_resync_to_restart;
392 jpeg_mem_src(&cinfo,
buf, len);
395 jpeg_read_header(&cinfo, TRUE);
397 cinfo.out_color_space = JCS_RGB;
399 if (SDL_Surface*
const s =
createSurface(cinfo.image_height, cinfo.image_width)) {
400 jpeg_start_decompress(&cinfo);
402 byte* dst =
static_cast<byte*
>(s->pixels);
403 size_t const pitch = s->pitch;
404 for (
size_t n = cinfo.image_height; n != 0; dst += pitch, --n) {
405 JSAMPLE* lines[1] = { dst };
406 jpeg_read_scanlines(&cinfo, lines, 1);
409 for (
size_t x = cinfo.image_width; x-- != 0;) {
410 dst[4 * x + 0] = dst[3 * x + 0];
411 dst[4 * x + 1] = dst[3 * x + 1];
412 dst[4 * x + 2] = dst[3 * x + 2];
413 dst[4 * x + 3] = 255;
417 jpeg_finish_decompress(&cinfo);
421 jpeg_destroy_decompress(&cinfo);
static char const *const IMAGE_TYPES[]
static boolean djpeg_fill_input_buffer(jpeg_decompress_struct *const cinfo)
static SDL_Surface * Img_LoadJPG(char const *const name)
Image loading and saving functions.
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
void R_WriteJPG(qFILE *f, byte *buffer, int width, int height, int quality)
char const *const * Img_GetImageTypes(void)
static void djpeg_skip_input_data(jpeg_decompress_struct *const cinfo, long const num_bytes)
static void readMem(png_struct *const png, png_byte *const dst, png_size_t const size)
SDL_Surface * Img_LoadImage(char const *name)
Loads the specified image from the game filesystem and populates the provided SDL_Surface.
static SDL_Surface * Img_LoadPNG(char const *const name)
QGL_EXTERN GLuint GLchar GLuint * len
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
static byte * readFile(char const *const name, char const *const suffix, size_t &len)
void R_WritePNG(qFILE *f, byte *buffer, int width, int height)
static SDL_Surface * createSurface(int const height, int const width)
static void djpeg_nop(jpeg_decompress_struct *)
void FS_FreeFile(void *buffer)
int FS_Write(const void *buffer, int len, qFILE *f)
Properly handles partial writes.
void R_WriteCompressedTGA(qFILE *f, const byte *buffer, int width, int height)