libcaca  0.99.beta19
About: libcaca is a graphics library that outputs text instead of pixels, so that it can work on older video cards or text terminals (something like an advanced AAlib library).
  Fossies Dox: libcaca-0.99.beta19.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

import.c
Go to the documentation of this file.
1 /*
2  * libcaca Colour ASCII-Art library
3  * Copyright (c) 2002-2014 Sam Hocevar <sam@hocevar.net>
4  * All Rights Reserved
5  *
6  * This library is free software. It comes without any warranty, to
7  * the extent permitted by applicable law. You can redistribute it
8  * and/or modify it under the terms of the Do What the Fuck You Want
9  * to Public License, Version 2, as published by Sam Hocevar. See
10  * http://www.wtfpl.net/ for more details.
11  */
12 
13 /*
14  * This file contains various import functions.
15  */
16 
17 #include "config.h"
18 
19 #if !defined __KERNEL__
20 # include <stdlib.h>
21 # include <string.h>
22 # include <stdio.h>
23 #endif
24 
25 #include "caca.h"
26 #include "caca_internals.h"
27 #include "codec.h"
28 
29 static inline uint32_t sscanu32(void const *s)
30 {
31  uint32_t x;
32  memcpy(&x, s, 4);
33  return hton32(x);
34 }
35 
36 static inline uint16_t sscanu16(void const *s)
37 {
38  uint16_t x;
39  memcpy(&x, s, 2);
40  return hton16(x);
41 }
42 
43 static ssize_t import_caca(caca_canvas_t *, void const *, size_t);
44 
73 ssize_t caca_import_canvas_from_memory(caca_canvas_t *cv, void const *data,
74  size_t len, char const *format)
75 {
76  if(!strcasecmp("caca", format))
77  return import_caca(cv, data, len);
78  if(!strcasecmp("utf8", format))
79  return _import_ansi(cv, data, len, 1);
80  if(!strcasecmp("text", format))
81  return _import_text(cv, data, len);
82  if(!strcasecmp("ansi", format))
83  return _import_ansi(cv, data, len, 0);
84  if(!strcasecmp("bin", format))
85  return _import_bin(cv, data, len);
86 
87  /* Autodetection */
88  if(!strcasecmp("", format))
89  {
90  unsigned char const *str = data;
91  unsigned int i, j, k;
92 
93  /* If 4 first bytes are 0xcaca + 'CV' */
94  if(len >= 4 && str[0] == 0xca &&
95  str[1] == 0xca && str[2] == 'C' && str[3] == 'V')
96  return import_caca(cv, data, len);
97 
98  /* If we find ESC[ argv, we guess it's an ANSI file */
99  for(i = 0; i + 1 < len; i++)
100  if((str[i] == '\033') && (str[i + 1] == '['))
101  return _import_ansi(cv, data, len, 0);
102 
103  /* If we find a lot of spaces at even locations,
104  * we guess it's a BIN file. */
105  for (i = j = k = 0; i < len; i += 2)
106  {
107  j += (str[i] == ' ');
108  k += (str[i + 1] == ' ');
109  }
110 
111  if (j > 10 && j > len / 40 && k < 10)
112  return _import_bin(cv, data, len);
113 
114  /* Otherwise, import it as text */
115  return _import_text(cv, data, len);
116  }
117 
118  seterrno(EINVAL);
119  return -1;
120 }
121 
152 ssize_t caca_import_canvas_from_file(caca_canvas_t *cv, char const *filename,
153  char const *format)
154 {
155 #if defined __KERNEL__
156  seterrno(ENOSYS);
157  return -1;
158 #else
159  caca_file_t *f;
160  char *data = NULL;
161  ssize_t ret, size = 0;
162 
163  f = caca_file_open(filename, "rb");
164  if(!f)
165  return -1; /* fopen already set errno */
166 
167  while(!caca_file_eof(f))
168  {
169  data = realloc(data, size + 1024);
170  if(!data)
171  {
172  caca_file_close(f);
173  seterrno(ENOMEM);
174  return -1;
175  }
176 
177  ret = (ssize_t)caca_file_read(f, data + size, 1024);
178  if(ret >= 0)
179  size += ret;
180  }
181  caca_file_close(f);
182 
183  ret = caca_import_canvas_from_memory(cv, data, size, format);
184  free(data);
185 
186  return ret;
187 #endif
188 }
189 
210  void const *data, size_t len,
211  char const *format)
212 {
213  caca_canvas_t *tmp;
214  ssize_t ret;
215 
216  tmp = caca_create_canvas(0, 0);
217  ret = caca_import_canvas_from_memory(tmp, data, len, format);
218 
219  if(ret > 0)
220  caca_blit(cv, x, y, tmp, NULL);
221 
222  caca_free_canvas(tmp);
223 
224  return ret;
225 }
226 
249  char const *filename, char const *format)
250 {
251  caca_canvas_t *tmp;
252  ssize_t ret;
253 
254  tmp = caca_create_canvas(0, 0);
255  ret = caca_import_canvas_from_file(tmp, filename, format);
256 
257  if(ret > 0)
258  caca_blit(cv, x, y, tmp, NULL);
259 
260  caca_free_canvas(tmp);
261 
262  return ret;
263 }
264 
276 char const * const * caca_get_import_list(void)
277 {
278  static char const * const list[] =
279  {
280  "", "autodetect",
281  "caca", "native libcaca format",
282  "text", "plain text",
283  "ansi", "ANSI coloured text",
284  "utf8", "UTF-8 files with ANSI colour codes",
285  "bin", "BIN binary ANSI art",
286  NULL, NULL
287  };
288 
289  return list;
290 }
291 
292 /*
293  * XXX: the following functions are local.
294  */
295 
296 static ssize_t import_caca(caca_canvas_t *cv, void const *data, size_t size)
297 {
298  uint8_t const *buf = (uint8_t const *)data;
299  size_t control_size, data_size, expected_size;
300  unsigned int frames, f, n, offset;
301  uint16_t version, flags;
302  int32_t xmin = 0, ymin = 0, xmax = 0, ymax = 0;
303 
304  if(size < 20)
305  return 0;
306 
307  if(buf[0] != 0xca || buf[1] != 0xca || buf[2] != 'C' || buf[3] != 'V')
308  {
309  debug("caca import error: expected \\xca\\xcaCV header");
310  goto invalid_caca;
311  }
312 
313  control_size = sscanu32(buf + 4);
314  data_size = sscanu32(buf + 8);
315  version = sscanu16(buf + 12);
316  frames = sscanu32(buf + 14);
317  flags = sscanu16(buf + 18);
318 
319  if(size < 4 + control_size + data_size)
320  return 0;
321 
322  if(control_size < 16 + frames * 32)
323  {
324  debug("caca import error: control size %u < expected %u",
325  (unsigned int)control_size, 16 + frames * 32);
326  goto invalid_caca;
327  }
328 
329  for(expected_size = 0, f = 0; f < frames; f++)
330  {
331  unsigned int width, height, duration;
332  uint32_t attr;
333  int x, y, handlex, handley;
334 
335  width = sscanu32(buf + 4 + 16 + f * 32);
336  height = sscanu32(buf + 4 + 16 + f * 32 + 4);
337  duration = sscanu32(buf + 4 + 16 + f * 32 + 8);
338  attr = sscanu32(buf + 4 + 16 + f * 32 + 12);
339  x = (int32_t)sscanu32(buf + 4 + 16 + f * 32 + 16);
340  y = (int32_t)sscanu32(buf + 4 + 16 + f * 32 + 20);
341  handlex = (int32_t)sscanu32(buf + 4 + 16 + f * 32 + 24);
342  handley = (int32_t)sscanu32(buf + 4 + 16 + f * 32 + 28);
343  expected_size += width * height * 8;
344  if(-handlex < xmin)
345  xmin = -handlex;
346  if(-handley < ymin)
347  ymin = -handley;
348  if((((int32_t) width) - handlex) > xmax)
349  xmax = ((int32_t) width) - handlex;
350  if((((int32_t) height) - handley) > ymax)
351  ymax = ((int32_t) height) - handley;
352  }
353 
354  if(expected_size != data_size)
355  {
356  debug("caca import error: data size %u < expected %u",
357  (unsigned int)data_size, (unsigned int)expected_size);
358  goto invalid_caca;
359  }
360 
361  caca_set_canvas_size(cv, 0, 0);
362  caca_set_canvas_size(cv, xmax - xmin, ymax - ymin);
363 
364  for (f = caca_get_frame_count(cv); f--; )
365  {
366  caca_free_frame(cv, f);
367  }
368 
369  for (offset = 0, f = 0; f < frames; f ++)
370  {
371  unsigned int width, height;
372 
373  width = sscanu32(buf + 4 + 16 + f * 32);
374  height = sscanu32(buf + 4 + 16 + f * 32 + 4);
375  caca_create_frame(cv, f);
376  caca_set_frame(cv, f);
377 
378  cv->curattr = sscanu32(buf + 4 + 16 + f * 32 + 12);
379  cv->frames[f].x = (int32_t)sscanu32(buf + 4 + 16 + f * 32 + 16);
380  cv->frames[f].y = (int32_t)sscanu32(buf + 4 + 16 + f * 32 + 20);
381  cv->frames[f].handlex = (int32_t)sscanu32(buf + 4 + 16 + f * 32 + 24);
382  cv->frames[f].handley = (int32_t)sscanu32(buf + 4 + 16 + f * 32 + 28);
383 
384  /* FIXME: check for return value */
385 
386  for(n = width * height; n--; )
387  {
388  int x = (n % width) - cv->frames[f].handlex - xmin;
389  int y = (n / width) - cv->frames[f].handley - ymin;
390 
391  caca_put_char(cv, x, y, sscanu32(buf + 4 + control_size
392  + offset + 8 * n));
393  caca_put_attr(cv, x, y, sscanu32(buf + 4 + control_size
394  + offset + 8 * n + 4));
395  }
396  offset += width * height * 8;
397 
398  cv->frames[f].x -= cv->frames[f].handlex;
399  cv->frames[f].y -= cv->frames[f].handley;
400  cv->frames[f].handlex = -xmin;
401  cv->frames[f].handley = -ymin;
402  }
403 
404  caca_set_frame(cv, 0);
405 
406  return (ssize_t)(4 + control_size + data_size);
407 
408 invalid_caca:
409  seterrno(EINVAL);
410  return -1;
411 }
412 
413 ssize_t _import_bin(caca_canvas_t *cv, void const *data, size_t len)
414 {
415  uint8_t const *buf = (uint8_t const *)data;
416  size_t i;
417  int x = 0, y = 0;
418 
419  caca_set_canvas_size(cv, 0, 0);
420  caca_set_canvas_size(cv, 160, len / 160);
421 
422  for (i = 0; i < len; i += 2)
423  {
424  caca_set_color_ansi(cv, buf[i + 1] & 0xf, buf[i + 1] >> 4);
425  caca_put_char(cv, x, y, caca_cp437_to_utf32(buf[i]));
426 
427  ++x;
428  if (x >= 160)
429  {
430  ++y;
431  x = 0;
432  }
433  }
434 
435  return len & ~(size_t)1;
436 }
437 
438 /*
439  * XXX: The following functions are aliases.
440  */
441 
442 ssize_t cucul_import_memory(cucul_canvas_t *, void const *, size_t,
444 ssize_t cucul_import_file(cucul_canvas_t *, char const *,
446 ssize_t caca_import_memory(caca_canvas_t *, void const *, size_t, char const *)
448 ssize_t caca_import_file(caca_canvas_t *, char const *, char const *)
450 char const * const * cucul_get_import_list(void)
452 
sscanu16
static uint16_t sscanu16(void const *s)
Definition: import.c:36
caca_file
Definition: file.c:38
CACA_ALIAS
#define CACA_ALIAS(x)
Definition: caca.h:689
caca_blit
int caca_blit(caca_canvas_t *, int, int, caca_canvas_t const *, caca_canvas_t const *)
Blit a canvas onto another one.
Definition: string.c:455
cucul_get_import_list
#define cucul_get_import_list
Definition: caca.h:822
caca_free_frame
int caca_free_frame(caca_canvas_t *, int)
Remove a frame from a canvas.
Definition: frame.c:205
caca_frame::handley
int handley
Definition: caca_internals.h:40
y
static int y
Definition: cacadraw.c:27
caca_import_area_from_memory
ssize_t caca_import_area_from_memory(caca_canvas_t *cv, int x, int y, void const *data, size_t len, char const *format)
Import a memory buffer into a canvas area.
Definition: import.c:209
caca_create_frame
int caca_create_frame(caca_canvas_t *, int)
Add a frame to a canvas.
Definition: frame.c:145
caca_file_eof
int caca_file_eof(caca_file_t *)
Tell whether a file handle reached end of file.
Definition: file.c:298
caca_create_canvas
caca_canvas_t * caca_create_canvas(int, int)
Initialise a libcaca canvas.
Definition: canvas.c:54
caca_free_canvas
int caca_free_canvas(caca_canvas_t *)
Free a libcaca canvas.
Definition: canvas.c:308
sscanu32
static uint32_t sscanu32(void const *s)
Definition: import.c:29
caca_canvas::curattr
uint32_t curattr
Definition: caca_internals.h:74
codec.h
caca_canvas::frames
struct caca_frame * frames
Definition: caca_internals.h:54
hton16
static uint16_t hton16(uint16_t x)
Definition: caca_stubs.h:46
caca_import_memory
ssize_t caca_import_memory(caca_canvas_t *, void const *, size_t, char const *)
strcasecmp
#define strcasecmp
Definition: config.h:95
caca_cp437_to_utf32
uint32_t caca_cp437_to_utf32(uint8_t)
Convert a CP437 character to UTF-32.
Definition: charset.c:223
caca_import_file
ssize_t caca_import_file(caca_canvas_t *, char const *, char const *)
seterrno
#define seterrno(x)
Definition: caca_stubs.h:27
setup.version
version
Definition: setup.py:21
cucul_canvas_t
#define cucul_canvas_t
Definition: caca.h:763
caca_frame::x
int x
Definition: caca_internals.h:39
caca_get_import_list
const char *const * caca_get_import_list(void)
Get available import formats.
Definition: import.c:276
cv
caca_canvas_t * cv
Definition: cacaview.c:45
caca_file_close
int caca_file_close(caca_file_t *)
Close a file handle.
Definition: file.c:151
_import_text
ssize_t _import_text(caca_canvas_t *, void const *, size_t)
Definition: text.c:44
caca_import_area_from_file
ssize_t caca_import_area_from_file(caca_canvas_t *cv, int x, int y, char const *filename, char const *format)
Import a file into a canvas area.
Definition: import.c:248
caca_import_canvas_from_memory
ssize_t caca_import_canvas_from_memory(caca_canvas_t *cv, void const *data, size_t len, char const *format)
Import a memory buffer into a canvas.
Definition: import.c:73
caca_put_char
int caca_put_char(caca_canvas_t *, int, int, uint32_t)
Print an ASCII or Unicode character.
Definition: string.c:120
caca_internals.h
caca_put_attr
int caca_put_attr(caca_canvas_t *cv, int x, int y, uint32_t attr)
Set the character attribute at the given coordinates.
Definition: attr.c:182
hton32
static uint32_t hton32(uint32_t x)
Definition: caca_stubs.h:60
caca_frame::y
int y
Definition: caca_internals.h:39
caca_frame::handlex
int handlex
Definition: caca_internals.h:40
caca_file_open
caca_file_t * caca_file_open(char const *, const char *)
Open a file for reading or writing.
Definition: file.c:64
caca_set_color_ansi
int caca_set_color_ansi(caca_canvas_t *cv, uint8_t fg, uint8_t bg)
Set the default colour pair for text (ANSI version).
Definition: attr.c:234
caca_set_canvas_size
int caca_set_canvas_size(caca_canvas_t *, int, int)
Resize a canvas.
Definition: canvas.c:212
caca.h
The libcaca public header.
import_caca
static ssize_t import_caca(caca_canvas_t *, void const *, size_t)
Definition: import.c:296
config.h
caca_import_canvas_from_file
ssize_t caca_import_canvas_from_file(caca_canvas_t *cv, char const *filename, char const *format)
Import a file into a canvas.
Definition: import.c:152
_import_bin
ssize_t _import_bin(caca_canvas_t *cv, void const *data, size_t len)
Definition: import.c:413
cucul_import_file
#define cucul_import_file
Definition: caca.h:821
caca_set_frame
int caca_set_frame(caca_canvas_t *, int)
Activate a given canvas frame.
Definition: frame.c:57
cucul_import_memory
#define cucul_import_memory
Definition: caca.h:820
debug
#define debug(format,...)
Definition: caca_debug.h:36
caca_file_read
size_t caca_file_read(caca_file_t *, void *, size_t)
Read data from a file handle.
Definition: file.c:199
_import_ansi
ssize_t _import_ansi(caca_canvas_t *, void const *, size_t, int)
Definition: text.c:86
caca_canvas
Definition: caca_internals.h:47
x
static int x
Definition: cacadraw.c:27
caca_get_frame_count
int caca_get_frame_count(caca_canvas_t const *)
Get the number of frames in a canvas.
Definition: frame.c:37