artworx.c (2312B)
1 /* 2 * artworx.c 3 * libansilove 1.3.1 4 * https://www.ansilove.org 5 * 6 * Copyright (c) 2011-2022 Stefan Vogt, Brian Cassidy, and Frederic Cambus 7 * All rights reserved. 8 * 9 * libansilove is licensed under the BSD 2-Clause license. 10 * See LICENSE file for details. 11 * 12 * SPDX-License-Identifier: BSD-2-Clause 13 */ 14 15 #include <gd.h> 16 #include <stddef.h> 17 #include <stdint.h> 18 #include "ansilove.h" 19 #include "config.h" 20 #include "drawchar.h" 21 #include "output.h" 22 23 #define ADF_HEADER_LENGTH 4289 /* 192 + 4096 + 1 */ 24 25 #define STATE_CHARACTER 0 26 #define STATE_ATTRIBUTE 1 27 28 int 29 ansilove_artworx(struct ansilove_ctx *ctx, struct ansilove_options *options) 30 { 31 uint8_t character, attribute, *cursor, state = STATE_CHARACTER; 32 uint32_t column = 0, row = 0; 33 uint32_t foreground, background; 34 uint32_t width, height; 35 size_t index, loop; 36 37 /* libgd image pointers */ 38 gdImagePtr canvas; 39 40 if (ctx == NULL || options == NULL) { 41 if (ctx) 42 ctx->error = ANSILOVE_INVALID_PARAM; 43 44 return -1; 45 } 46 47 if (ctx->length < ADF_HEADER_LENGTH) { 48 ctx->error = ANSILOVE_FORMAT_ERROR; 49 return -1; 50 } 51 52 /* create ADF instance */ 53 width = 640; 54 height = (ctx->length - ADF_HEADER_LENGTH) / 2 / 80 * 16; 55 56 if (!width || !height) { 57 ctx->error = ANSILOVE_FORMAT_ERROR; 58 return -1; 59 } 60 61 canvas = gdImageCreate(width, height); 62 63 if (!canvas) { 64 ctx->error = ANSILOVE_GD_ERROR; 65 return -1; 66 } 67 68 69 /* process ADF palette */ 70 for (loop = 0; loop < 16; loop++) { 71 index = (adf_colors[loop] * 3) + 1; 72 gdImageColorAllocate(canvas, 73 ctx->buffer[index] << 2 | ctx->buffer[index] >> 4, 74 ctx->buffer[index + 1] << 2 | ctx->buffer[index + 1] >> 4, 75 ctx->buffer[index + 2] << 2 | ctx->buffer[index + 2] >> 4); 76 } 77 78 /* process ADF */ 79 loop = ADF_HEADER_LENGTH; 80 81 while (loop < ctx->length) { 82 cursor = &ctx->buffer[loop]; 83 84 if (column == 80) { 85 column = 0; 86 row++; 87 } 88 89 switch (state) { 90 case STATE_CHARACTER: 91 character = *cursor; 92 state = STATE_ATTRIBUTE; 93 break; 94 case STATE_ATTRIBUTE: 95 attribute = *cursor; 96 97 background = (attribute & 240) >> 4; 98 foreground = attribute & 15; 99 100 drawchar(canvas, ctx->buffer+193, 8, 16, column, row, 101 background, foreground, character); 102 103 column++; 104 105 state = STATE_CHARACTER; 106 break; 107 } 108 109 loop++; 110 } 111 112 /* create output file */ 113 return output(ctx, options, canvas); 114 }