File: gap_vid_api_gimp.c

package info (click to toggle)
gimp-gap 2.6.0%2Bdfsg-5
  • links: PTS
  • area: main
  • in suites: bullseye, buster, stretch
  • size: 20,720 kB
  • ctags: 7,997
  • sloc: ansic: 119,817; sh: 3,890; makefile: 932; lisp: 97; pascal: 55
file content (403 lines) | stat: -rw-r--r-- 11,613 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
/* gap_vid_api_gimp.c
 *
 * GAP Video read API implementation for singleframe sequence
 * wrappers for gap/gimp generic file load procedure
 *
 * please note that the singleframes are loaded as flatened frames
 * when they are read by this API.
 *
 * 2003.05.09   hof created
 *
 */


/* ================================================ gimp
 * gimp (singleframe access via gap/gimp)           gimp
 * ================================================ gimp
 * ================================================ gimp
 */
#ifdef ENABLE_GVA_GIMP

static gchar  *global_gva_gimp_filename = NULL;
static gint32  global_gva_gimp_image_id = -1;

/* -------------------------
 * API READ extension GIMP
 * -------------------------
 */

/* structure with gap specific anim information */
typedef struct t_GVA_gimp
{
   gint32       initial_image_id;
   long         first_frame_nr;
   long         last_frame_nr;
   long         curr_frame_nr;
   long         frame_cnt;
   char         basename[1024];    /* may include path */
   char         extension[50];
   gdouble      framerate;
} t_GVA_gimp;



/* -----------------------------
 * p_wrapper_gimp_check_sig
 * -----------------------------
 */
gboolean
p_wrapper_gimp_check_sig(char *filename)
{
  gint32 l_image_id;

  if(gap_debug) printf("p_wrapper_gimp_check_sig: START filename:%s\n", filename);

  l_image_id = gimp_file_load(GIMP_RUN_NONINTERACTIVE, filename, filename);
  if (l_image_id < 0)
  {
     if(gap_debug) printf("p_wrapper_gimp_check_sig:%s: could not load file\n", filename);
     return(FALSE);
  }

  /* we do not delete l_image_id at this point.
   * in most cases the check_sig call is followed by open_read
   * where we need that image again
   */
  if(global_gva_gimp_filename) g_free(global_gva_gimp_filename);
  global_gva_gimp_filename = g_strdup(filename);
  global_gva_gimp_image_id = l_image_id;

  if(gap_debug) printf("p_wrapper_gimp_check_sig: compatible is TRUE\n");

  return (TRUE);
}

/* -----------------------------
 * p_wrapper_gimp_open_read
 * -----------------------------
 *  open performs a GAP directory scan to findout
 *  how many frames we have.
 *  the initial image (the one with filename)
 *  will be loaded as gimp_image and kept cached until close.
 */
void
p_wrapper_gimp_open_read(char *filename, t_GVA_Handle *gvahand)
{
  t_GVA_gimp*  handle;
  t_GVA_DecoderElem  *dec_elem;
  gint32       l_image_id;

  if(gap_debug) printf("p_wrapper_gimp_open_read: START filename:%s\n", filename);

  gvahand->decoder_handle = (void *)NULL;

  handle = g_malloc0(sizeof(t_GVA_gimp));

  l_image_id = -1;
  if(global_gva_gimp_filename)
  {
    if(strcmp(global_gva_gimp_filename, filename) == 0)
    {
      l_image_id = global_gva_gimp_image_id;
    }
  }

  if(l_image_id < 0)
  {
    l_image_id = gimp_file_load(GIMP_RUN_NONINTERACTIVE, filename, filename);
    if (l_image_id < 0)
    {
      g_free(handle);
      return;
    }
  }

  /* the initial image is now flattened and kept until close
   * (read ops for the curr_frame_nr will read from the initial_image_id
   *  and can skip the slower file load)
   */
  gimp_image_flatten(l_image_id);
  handle->initial_image_id = l_image_id;

  gvahand->gva_thread_save = FALSE;  /* calls to gimp from 2 threads do crash */
  gvahand->vtracks = 1;
  gvahand->atracks = 0;
  gvahand->frame_bpp = 3;              /* RGB pixelformat */
  gvahand->total_aud_samples = 0;
  gvahand->width = gimp_image_width(l_image_id);
  gvahand->height = gimp_image_height(l_image_id);

  /* fetch animframe informations (perform GAP directoryscan) */
  if(l_image_id >= 0)
  {
    static char     *l_called_proc = "plug_in_gap_get_animinfo";
    GimpParam       *return_vals;
    int              nreturn_vals;
    gint32           dummy_layer_id;

    dummy_layer_id = gap_image_get_any_layer(l_image_id);
    return_vals = gimp_run_procedure (l_called_proc,
                                 &nreturn_vals,
                                 GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE,
                                 GIMP_PDB_IMAGE, l_image_id,
                                 GIMP_PDB_DRAWABLE, dummy_layer_id,
                                 GIMP_PDB_END);

    if (return_vals[0].data.d_status != GIMP_PDB_SUCCESS)
    {
      printf("Error: PDB call of %s failed, image_ID: %d\n", l_called_proc, (int)l_image_id);
      g_free(handle);
      return;
    }
    handle->first_frame_nr = return_vals[1].data.d_int32;
    handle->last_frame_nr =  return_vals[2].data.d_int32;
    handle->curr_frame_nr =  return_vals[3].data.d_int32;
    handle->frame_cnt =      return_vals[4].data.d_int32;
    g_snprintf(handle->basename, sizeof(handle->basename), "%s", return_vals[5].data.d_string);
    g_snprintf(handle->extension, sizeof(handle->extension), "%s", return_vals[6].data.d_string);
    handle->framerate = return_vals[7].data.d_float;
  }

  gvahand->framerate    = handle->framerate;
  gvahand->total_frames = handle->frame_cnt;
  gvahand->all_frames_counted = TRUE;  /* handle->frame_cnt is the exact total_frames number */

  dec_elem = (t_GVA_DecoderElem *)gvahand->dec_elem;

  if(dec_elem)
  {
    if(dec_elem->decoder_description)
    {
      g_free(dec_elem->decoder_description);
    }
    dec_elem->decoder_description =
        g_strdup_printf("GAP Decoder (for all GIMP readable imagefiles)\n"
                        " (EXT: .xcf,.jpg,.gif,.png,.tif,...)"
                       );
  }


  gvahand->decoder_handle = (void *)handle;

  if(gap_debug) printf("p_wrapper_gimp_open_read: END, OK\n");

}  /* end p_wrapper_gimp_open_read */


