binary.c (2775B)
1 /* 2 * binary.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 <string.h> 19 #include "ansilove.h" 20 #include "config.h" 21 #include "drawchar.h" 22 #include "fonts.h" 23 #include "output.h" 24 25 #define STATE_CHARACTER 0 26 #define STATE_ATTRIBUTE 1 27 28 int 29 ansilove_binary(struct ansilove_ctx *ctx, struct ansilove_options *options) 30 { 31 uint8_t character, attribute, *cursor, state = STATE_CHARACTER; 32 int32_t column = 0, row = 0; 33 uint32_t background, foreground; 34 uint32_t width, height; 35 uint32_t colors[16]; 36 size_t loop = 0; 37 struct fontStruct fontData; 38 39 /* libgd image pointers */ 40 gdImagePtr canvas; 41 42 if (ctx == NULL || options == NULL) { 43 if (ctx) 44 ctx->error = ANSILOVE_INVALID_PARAM; 45 46 return -1; 47 } 48 49 if (!ctx->length) { 50 ctx->error = ANSILOVE_FORMAT_ERROR; 51 return -1; 52 } 53 54 if (options->bits != 8 && options->bits !=9) { 55 ctx->error = ANSILOVE_RANGE_ERROR; 56 return -1; 57 } 58 59 /* font selection */ 60 memset(&fontData, 0, sizeof(struct fontStruct)); 61 select_font(&fontData, options->font); 62 63 /* Default to 160 columns if columns option wasn't set */ 64 options->columns = options->columns ? options->columns : 160; 65 66 if (options->columns < 1 || options->columns > 4096) { 67 ctx->error = ANSILOVE_RANGE_ERROR; 68 return -1; 69 } 70 71 width = options->columns * options->bits; 72 height = ctx->length / 2 / options->columns * fontData.height; 73 74 if (!width || !height) { 75 ctx->error = ANSILOVE_FORMAT_ERROR; 76 return -1; 77 } 78 79 /* allocate buffer image memory */ 80 canvas = gdImageCreate(width, height); 81 82 if (!canvas) { 83 ctx->error = ANSILOVE_GD_ERROR; 84 return -1; 85 } 86 87 /* allocate color palette */ 88 for (size_t i = 0; i < 16; i++) 89 colors[i] = gdImageColorAllocate(canvas, vga_palette_red[i], 90 vga_palette_green[i], vga_palette_blue[i]); 91 92 /* process binary */ 93 while (loop < ctx->length) { 94 cursor = &ctx->buffer[loop]; 95 96 if (column == options->columns) { 97 column = 0; 98 row++; 99 } 100 101 switch (state) { 102 case STATE_CHARACTER: 103 character = *cursor; 104 state = STATE_ATTRIBUTE; 105 break; 106 case STATE_ATTRIBUTE: 107 attribute = *cursor; 108 109 background = (attribute & 240) >> 4; 110 foreground = attribute & 15; 111 112 if (background > 8 && !options->icecolors) 113 background -= 8; 114 115 drawchar(canvas, fontData.font_data, options->bits, 116 fontData.height, column, row, colors[background], 117 colors[foreground], character); 118 119 column++; 120 121 state = STATE_CHARACTER; 122 break; 123 } 124 125 loop++; 126 } 127 128 /* create output image */ 129 return output(ctx, options, canvas); 130 }