]> granicus.if.org Git - libass/blob - test/test.c
6a6d8fb9857a04e03e75742042869a6d9a2cbb6b
[libass] / test / test.c
1 /*
2  * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
3  * Copyright (C) 2009 Grigori Goronzy <greg@geekmind.org>
4  *
5  * This file is part of libass.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <ass.h>
24 #include <png.h>
25
26 typedef struct image_s {
27     int width, height, stride;
28     unsigned char *buffer;      // RGB24
29 } image_t;
30
31 ASS_Library *ass_library;
32 ASS_Renderer *ass_renderer;
33
34 void msg_callback(int level, const char *fmt, va_list va, void *data)
35 {
36     if (level > 6)
37         return;
38     printf("libass: ");
39     vprintf(fmt, va);
40     printf("\n");
41 }
42
43 static void write_png(char *fname, image_t *img)
44 {
45     FILE *fp;
46     png_structp png_ptr;
47     png_infop info_ptr;
48     png_byte **row_pointers;
49     int k;
50
51     png_ptr =
52         png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
53     info_ptr = png_create_info_struct(png_ptr);
54     fp = NULL;
55
56     if (setjmp(png_jmpbuf(png_ptr))) {
57         png_destroy_write_struct(&png_ptr, &info_ptr);
58         fclose(fp);
59         return;
60     }
61
62     fp = fopen(fname, "wb");
63     if (fp == NULL) {
64         printf("PNG Error opening %s for writing!\n", fname);
65         return;
66     }
67
68     png_init_io(png_ptr, fp);
69     png_set_compression_level(png_ptr, 0);
70
71     png_set_IHDR(png_ptr, info_ptr, img->width, img->height,
72                  8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
73                  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
74
75     png_write_info(png_ptr, info_ptr);
76
77     png_set_bgr(png_ptr);
78
79     row_pointers = (png_byte **) malloc(img->height * sizeof(png_byte *));
80     for (k = 0; k < img->height; k++)
81         row_pointers[k] = img->buffer + img->stride * k;
82
83     png_write_image(png_ptr, row_pointers);
84     png_write_end(png_ptr, info_ptr);
85     png_destroy_write_struct(&png_ptr, &info_ptr);
86
87     free(row_pointers);
88
89     fclose(fp);
90 }
91
92 static void init(int frame_w, int frame_h)
93 {
94     ass_library = ass_library_init();
95     if (!ass_library) {
96         printf("ass_library_init failed!\n");
97         exit(1);
98     }
99
100     ass_set_message_cb(ass_library, msg_callback, NULL);
101
102     ass_renderer = ass_renderer_init(ass_library);
103     if (!ass_renderer) {
104         printf("ass_renderer_init failed!\n");
105         exit(1);
106     }
107
108     ass_set_frame_size(ass_renderer, frame_w, frame_h);
109     ass_set_fonts(ass_renderer, NULL, "Sans", 1, NULL, 1);
110 }
111
112 static image_t *gen_image(int width, int height)
113 {
114     image_t *img = malloc(sizeof(image_t));
115     img->width = width;
116     img->height = height;
117     img->stride = width * 3;
118     img->buffer = (unsigned char *) calloc(1, height * width * 3);
119     memset(img->buffer, 63, img->stride * img->height);
120     //for (int i = 0; i < height * width * 3; ++i)
121     // img->buffer[i] = (i/3/50) % 100;
122     return img;
123 }
124
125 #define _r(c)  ((c)>>24)
126 #define _g(c)  (((c)>>16)&0xFF)
127 #define _b(c)  (((c)>>8)&0xFF)
128 #define _a(c)  ((c)&0xFF)
129
130 static void blend_single(image_t * frame, ASS_Image *img)
131 {
132     int x, y;
133     unsigned char opacity = 255 - _a(img->color);
134     unsigned char r = _r(img->color);
135     unsigned char g = _g(img->color);
136     unsigned char b = _b(img->color);
137
138     unsigned char *src;
139     unsigned char *dst;
140
141     src = img->bitmap;
142     dst = frame->buffer + img->dst_y * frame->stride + img->dst_x * 3;
143     for (y = 0; y < img->h; ++y) {
144         for (x = 0; x < img->w; ++x) {
145             unsigned k = ((unsigned) src[x]) * opacity / 255;
146             // possible endianness problems
147             dst[x * 3] = (k * b + (255 - k) * dst[x * 3]) / 255;
148             dst[x * 3 + 1] = (k * g + (255 - k) * dst[x * 3 + 1]) / 255;
149             dst[x * 3 + 2] = (k * r + (255 - k) * dst[x * 3 + 2]) / 255;
150         }
151         src += img->stride;
152         dst += frame->stride;
153     }
154 }
155
156 static void blend(image_t * frame, ASS_Image *img)
157 {
158     int cnt = 0;
159     while (img) {
160         blend_single(frame, img);
161         ++cnt;
162         img = img->next;
163     }
164     printf("%d images blended\n", cnt);
165 }
166
167 int main(int argc, char *argv[])
168 {
169     const int frame_w = 1280;
170     const int frame_h = 720;
171
172     if (argc < 4) {
173         printf("usage: %s <image file> <subtitle file> <time>\n", argv[0]);
174         exit(1);
175     }
176     char *imgfile = argv[1];
177     char *subfile = argv[2];
178     double tm = strtod(argv[3], 0);
179
180     init(frame_w, frame_h);
181     ASS_Track *track = ass_read_file(ass_library, subfile, NULL);
182     if (!track) {
183         printf("track init failed!\n");
184         return 1;
185     }
186
187     ASS_Image *img =
188         ass_render_frame(ass_renderer, track, (int) (tm * 1000), NULL);
189     image_t *frame = gen_image(frame_w, frame_h);
190     blend(frame, img);
191
192     ass_free_track(track);
193     ass_renderer_done(ass_renderer);
194     ass_library_done(ass_library);
195
196     write_png(imgfile, frame);
197     free(frame->buffer);
198     free(frame);
199
200     return 0;
201 }