/* -----------------------------
 * p_wrapper_gimp_close
 * -----------------------------
 */
void
p_wrapper_gimp_close(t_GVA_Handle *gvahand)
{
  t_GVA_gimp *handle;

  if(gap_debug) printf("p_wrapper_gimp_close: START\n");

  handle = (t_GVA_gimp *)gvahand->decoder_handle;

  /* delete the initial image at close */
  p_gimp_image_delete(handle->initial_image_id);

  return;
}  /* end p_wrapper_gimp_close */


/* ----------------------------------
 * p_wrapper_gimp_get_next_frame
 * ----------------------------------
 * read singleframe with current_seek_nr and advance position
 * TODO: EOF detection
 *
 */
t_GVA_RetCode
p_wrapper_gimp_get_next_frame(t_GVA_Handle *gvahand)
{
  t_GVA_gimp *handle;
  gchar    *l_framename;
  gint32    l_image_id;
  gint32    l_frame_nr;
  t_GVA_RetCode       l_rc;

  handle = (t_GVA_gimp *)gvahand->decoder_handle;

  l_frame_nr = gvahand->current_seek_nr + (handle->first_frame_nr - 1);

  if(1==0  /*l_frame_nr == handle->curr_frame_nr*/)
  {
    /* this frame_nr is the initial_image, that is always cached
     * as gimp image (without a display)
     * no need to load agian, just transfer to rowbuffer
     */
    l_rc = GVA_gimp_image_to_rowbuffer(gvahand, handle->initial_image_id);
  }
  else
  {
    l_framename = p_alloc_fname(handle->basename
                               ,l_frame_nr
                               ,handle->extension
                               );

    l_image_id = gimp_file_load(GIMP_RUN_NONINTERACTIVE, l_framename, l_framename);
    if(l_image_id < 0)
    {
      l_rc = GVA_RET_ERROR;
    }
    else
    {
      l_rc = GVA_gimp_image_to_rowbuffer(gvahand, l_image_id);
      p_gimp_image_delete(l_image_id);
    }

    g_free(l_framename);
  }

  if (l_rc == GVA_RET_OK)
  {
    gvahand->current_frame_nr = gvahand->current_seek_nr;
    gvahand->current_seek_nr++;
    return(GVA_RET_OK);
  }

  return(l_rc);
}  /* end p_wrapper_gimp_get_next_frame */


/* ------------------------------
 * p_wrapper_gimp_seek_frame
 * ------------------------------
 *  - for the singleframe decoder
 *    we just set the current framenumber.
 */
