ohmu
·
2026-10-15
1/*
2 * Copyright (c) 2014-2019 Hayaki Saito
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy of
5 * this software and associated documentation files (the "Software"), to deal in
6 * the Software without restriction, including without limitation the rights to
7 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8 * the Software, and to permit persons to whom the Software is furnished to do so,
9 * subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22#include "config.h"
23
24/* STDC_HEADERS */
25# include <stdio.h>
26# include <stdlib.h>
27
28#if HAVE_ASSERT_H
29# include <assert.h>
30#endif /* HAVE_ASSERT_H */
31
32#include <sixel.h>
33#include "output.h"
34
35
36/* create new output context object */
37SIXELAPI SIXELSTATUS
38sixel_output_new(
39 sixel_output_t /* out */ **output,
40 sixel_write_function /* in */ fn_write,
41 void /* in */ *priv,
42 sixel_allocator_t /* in */ *allocator)
43{
44 SIXELSTATUS status = SIXEL_FALSE;
45 size_t size;
46
47 if (allocator == NULL) {
48 status = sixel_allocator_new(&allocator, NULL, NULL, NULL, NULL);
49 if (SIXEL_FAILED(status)) {
50 goto end;
51 }
52 } else {
53 sixel_allocator_ref(allocator);
54 }
55 size = sizeof(sixel_output_t) + SIXEL_OUTPUT_PACKET_SIZE * 2;
56
57 *output = (sixel_output_t *)sixel_allocator_malloc(allocator, size);
58 if (*output == NULL) {
59 sixel_helper_set_additional_message(
60 "sixel_output_new: sixel_allocator_malloc() failed.");
61 status = SIXEL_BAD_ALLOCATION;
62 sixel_allocator_unref(allocator);
63 goto end;
64 }
65
66 (*output)->ref = 1;
67 (*output)->has_8bit_control = 0;
68 (*output)->has_sdm_glitch = 0;
69 (*output)->has_gri_arg_limit = 1;
70 (*output)->skip_dcs_envelope = 0;
71 (*output)->palette_type = SIXEL_PALETTETYPE_AUTO;
72 (*output)->fn_write = fn_write;
73 (*output)->save_pixel = 0;
74 (*output)->save_count = 0;
75 (*output)->active_palette = (-1);
76 (*output)->node_top = NULL;
77 (*output)->node_free = NULL;
78 (*output)->priv = priv;
79 (*output)->pos = 0;
80 (*output)->penetrate_multiplexer = 0;
81 (*output)->encode_policy = SIXEL_ENCODEPOLICY_AUTO;
82 (*output)->allocator = allocator;
83
84 status = SIXEL_OK;
85
86end:
87 return status;
88}
89
90
91/* deprecated: create an output object */
92SIXELAPI sixel_output_t *
93sixel_output_create(sixel_write_function fn_write, void *priv)
94{
95 SIXELSTATUS status = SIXEL_FALSE;
96 sixel_output_t *output = NULL;
97
98 status = sixel_output_new(&output, fn_write, priv, NULL);
99 if (SIXEL_FAILED(status)) {
100 goto end;
101 }
102
103end:
104 return output;
105}
106
107
108/* destroy output context object */
109SIXELAPI void
110sixel_output_destroy(sixel_output_t *output)
111{
112 sixel_allocator_t *allocator;
113
114 if (output) {
115 allocator = output->allocator;
116 sixel_allocator_free(allocator, output);
117 sixel_allocator_unref(allocator);
118 }
119}
120
121
122/* increase reference count of output context object (thread-unsafe) */
123SIXELAPI void
124sixel_output_ref(sixel_output_t *output)
125{
126 /* TODO: be thread-safe */
127 ++output->ref;
128}
129
130
131/* decrease reference count of output context object (thread-unsafe) */
132SIXELAPI void
133sixel_output_unref(sixel_output_t *output)
134{
135 /* TODO: be thread-safe */
136 if (output) {
137 assert(output->ref > 0);
138 output->ref--;
139 if (output->ref == 0) {
140 sixel_output_destroy(output);
141 }
142 }
143}
144
145
146/* get 8bit output mode which indicates whether it uses C1 control characters */
147SIXELAPI int
148sixel_output_get_8bit_availability(sixel_output_t *output)
149{
150 return output->has_8bit_control;
151}
152
153
154/* set 8bit output mode state */
155SIXELAPI void
156sixel_output_set_8bit_availability(sixel_output_t *output, int availability)
157{
158 output->has_8bit_control = availability;
159}
160
161
162/* set whether limit arguments of DECGRI('!') to 255 */
163SIXELAPI void
164sixel_output_set_gri_arg_limit(
165 sixel_output_t /* in */ *output, /* output context */
166 int /* in */ value) /* 0: don't limit arguments of DECGRI
167 1: limit arguments of DECGRI to 255 */
168{
169 output->has_gri_arg_limit = value;
170}
171
172
173/* set GNU Screen penetration feature enable or disable */
174SIXELAPI void
175sixel_output_set_penetrate_multiplexer(sixel_output_t *output, int penetrate)
176{
177 output->penetrate_multiplexer = penetrate;
178}
179
180
181/* set whether we skip DCS envelope */
182SIXELAPI void
183sixel_output_set_skip_dcs_envelope(sixel_output_t *output, int skip)
184{
185 output->skip_dcs_envelope = skip;
186}
187
188
189/* set palette type: RGB or HLS */
190SIXELAPI void
191sixel_output_set_palette_type(sixel_output_t *output, int palettetype)
192{
193 output->palette_type = palettetype;
194}
195
196
197/* set encodeing policy: auto, fast or size */
198SIXELAPI void
199sixel_output_set_encode_policy(sixel_output_t *output, int encode_policy)
200{
201 output->encode_policy = encode_policy;
202}
203
204/* emacs Local Variables: */
205/* emacs mode: c */
206/* emacs tab-width: 4 */
207/* emacs indent-tabs-mode: nil */
208/* emacs c-basic-offset: 4 */
209/* emacs End: */
210/* vim: set expandtab ts=4 sts=4 sw=4 : */
211/* EOF */