/* * upkg: a tool for manipulating Unreal Tournament packages. * Very simple PCX writer for saving extracted textures. * * Copyright © 2012 Nick Bowler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "pcx.h" int pcx_init_header(struct pcx_head *head) { unsigned short stride; if (head->width == 0 || head->width > 0xffff) return -1; if (head->height == 0 || head->height > 0xffff) return -1; stride = head->width + (head->width & 1); if (stride == 0 || stride > 0xffff) return -1; memset(head->encoded, 0, sizeof head->encoded); head->encoded[0] = 10; /* PCX Magic */ head->encoded[1] = 5; /* Version 3. */ head->encoded[2] = 1; /* Run-length encoding. */ head->encoded[3] = 8; /* Bits per pixel. */ pack_16_le(head->encoded+8, head->width-1); pack_16_le(head->encoded+10, head->height-1); head->encoded[65] = 1; /* One plane (indexed colour). */ pack_16_le(head->encoded+66, stride); head->encoded[68] = 1; /* Colour palette. */ return 0; } int pcx_write_scanline(const struct pcx_head *head, const unsigned char *src, FILE *f) { size_t len = head->width, offset = 0; unsigned char buf[head->width*2ul]; for (size_t i = 0; i < len;) { unsigned run = 0; while (i+run < len && src[i] == src[i+run] && run <= 0x3f) run++; if (run > 1 || src[i] > 0xbf) buf[offset++] = 0xc0 | run; buf[offset++] = src[i]; i += run; } if (fwrite(buf, offset, 1, f) != 1) return -1; return 0; } int pcx_write_palette(EnginePalette *palette, FILE *f) { unsigned char buf[769] = {12}; for (unsigned i = 0; i < palette->entries; i++) { buf[3*i+1] = palette->rgba[i][0]; buf[3*i+2] = palette->rgba[i][1]; buf[3*i+3] = palette->rgba[i][2]; } if (fwrite(buf, sizeof buf, 1, f) != 1) return -1; return 0; }