t_GVA_RetCode
p_wrapper_gimp_seek_frame(t_GVA_Handle *gvahand, gdouble pos, t_GVA_PosUnit pos_unit)
{
  t_GVA_gimp *handle;
  gint32   l_frame_pos;

  handle = (t_GVA_gimp *)gvahand->decoder_handle;

  switch(pos_unit)
  {
    case GVA_UPOS_FRAMES:
      l_frame_pos = (gint32)pos;
      break;
    case GVA_UPOS_SECS:
      l_frame_pos = (gint32)rint (pos * gvahand->framerate);
      break;
    case GVA_UPOS_PRECENTAGE:
      /* is not reliable until all_frames_counted == TRUE */
      l_frame_pos = (gint32)GVA_percent_2_frame(gvahand->total_frames, pos);
      break;
    default:
      l_frame_pos = (gint32)pos;
      break;
  }

  gvahand->percentage_done = 0.0;

  if(l_frame_pos < gvahand->total_frames)
  {
    if(gap_debug) printf("p_wrapper_gimp_seek_frame: SEEK OK: l_frame_pos: %d cur_seek:%d cur_frame:%d\n", (int)l_frame_pos, (int)gvahand->current_seek_nr, (int)gvahand->current_frame_nr);

    gvahand->current_seek_nr = (gint32)l_frame_pos;

    return(GVA_RET_OK);
  }

  return(GVA_RET_EOF);
}  /* end p_wrapper_gimp_seek_frame */


/* ------------------------------
 * p_wrapper_gimp_seek_audio
 * ------------------------------
 */
t_GVA_RetCode
p_wrapper_gimp_seek_audio(t_GVA_Handle *gvahand, gdouble pos, t_GVA_PosUnit pos_unit)
{
  printf("p_wrapper_gimp_get_audio: there is NO adiosupport for single frames\n");
  return(GVA_RET_ERROR);
}  /* end p_wrapper_gimp_seek_audio */


/* ------------------------------
 * p_wrapper_gimp_get_audio
 * ------------------------------
 */
t_GVA_RetCode
p_wrapper_gimp_get_audio(t_GVA_Handle *gvahand
             ,gint16 *output_i
             ,gint32 channel
             ,gdouble samples
             ,t_GVA_AudPos mode_flag
             )
{
  printf("p_wrapper_gimp_get_audio: there is NO adiosupport for single frames\n");
  return(GVA_RET_ERROR);
}  /* end p_wrapper_gimp_get_audio */


/* ----------------------------------
 * p_wrapper_gimp_count_frames
 * ----------------------------------
 * (re)open a separated handle for counting
 * to ensure that stream positions are not affected by the count.
 */
t_GVA_RetCode
p_wrapper_gimp_count_frames(t_GVA_Handle *gvahand)
{
  gvahand->percentage_done = 0.0;
  /* do not count at all, exact total_frames is known at open_read time */
  return(GVA_RET_OK);
}  /* end p_wrapper_gimp_count_frames */



/* ----------------------------------
 * p_wrapper_gimp_seek_support
 * ----------------------------------
 */
t_GVA_SeekSupport
p_wrapper_gimp_seek_support(t_GVA_Handle *gvahand)
{
  return(GVA_SEEKSUPP_NATIVE);
}  /* end p_wrapper_gimp_seek_support */


/* -----------------------------
 * p_gimp_new_dec_elem
 * -----------------------------
 * create a new decoder element and init with
 * functionpointers referencing the GIMP singleframe
 * specific Procedures
 */
t_GVA_DecoderElem  *
p_gimp_new_dec_elem(void)
{
  t_GVA_DecoderElem  *dec_elem;

  dec_elem = g_malloc0(sizeof(t_GVA_DecoderElem));
  if(dec_elem)
  {
    dec_elem->decoder_name         = g_strdup("gimp/gap");
    dec_elem->decoder_description  = g_strdup("gimp singleframe loader (EXT: .xcf,.jpg,.gif,.tif,.bmp,...)");
    dec_elem->fptr_check_sig       = &p_wrapper_gimp_check_sig;
    dec_elem->fptr_open_read       = &p_wrapper_gimp_open_read;
    dec_elem->fptr_close           = &p_wrapper_gimp_close;
    dec_elem->fptr_get_next_frame  = &p_wrapper_gimp_get_next_frame;
    dec_elem->fptr_seek_frame      = &p_wrapper_gimp_seek_frame;
    dec_elem->fptr_seek_audio      = &p_wrapper_gimp_seek_audio;
    dec_elem->fptr_get_audio       = &p_wrapper_gimp_get_audio;
    dec_elem->fptr_count_frames    = &p_wrapper_gimp_count_frames;
    dec_elem->fptr_seek_support    = &p_wrapper_gimp_seek_support;
    dec_elem->fptr_get_video_chunk = NULL;  /* singleframes dont have compressed video chunks */
    dec_elem->next = NULL;
  }

  return (dec_elem);
}  /* end p_gimp_new_dec_elem */


#endif  /* ENABLE_GVA_GIMP */