/*
* 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;
}