Subversion Repositories cinelerra

Compare Revisions

Ignore whitespace Rev 658 → Rev 659

/branches/automake-1_1_5/hvirtual/quicktime/avcc.c
New file
0,0 → 1,61
#include "funcprotos.h"
#include "quicktime.h"
 
 
 
void quicktime_delete_avcc(quicktime_avcc_t *avcc)
{
if(avcc->data) free(avcc->data);
}
 
// Set esds header to a copy of the argument
void quicktime_set_avcc_header(quicktime_avcc_t *avcc,
unsigned char *data,
int size)
{
if(avcc->data)
{
free(avcc->data);
}
 
avcc->data = calloc(1, size);
memcpy(avcc->data, data, size);
avcc->data_size = size;
}
 
void quicktime_write_avcc(quicktime_t *file,
quicktime_avcc_t *avcc)
{
quicktime_atom_t atom;
quicktime_atom_write_header(file, &atom, "avcC");
quicktime_write_data(file, avcc->data, avcc->data_size);
quicktime_atom_write_footer(file, &atom);
}
 
 
 
int quicktime_read_avcc(quicktime_t *file,
quicktime_atom_t *parent_atom,
quicktime_avcc_t *avcc)
{
avcc->data_size = parent_atom->size - 8;
avcc->data = calloc(1, avcc->data_size + 1024);
quicktime_read_data(file,
avcc->data,
avcc->data_size);
quicktime_atom_skip(file, parent_atom);
return 0;
}
 
void quicktime_avcc_dump(quicktime_avcc_t *avcc)
{
int i;
printf(" h264 description\n");
printf(" data_size=0x%x\n", avcc->data_size);
printf(" data=");
for(i = 0; i < avcc->data_size; i++)
{
printf("0x%02x ", (unsigned char)avcc->data[i]);
}
printf("\n");
}
/branches/automake-1_1_5/hvirtual/quicktime/qtdv.c
New file
0,0 → 1,447
/* 2002: Refurbished by Arthur Peters amep@softhome.net */
/* 2000: Original codec by Heroine Virtual */
 
 
#include "colormodels.h"
#include "funcprotos.h"
#include "libdv/dv.h"
#include "quicktime.h"
 
#include <pthread.h>
#include <string.h>
 
// Buffer sizes
#define DV_NTSC_SIZE 120000
#define DV_PAL_SIZE 144000
 
typedef struct
{
dv_decoder_t *dv_decoder;
dv_encoder_t *dv_encoder;
unsigned char *data;
unsigned char *temp_frame, **temp_rows;
 
/* Parameters */
int decode_quality;
int anamorphic16x9;
int vlc_encode_passes;
int clamp_luma, clamp_chroma;
 
int add_ntsc_setup;
 
int rem_ntsc_setup;
 
int parameters_changed;
} quicktime_dv_codec_t;
 
static pthread_mutex_t libdv_init_mutex = PTHREAD_MUTEX_INITIALIZER;
 
static int delete_codec(quicktime_video_map_t *vtrack)
{
quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
 
if(codec->dv_decoder)
{
dv_decoder_free( codec->dv_decoder );
codec->dv_decoder = NULL;
}
if(codec->dv_encoder)
{
dv_encoder_free( codec->dv_encoder );
codec->dv_encoder = NULL;
}
if(codec->temp_frame) free(codec->temp_frame);
if(codec->temp_rows) free(codec->temp_rows);
free(codec->data);
free(codec);
return 0;
}
 
static int check_sequentiality( unsigned char **row_pointers,
int bytes_per_row,
int height )
{
int i = 0;
for(; i < height-1; i++)
{
if( row_pointers[i+1] - row_pointers[i] != bytes_per_row )
{
return 0;
}
}
return 1;
}
 
static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
{
long bytes;
quicktime_video_map_t *vtrack = &(file->vtracks[track]);
quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
int width = vtrack->track->tkhd.track_width;
int height = vtrack->track->tkhd.track_height;
int result = 0;
int i;
int decode_colormodel = 0;
int pitches[3] = { 720 * 2, 0, 0 };
 
 
quicktime_set_video_position(file, vtrack->current_position, track);
bytes = quicktime_frame_size(file, vtrack->current_position, track);
result = !quicktime_read_data(file, (char*)codec->data, bytes);
 
if( codec->dv_decoder && codec->parameters_changed )
{
dv_decoder_free( codec->dv_decoder );
codec->dv_decoder = NULL;
codec->parameters_changed = 0;
}
if( ! codec->dv_decoder )
{
pthread_mutex_lock( &libdv_init_mutex );
 
codec->dv_decoder = dv_decoder_new( codec->add_ntsc_setup,
codec->clamp_luma,
codec->clamp_chroma );
codec->dv_decoder->prev_frame_decoded = 0;
codec->parameters_changed = 0;
pthread_mutex_unlock( &libdv_init_mutex );
}
 
if(codec->dv_decoder)
{
int is_sequential =
check_sequentiality( row_pointers,
720 * cmodel_calculate_pixelsize(file->color_model),
file->out_h );
 
codec->dv_decoder->quality = codec->decode_quality;
 
dv_parse_header( codec->dv_decoder, codec->data );
// Libdv improperly decodes RGB colormodels.
if((file->color_model == BC_YUV422 ||
file->color_model == BC_RGB888) &&
file->in_x == 0 &&
file->in_y == 0 &&
file->in_w == width &&
file->in_h == height &&
file->out_w == width &&
file->out_h == height &&
is_sequential)
{
if( file->color_model == BC_YUV422 )
{
pitches[0] = 720 * 2;
dv_decode_full_frame( codec->dv_decoder, codec->data,
e_dv_color_yuv, row_pointers,
pitches );
}
else
if( file->color_model == BC_RGB888)
{
pitches[0] = 720 * 3;
dv_decode_full_frame( codec->dv_decoder, codec->data,
e_dv_color_rgb, row_pointers,
pitches );
}
}
else
{
if(!codec->temp_frame)
{
codec->temp_frame = malloc(720 * 576 * 2);
codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
for(i = 0; i < 576; i++)
codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
}
 
decode_colormodel = BC_YUV422;
pitches[0] = 720 * 2;
dv_decode_full_frame( codec->dv_decoder, codec->data,
e_dv_color_yuv, codec->temp_rows,
pitches );
 
 
 
cmodel_transfer(row_pointers,
codec->temp_rows,
row_pointers[0],
row_pointers[1],
row_pointers[2],
codec->temp_rows[0],
codec->temp_rows[1],
codec->temp_rows[2],
file->in_x,
file->in_y,
file->in_w,
file->in_h,
0,
0,
file->out_w,
file->out_h,
decode_colormodel,
file->color_model,
0,
width,
file->out_w);
}
}
 
//printf(__FUNCTION__ " 2\n");
return result;
}
 
static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
{
int64_t offset = quicktime_position(file);
quicktime_video_map_t *vtrack = &(file->vtracks[track]);
quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
quicktime_trak_t *trak = vtrack->track;
int width = trak->tkhd.track_width;
int height = trak->tkhd.track_height;
int width_i = 720;
int height_i = (height <= 480) ? 480 : 576;
int i;
unsigned char **input_rows;
int is_pal = (height_i == 480) ? 0 : 1;
int data_length = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
int result = 0;
int encode_colormodel = 0;
dv_color_space_t encode_dv_colormodel = 0;
quicktime_atom_t chunk_atom;
 
if( codec->dv_encoder != NULL && codec->parameters_changed )
{
dv_encoder_free( codec->dv_encoder );
codec->dv_encoder = NULL;
codec->parameters_changed = 0;
}
if( ! codec->dv_encoder )
{
pthread_mutex_lock( &libdv_init_mutex );
 
//printf( "dv.c encode: Alloc'ing encoder\n" );
codec->dv_encoder = dv_encoder_new( codec->rem_ntsc_setup,
codec->clamp_luma,
codec->clamp_chroma );
 
codec->parameters_changed = 0;
pthread_mutex_unlock( &libdv_init_mutex );
}
 
if(codec->dv_encoder)
{
int is_sequential =
check_sequentiality( row_pointers,
width_i * cmodel_calculate_pixelsize(file->color_model),
height );
if( ( file->color_model == BC_YUV422
|| file->color_model == BC_RGB888 ) &&
width == width_i &&
height == height_i &&
is_sequential )
{
input_rows = row_pointers;
encode_colormodel = file->color_model;
switch( file->color_model )
{
case BC_YUV422:
encode_dv_colormodel = e_dv_color_yuv;
//printf( "dv.c encode: e_dv_color_yuv\n" );
break;
case BC_RGB888:
encode_dv_colormodel = e_dv_color_rgb;
//printf( "dv.c encode: e_dv_color_rgb\n" );
break;
default:
return 0;
break;
}
}
else
{
// The best colormodel for encoding is YUV 422
 
if(!codec->temp_frame)
{
codec->temp_frame = malloc(720 * 576 * 2);
codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
for(i = 0; i < 576; i++)
codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
}
cmodel_transfer(codec->temp_rows, /* Leave NULL if non existent */
row_pointers,
codec->temp_rows[0], /* Leave NULL if non existent */
codec->temp_rows[1],
codec->temp_rows[2],
row_pointers[0], /* Leave NULL if non existent */
row_pointers[1],
row_pointers[2],
0, /* Dimensions to capture from input frame */
0,
MIN(width, width_i),
MIN(height, height_i),
0, /* Dimensions to project on output frame */
0,
MIN(width, width_i),
MIN(height, height_i),
file->color_model,
BC_YUV422,
0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
width, /* For planar use the luma rowspan */
width_i);
 
 
input_rows = codec->temp_rows;
encode_colormodel = BC_YUV422;
encode_dv_colormodel = e_dv_color_yuv;
}
 
// Setup the encoder
codec->dv_encoder->is16x9 = codec->anamorphic16x9;
codec->dv_encoder->vlc_encode_passes = codec->vlc_encode_passes;
codec->dv_encoder->static_qno = 0;
codec->dv_encoder->force_dct = DV_DCT_AUTO;
codec->dv_encoder->isPAL = is_pal;
 
 
//printf("dv.c encode: 1 %d %d %d\n", width_i, height_i, encode_dv_colormodel);
dv_encode_full_frame( codec->dv_encoder,
input_rows, encode_dv_colormodel, codec->data );
//printf("dv.c encode: 2 %d %d\n", width_i, height_i);
 
quicktime_write_chunk_header(file, trak, &chunk_atom);
result = !quicktime_write_data(file, codec->data, data_length);
quicktime_write_chunk_footer(file,
trak,
vtrack->current_chunk,
&chunk_atom,
1);
vtrack->current_chunk++;
//printf("encode 3\n");
}
 
return result;
}
 
// Logic: DV contains a mixture of 420 and 411 so can only
// output/input 444 or 422 and libdv can output/input RGB as well so
// we include that.
 
// This function is used as both reads_colormodel and writes_colormodel
static int colormodel_dv(quicktime_t *file,
int colormodel,
int track)
{
return (colormodel == BC_RGB888 ||
colormodel == BC_YUV888 ||
colormodel == BC_YUV422);
}
 
static int set_parameter(quicktime_t *file,
int track,
char *key,
void *value)
{
quicktime_dv_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
if(!strcasecmp(key, "dv_decode_quality"))
{
codec->decode_quality = *(int*)value;
}
else if(!strcasecmp(key, "dv_anamorphic16x9"))
{
codec->anamorphic16x9 = *(int*)value;
}
else if(!strcasecmp(key, "dv_vlc_encode_passes"))
{
codec->vlc_encode_passes = *(int*)value;
}
else if(!strcasecmp(key, "dv_clamp_luma"))
{
codec->clamp_luma = *(int*)value;
}
else if(!strcasecmp(key, "dv_clamp_chroma"))
{
codec->clamp_chroma = *(int*)value;
}
else if(!strcasecmp(key, "dv_add_ntsc_setup"))
{
codec->add_ntsc_setup = *(int*)value;
}
else if(!strcasecmp(key, "dv_rem_ntsc_setup"))
{
codec->rem_ntsc_setup = *(int*)value;
}
else
{
return 0;
}
 
codec->parameters_changed = 1;
return 0;
}
 
static void init_codec_common(quicktime_video_map_t *vtrack, char *fourcc)
{
quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
quicktime_dv_codec_t *codec;
int i;
 
/* Init public items */
codec_base->priv = calloc(1, sizeof(quicktime_dv_codec_t));
codec_base->delete_vcodec = delete_codec;
codec_base->decode_video = decode;
codec_base->encode_video = encode;
codec_base->decode_audio = 0;
codec_base->encode_audio = 0;
codec_base->reads_colormodel = colormodel_dv;
codec_base->writes_colormodel = colormodel_dv;
codec_base->set_parameter = set_parameter;
codec_base->fourcc = fourcc;
codec_base->title = "DV";
codec_base->desc = "DV";
 
 
/* Init private items */
 
codec = codec_base->priv;
codec->dv_decoder = NULL;
codec->dv_encoder = NULL;
codec->decode_quality = DV_QUALITY_BEST;
codec->anamorphic16x9 = 0;
codec->vlc_encode_passes = 3;
codec->clamp_luma = codec->clamp_chroma = 0;
codec->add_ntsc_setup = 0;
codec->parameters_changed = 0;
 
// Allocate extra to work around some libdv overrun
codec->data = calloc(1, 144008);
}
 
void quicktime_init_codec_dv(quicktime_video_map_t *vtrack)
{
init_codec_common(vtrack, QUICKTIME_DV);
}
 
void quicktime_init_codec_dv25(quicktime_video_map_t *vtrack)
{
init_codec_common(vtrack, QUICKTIME_DV25);
}
 
void quicktime_init_codec_dvsd(quicktime_video_map_t *vtrack)
{
init_codec_common(vtrack, QUICKTIME_DVSD);
}
/branches/automake-1_1_5/hvirtual/quicktime/qtdv.h
New file
0,0 → 1,8
#ifndef QUICKTIME_DV_H
#define QUICKTIME_DV_H
 
extern void quicktime_init_codec_dv(quicktime_video_map_t *);
extern void quicktime_init_codec_dv25(quicktime_video_map_t *);
extern void quicktime_init_codec_dvsd(quicktime_video_map_t *vtrack);
 
#endif
/branches/automake-1_1_5/hvirtual/quicktime/qtffmpeg.c
New file
0,0 → 1,365
#include "colormodels.h"
#include "funcprotos.h"
#include <pthread.h>
#include "quicktime.h"
#include "qtffmpeg.h"
#include "qtprivate.h"
 
// FFMPEG front end for quicktime.
 
 
 
 
 
 
 
 
int ffmpeg_initialized = 0;
pthread_mutex_t ffmpeg_lock = PTHREAD_MUTEX_INITIALIZER;
 
 
 
 
 
 
quicktime_ffmpeg_t* quicktime_new_ffmpeg(int cpus,
int fields,
int ffmpeg_id,
int w,
int h,
quicktime_stsd_table_t *stsd_table)
{
quicktime_ffmpeg_t *ptr = calloc(1, sizeof(quicktime_ffmpeg_t));
quicktime_esds_t *esds = &stsd_table->esds;
quicktime_avcc_t *avcc = &stsd_table->avcc;
int i;
 
ptr->fields = fields;
ptr->width = w;
ptr->height = h;
ptr->ffmpeg_id = ffmpeg_id;
if(ffmpeg_id == CODEC_ID_SVQ1)
{
ptr->width_i = quicktime_quantize32(ptr->width);
ptr->height_i = quicktime_quantize32(ptr->height);
}
else
{
ptr->width_i = quicktime_quantize16(ptr->width);
ptr->height_i = quicktime_quantize16(ptr->height);
}
 
pthread_mutex_lock(&ffmpeg_lock);
if(!ffmpeg_initialized)
{
ffmpeg_initialized = 1;
avcodec_init();
avcodec_register_all();
}
 
for(i = 0; i < fields; i++)
{
ptr->decoder[i] = avcodec_find_decoder(ptr->ffmpeg_id);
if(!ptr->decoder[i])
{
printf("quicktime_new_ffmpeg: avcodec_find_decoder returned NULL.\n");
quicktime_delete_ffmpeg(ptr);
return 0;
}
ptr->decoder_context[i] = avcodec_alloc_context();
ptr->decoder_context[i]->width = w;
ptr->decoder_context[i]->height = h;
if(esds->mpeg4_header && esds->mpeg4_header_size)
{
ptr->decoder_context[i]->extradata = esds->mpeg4_header;
ptr->decoder_context[i]->extradata_size = esds->mpeg4_header_size;
}
if(avcc->data && avcc->data_size)
{
ptr->decoder_context[i]->extradata = avcc->data;
ptr->decoder_context[i]->extradata_size = avcc->data_size;
}
if(cpus > 1)
{
avcodec_thread_init(ptr->decoder_context[i], cpus);
ptr->decoder_context[i]->thread_count = cpus;
}
if(avcodec_open(ptr->decoder_context[i],
ptr->decoder[i]) < 0)
{
printf("quicktime_new_ffmpeg: avcodec_open failed.\n");
quicktime_delete_ffmpeg(ptr);
}
}
pthread_mutex_unlock(&ffmpeg_lock);
 
return ptr;
}
 
 
 
void quicktime_delete_ffmpeg(quicktime_ffmpeg_t *ptr)
{
int i;
if(ptr)
{
pthread_mutex_lock(&ffmpeg_lock);
for(i = 0; i < ptr->fields; i++)
{
if(ptr->decoder_context[i])
{
avcodec_close(ptr->decoder_context[i]);
free(ptr->decoder_context[i]);
}
}
pthread_mutex_unlock(&ffmpeg_lock);
 
 
 
if(ptr->temp_frame) free(ptr->temp_frame);
if(ptr->work_buffer) free(ptr->work_buffer);
 
 
free(ptr);
}
}
 
 
static int decode_wrapper(quicktime_t *file,
quicktime_video_map_t *vtrack,
quicktime_ffmpeg_t *ffmpeg,
int frame_number,
int current_field,
int track,
int drop_it)
{
int got_picture = 0;
int result = 0;
int bytes = 0;
int header_bytes = 0;
char *compressor = vtrack->track->mdia.minf.stbl.stsd.table[0].format;
quicktime_trak_t *trak = vtrack->track;
quicktime_stsd_table_t *stsd_table = &trak->mdia.minf.stbl.stsd.table[0];
 
quicktime_set_video_position(file, frame_number, track);
 
bytes = quicktime_frame_size(file, frame_number, track);
if(frame_number == 0)
{
header_bytes = stsd_table->esds.mpeg4_header_size;
}
 
if(!ffmpeg->work_buffer || ffmpeg->buffer_size < bytes + header_bytes)
{
if(ffmpeg->work_buffer) free(ffmpeg->work_buffer);
ffmpeg->buffer_size = bytes + header_bytes;
ffmpeg->work_buffer = calloc(1, ffmpeg->buffer_size + 100);
}
if(header_bytes)
memcpy(ffmpeg->work_buffer, stsd_table->esds.mpeg4_header, header_bytes);
 
if(!quicktime_read_data(file,
ffmpeg->work_buffer + header_bytes,
bytes))
result = -1;
if(!result)
{
 
 
// No way to determine if there was an error based on nonzero status.
// Need to test row pointers to determine if an error occurred.
if(drop_it)
ffmpeg->decoder_context[current_field]->skip_frame = AVDISCARD_NONREF;
else
ffmpeg->decoder_context[current_field]->skip_frame = AVDISCARD_DEFAULT;
result = avcodec_decode_video(ffmpeg->decoder_context[current_field],
&ffmpeg->picture[current_field],
&got_picture,
ffmpeg->work_buffer,
bytes + header_bytes);
 
 
 
if(ffmpeg->picture[current_field].data[0])
{
result = 0;
}
else
{
// ffmpeg can't recover if the first frame errored out, like in a direct copy
// sequence.
result = 1;
}
 
#ifdef ARCH_X86
asm("emms");
#endif
}
 
return result;
}
 
 
 
int quicktime_ffmpeg_decode(quicktime_ffmpeg_t *ffmpeg,
quicktime_t *file,
unsigned char **row_pointers,
int track)
{
quicktime_video_map_t *vtrack = &(file->vtracks[track]);
quicktime_trak_t *trak = vtrack->track;
int current_field = vtrack->current_position % ffmpeg->fields;
int input_cmodel;
int result = 0;
int seeking_done = 0;
int i;
 
pthread_mutex_lock(&ffmpeg_lock);
 
// Handle seeking
if(quicktime_has_keyframes(file, track) &&
vtrack->current_position != ffmpeg->last_frame[current_field] + ffmpeg->fields)
{
int frame1;
int frame2 = vtrack->current_position;
int current_frame = frame2;
int do_i_frame = 1;
 
// Get first keyframe of same field
do
{
frame1 = quicktime_get_keyframe_before(file,
current_frame--,
track);
}while(frame1 > 0 && (frame1 % ffmpeg->fields) != current_field);
 
// Keyframe is before last decoded frame and current frame is after last decoded
// frame, so instead of rerendering from the last keyframe we can rerender from
// the last decoded frame.
if(frame1 < ffmpeg->last_frame[current_field] &&
frame2 > ffmpeg->last_frame[current_field])
{
frame1 = ffmpeg->last_frame[current_field] + ffmpeg->fields;
do_i_frame = 0;
}
 
while(frame1 <= frame2)
{
result = decode_wrapper(file,
vtrack,
ffmpeg,
frame1,
current_field,
track,
(frame1 < frame2));
 
 
// May need to do the first I frame twice.
if(do_i_frame)
{
result = decode_wrapper(file,
vtrack,
ffmpeg,
frame1,
current_field,
track,
0);
do_i_frame = 0;
}
frame1 += ffmpeg->fields;
}
 
vtrack->current_position = frame2;
seeking_done = 1;
}
 
if(!seeking_done)
{
result = decode_wrapper(file,
vtrack,
ffmpeg,
vtrack->current_position,
current_field,
track,
0);
}
 
pthread_mutex_unlock(&ffmpeg_lock);
 
 
ffmpeg->last_frame[current_field] = vtrack->current_position;
 
switch(ffmpeg->decoder_context[current_field]->pix_fmt)
{
case PIX_FMT_YUV420P:
input_cmodel = BC_YUV420P;
break;
case PIX_FMT_YUV422:
input_cmodel = BC_YUV422;
break;
case PIX_FMT_YUV422P:
input_cmodel = BC_YUV422P;
break;
case PIX_FMT_YUV410P:
input_cmodel = BC_YUV9P;
break;
default:
fprintf(stderr,
"quicktime_ffmpeg_decode: unrecognized color model %d\n",
ffmpeg->decoder_context[current_field]->pix_fmt);
input_cmodel = BC_YUV420P;
break;
}
 
if(ffmpeg->picture[current_field].data[0])
{
unsigned char **input_rows;
 
input_rows =
malloc(sizeof(unsigned char*) *
ffmpeg->decoder_context[current_field]->height);
 
 
for(i = 0; i < ffmpeg->decoder_context[current_field]->height; i++)
input_rows[i] = ffmpeg->picture[current_field].data[0] +
i *
ffmpeg->decoder_context[current_field]->width *
cmodel_calculate_pixelsize(input_cmodel);
 
 
cmodel_transfer(row_pointers, /* Leave NULL if non existent */
input_rows,
row_pointers[0], /* Leave NULL if non existent */
row_pointers[1],
row_pointers[2],
ffmpeg->picture[current_field].data[0], /* Leave NULL if non existent */
ffmpeg->picture[current_field].data[1],
ffmpeg->picture[current_field].data[2],
file->in_x, /* Dimensions to capture from input frame */
file->in_y,
file->in_w,
file->in_h,
0, /* Dimensions to project on output frame */
0,
file->out_w,
file->out_h,
input_cmodel,
file->color_model,
0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
ffmpeg->picture[current_field].linesize[0], /* For planar use the luma rowspan */
ffmpeg->width);
free(input_rows);
}
 
 
return result;
}
 
 
 
 
 
 
/branches/automake-1_1_5/hvirtual/quicktime/qtffmpeg.h
New file
0,0 → 1,85
#ifndef QTFFMPEG_H
#define QTFFMPEG_H
 
 
 
// This must be separate from qtprivate.h to keep everyone from
// depending on avcodec.h
// FFMPEG front end for quicktime.
// Getting ffmpeg to do all the things it needs to do is so labor
// intensive, we have a front end for the ffmpeg front end.
 
 
// This front end is bastardized to support alternating fields with
// alternating ffmpeg instances. It drastically reduces the bitrate
// required to store interlaced video but nothing can read it but
// Heroine Virtual.
 
 
 
#include "avcodec.h"
#include "qtprivate.h"
 
 
 
typedef struct
{
#define FIELDS 2
// Encoding
AVCodec *encoder[FIELDS];
AVCodecContext *encoder_context[FIELDS];
 
 
// Decoding
AVCodec *decoder[FIELDS];
AVCodecContext *decoder_context[FIELDS];
AVFrame picture[FIELDS];
 
// Last frame decoded
int64_t last_frame[FIELDS];
// Rounded dimensions
int width_i;
int height_i;
// Original dimensions
int width;
int height;
int fields;
 
 
// Temporary storage for color conversions
char *temp_frame;
// Storage of compressed data
unsigned char *work_buffer;
// Allocation of work_buffer
int buffer_size;
int ffmpeg_id;
} quicktime_ffmpeg_t;
 
extern int ffmpeg_initialized;
extern pthread_mutex_t ffmpeg_lock;
 
 
quicktime_ffmpeg_t* quicktime_new_ffmpeg(
int cpus,
int fields,
int ffmpeg_id,
int w,
int h,
// FFmpeg needs this for the header
quicktime_stsd_table_t *stsd_table);
void quicktime_delete_ffmpeg(quicktime_ffmpeg_t *ptr);
int quicktime_ffmpeg_decode(quicktime_ffmpeg_t *ffmpeg,
quicktime_t *file,
unsigned char **row_pointers,
int track);
 
 
 
#endif
 
 
 
 
 
 
 
/branches/automake-1_1_5/hvirtual/quicktime/qth264.c
New file
0,0 → 1,524
#include "avcodec.h"
#include "colormodels.h"
#include "funcprotos.h"
#include <pthread.h>
#include "qtffmpeg.h"
#include "quicktime.h"
#include "workarounds.h"
#include "x264.h"
 
 
 
typedef struct
{
// Encoder side
x264_t *encoder[FIELDS];
x264_picture_t *pic[FIELDS];
x264_param_t param;
 
int encode_initialized[FIELDS];
 
// Temporary storage for color conversions
char *temp_frame;
// Storage of compressed data
unsigned char *work_buffer;
// Amount of data in work_buffer
int buffer_size;
int total_fields;
// Set by flush to get the header
int header_only;
 
// Decoder side
quicktime_ffmpeg_t *decoder;
 
} quicktime_h264_codec_t;
 
static pthread_mutex_t h264_lock = PTHREAD_MUTEX_INITIALIZER;
 
 
 
 
 
 
 
 
 
 
 
 
// Direct copy routines
int quicktime_h264_is_key(unsigned char *data, long size, char *codec_id)
{
}
 
 
 
 
static int delete_codec(quicktime_video_map_t *vtrack)
{
quicktime_h264_codec_t *codec;
int i;
 
 
codec = ((quicktime_codec_t*)vtrack->codec)->priv;
for(i = 0; i < codec->total_fields; i++)
{
if(codec->encode_initialized[i])
{
pthread_mutex_lock(&h264_lock);
 
 
if(codec->pic[i])
{
x264_picture_clean(codec->pic[i]);
free(codec->pic[i]);
}
 
if(codec->encoder[i])
{
x264_encoder_close(codec->encoder[i]);
}
 
pthread_mutex_unlock(&h264_lock);
}
}
 
 
if(codec->temp_frame) free(codec->temp_frame);
if(codec->work_buffer) free(codec->work_buffer);
 
 
free(codec);
return 0;
}
 
 
 
static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
{
int64_t offset = quicktime_position(file);
quicktime_video_map_t *vtrack = &(file->vtracks[track]);
quicktime_h264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
quicktime_trak_t *trak = vtrack->track;
int width = quicktime_video_width(file, track);
int height = quicktime_video_height(file, track);
int w_16 = quicktime_quantize16(width);
int h_16 = quicktime_quantize16(height);
int i;
int result = 0;
int bytes = 0;
int is_keyframe = 0;
int current_field = vtrack->current_position % codec->total_fields;
quicktime_atom_t chunk_atom;
unsigned char header[1024];
int header_size = 0;
int got_pps = 0;
int got_sps = 0;
quicktime_avcc_t *avcc = &trak->mdia.minf.stbl.stsd.table[0].avcc;
 
 
 
 
 
 
pthread_mutex_lock(&h264_lock);
 
if(!codec->encode_initialized[current_field])
{
codec->encode_initialized[current_field] = 1;
codec->param.i_width = w_16;
codec->param.i_height = w_16;
codec->param.i_fps_num = quicktime_frame_rate_n(file, track);
codec->param.i_fps_den = quicktime_frame_rate_d(file, track);
 
x264_param_t default_params;
x264_param_default(&default_params);
// Reset quantizer if fixed bitrate
if(codec->param.rc.b_cbr)
{
codec->param.rc.i_qp_constant = default_params.rc.i_qp_constant;
codec->param.rc.i_qp_min = default_params.rc.i_qp_min;
codec->param.rc.i_qp_max = default_params.rc.i_qp_max;
}
 
 
if(file->cpus > 1)
{
codec->param.i_threads = file->cpus;
}
 
codec->encoder[current_field] = x264_encoder_open(&codec->param);
codec->pic[current_field] = calloc(1, sizeof(x264_picture_t));
x264_picture_alloc(codec->pic[current_field],
X264_CSP_I420,
codec->param.i_width,
codec->param.i_height);
}
 
 
 
 
 
 
codec->pic[current_field]->i_type = X264_TYPE_AUTO;
codec->pic[current_field]->i_qpplus1 = 0;
 
 
if(codec->header_only)
{
bzero(codec->pic[current_field]->img.plane[0], w_16 * h_16);
bzero(codec->pic[current_field]->img.plane[1], w_16 * h_16 / 4);
bzero(codec->pic[current_field]->img.plane[2], w_16 * h_16 / 4);
}
else
if(file->color_model == BC_YUV420P)
{
memcpy(codec->pic[current_field]->img.plane[0], row_pointers[0], w_16 * h_16);
memcpy(codec->pic[current_field]->img.plane[1], row_pointers[1], w_16 * h_16 / 4);
memcpy(codec->pic[current_field]->img.plane[2], row_pointers[2], w_16 * h_16 / 4);
}
else
{
cmodel_transfer(0, /* Leave NULL if non existent */
row_pointers,
codec->pic[current_field]->img.plane[0], /* Leave NULL if non existent */
codec->pic[current_field]->img.plane[1],
codec->pic[current_field]->img.plane[2],
row_pointers[0], /* Leave NULL if non existent */
row_pointers[1],
row_pointers[2],
0, /* Dimensions to capture from input frame */
0,
width,
height,
0, /* Dimensions to project on output frame */
0,
width,
height,
file->color_model,
BC_YUV420P,
0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
width, /* For planar use the luma rowspan */
codec->pic[current_field]->img.i_stride[0]);
}
 
 
 
 
 
 
 
 
 
 
 
 
x264_picture_t pic_out;
x264_nal_t *nals;
int nnal;
x264_encoder_encode(codec->encoder[current_field],
&nals,
&nnal,
codec->pic[current_field],
&pic_out);
int allocation = w_16 * h_16 * 3;
if(!codec->work_buffer)
{
codec->work_buffer = calloc(1, allocation);
}
 
codec->buffer_size = 0;
for(i = 0; i < nnal; i++)
{
int size = x264_nal_encode(codec->work_buffer + codec->buffer_size,
&allocation,
1,
nals + i);
unsigned char *ptr = codec->work_buffer + codec->buffer_size;
 
if(size > 0)
{
// Size of NAL for avc
uint64_t avc_size = size - 4;
 
// Synthesize header.
// Hopefully all the parameter set NAL's are present in the first frame.
if(!avcc->data_size)
{
if(header_size < 6)
{
header[header_size++] = 0x01;
header[header_size++] = 0x4d;
header[header_size++] = 0x40;
header[header_size++] = 0x1f;
header[header_size++] = 0xff;
header[header_size++] = 0xe1;
}
 
int nal_type = (ptr[4] & 0x1f);
// Picture parameter or sequence parameter set
if(nal_type == 0x7 && !got_sps)
{
got_sps = 1;
header[header_size++] = (avc_size & 0xff00) >> 8;
header[header_size++] = (avc_size & 0xff);
memcpy(&header[header_size],
ptr + 4,
avc_size);
header_size += avc_size;
}
else
if(nal_type == 0x8 && !got_pps)
{
got_pps = 1;
// Number of sps nal's.
header[header_size++] = 0x1;
header[header_size++] = (avc_size & 0xff00) >> 8;
header[header_size++] = (avc_size & 0xff);
memcpy(&header[header_size],
ptr + 4,
avc_size);
header_size += avc_size;
}
 
// Write header
if(got_sps && got_pps)
{
quicktime_set_avcc_header(avcc,
header,
header_size);
}
}
 
 
// Convert to avc nal
*ptr++ = (avc_size & 0xff000000) >> 24;
*ptr++ = (avc_size & 0xff0000) >> 16;
*ptr++ = (avc_size & 0xff00) >> 8;
*ptr++ = (avc_size & 0xff);
codec->buffer_size += size;
}
else
break;
}
 
pthread_mutex_unlock(&h264_lock);
 
 
 
if(!codec->header_only)
{
if(pic_out.i_type == X264_TYPE_IDR ||
pic_out.i_type == X264_TYPE_I)
{
is_keyframe = 1;
}
 
if(codec->buffer_size)
{
quicktime_write_chunk_header(file, trak, &chunk_atom);
result = !quicktime_write_data(file,
codec->work_buffer,
codec->buffer_size);
quicktime_write_chunk_footer(file,
trak,
vtrack->current_chunk,
&chunk_atom,
1);
}
 
if(is_keyframe)
{
quicktime_insert_keyframe(file,
vtrack->current_position,
track);
}
vtrack->current_chunk++;
}
return result;
}
 
 
 
 
static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
{
quicktime_video_map_t *vtrack = &(file->vtracks[track]);
quicktime_trak_t *trak = vtrack->track;
quicktime_h264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
quicktime_stsd_table_t *stsd_table = &trak->mdia.minf.stbl.stsd.table[0];
int width = trak->tkhd.track_width;
int height = trak->tkhd.track_height;
int w_16 = quicktime_quantize16(width);
int h_16 = quicktime_quantize16(height);
 
 
if(!codec->decoder) codec->decoder = quicktime_new_ffmpeg(
file->cpus,
codec->total_fields,
CODEC_ID_H264,
width,
height,
stsd_table);
 
if(codec->decoder) return quicktime_ffmpeg_decode(codec->decoder,
file,
row_pointers,
track);
 
return 1;
}
 
// Straight out of another h264 file
/*
* static int write_avcc_header(unsigned char *data)
* {
* int result = 0;
* unsigned char *ptr = data;
*
*
* static unsigned char test[] =
* {
* 0x01, 0x4d, 0x40, 0x1f, 0xff, 0xe1, 0x00, 0x14,
* 0x27, 0x4d, 0x40, 0x1f, 0xa9, 0x18, 0x0a, 0x00,
* 0xb7, 0x60, 0x0d, 0x40, 0x40, 0x40, 0x4c, 0x2b,
* 0x5e, 0xf7, 0xc0, 0x40, 0x01, 0x00, 0x04, 0x28,
* 0xce, 0x0f, 0x88
* };
*
* memcpy(data, test, sizeof(test));
* result = sizeof(test);
*
* return result;
* }
*/
 
static void flush(quicktime_t *file, int track)
{
quicktime_video_map_t *track_map = &(file->vtracks[track]);
quicktime_trak_t *trak = track_map->track;
quicktime_h264_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
quicktime_avcc_t *avcc = &trak->mdia.minf.stbl.stsd.table[0].avcc;
 
if(!avcc->data_size)
{
codec->header_only = 1;
encode(file, 0, track);
/*
* unsigned char temp[1024];
* int size = write_avcc_header(temp);
* if(size)
* quicktime_set_avcc_header(avcc,
* temp,
* size);
*/
}
/*
* trak->mdia.minf.stbl.stsd.table[0].version = 1;
* trak->mdia.minf.stbl.stsd.table[0].revision = 1;
*/
}
 
 
 
static int reads_colormodel(quicktime_t *file,
int colormodel,
int track)
{
quicktime_video_map_t *vtrack = &(file->vtracks[track]);
quicktime_codec_t *codec = (quicktime_codec_t*)vtrack->codec;
return (colormodel == BC_YUV420P);
}
 
static int writes_colormodel(quicktime_t *file,
int colormodel,
int track)
{
return (colormodel == BC_YUV420P);
}
 
static int set_parameter(quicktime_t *file,
int track,
char *key,
void *value)
{
quicktime_video_map_t *vtrack = &(file->vtracks[track]);
char *compressor = quicktime_compressor(vtrack->track);
 
if(quicktime_match_32(compressor, QUICKTIME_H264) ||
quicktime_match_32(compressor, QUICKTIME_HV64))
{
quicktime_h264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
if(!strcasecmp(key, "h264_bitrate"))
{
if(quicktime_match_32(compressor, QUICKTIME_H264))
codec->param.rc.i_bitrate = *(int*)value;
else
codec->param.rc.i_bitrate = *(int*)value / 2;
}
else
if(!strcasecmp(key, "h264_quantizer"))
{
codec->param.rc.i_qp_constant =
codec->param.rc.i_qp_min =
codec->param.rc.i_qp_max = *(int*)value;
}
else
if(!strcasecmp(key, "h264_fix_bitrate"))
codec->param.rc.b_cbr = (*(int*)value) / 1000;
}
}
 
static quicktime_h264_codec_t* init_common(quicktime_video_map_t *vtrack,
char *compressor,
char *title,
char *description)
{
quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
quicktime_h264_codec_t *codec;
 
codec_base->priv = calloc(1, sizeof(quicktime_h264_codec_t));
codec_base->delete_vcodec = delete_codec;
codec_base->decode_video = decode;
codec_base->encode_video = encode;
codec_base->flush = flush;
codec_base->reads_colormodel = reads_colormodel;
codec_base->writes_colormodel = writes_colormodel;
codec_base->set_parameter = set_parameter;
codec_base->fourcc = compressor;
codec_base->title = title;
codec_base->desc = description;
 
 
codec = (quicktime_h264_codec_t*)codec_base->priv;
x264_param_default(&codec->param);
 
 
return codec;
}
 
 
void quicktime_init_codec_h264(quicktime_video_map_t *vtrack)
{
quicktime_h264_codec_t *result = init_common(vtrack,
QUICKTIME_H264,
"H.264",
"H.264");
result->total_fields = 1;
}
 
 
// field based H.264
void quicktime_init_codec_hv64(quicktime_video_map_t *vtrack)
{
quicktime_h264_codec_t *result = init_common(vtrack,
QUICKTIME_HV64,
"Dual H.264",
"H.264 with two streams alternating every other frame. (Not standardized)");
result->total_fields = 2;
}
 
/branches/automake-1_1_5/hvirtual/quicktime/qth264.h
New file
0,0 → 1,13
#ifndef QTH264_H
#define QTH264_H
 
 
 
void quicktime_init_codec_h264(quicktime_video_map_t *vtrack);
void quicktime_init_codec_hv64(quicktime_video_map_t *vtrack);
 
 
 
 
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/bcnewfolder.h
New file
0,0 → 1,44
#ifndef BC_NEWFOLDER_H
#define BC_NEWFOLDER_H
 
 
#include "bcfilebox.inc"
#include "bcwindow.h"
#include "thread.h"
 
 
class BC_NewFolder : public BC_Window
{
public:
BC_NewFolder(int x, int y, BC_FileBox *filebox);
~BC_NewFolder();
 
int create_objects();
char* get_text();
 
private:
BC_TextBox *textbox;
};
 
class BC_NewFolderThread : public Thread
{
public:
BC_NewFolderThread(BC_FileBox *filebox);
~BC_NewFolderThread();
 
void run();
int interrupt();
int start_new_folder();
 
private:
Mutex *change_lock;
Condition *completion_lock;
BC_FileBox *filebox;
BC_NewFolder *window;
};
 
 
 
 
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/bcdelete.h
New file
0,0 → 1,48
#ifndef BCDELETE_H
#define BCDELETE_H
 
 
 
#include "bcdialog.h"
#include "bcfilebox.inc"
 
class BC_DeleteFile : public BC_Window
{
public:
BC_DeleteFile(BC_FileBox *filebox, int x, int y);
~BC_DeleteFile();
void create_objects();
BC_FileBox *filebox;
ArrayList<BC_ListBoxItem*> *data;
};
 
class BC_DeleteList : public BC_ListBox
{
public:
BC_DeleteList(BC_FileBox *filebox,
int x,
int y,
int w,
int h,
ArrayList<BC_ListBoxItem*> *data);
BC_FileBox *filebox;
};
 
class BC_DeleteThread : public BC_DialogThread
{
public:
BC_DeleteThread(BC_FileBox *filebox);
void handle_done_event(int result);
BC_Window* new_gui();
 
BC_FileBox *filebox;
};
 
 
 
 
 
 
 
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/bcbar.h
New file
0,0 → 1,25
#ifndef BCBAR_H
#define BCBAR_H
 
 
#include "bcsubwindow.h"
#include "vframe.inc"
 
class BC_Bar : public BC_SubWindow
{
public:
BC_Bar(int x, int y, int w, VFrame *data = 0);
virtual ~BC_Bar();
int initialize();
void set_image(VFrame *data);
void draw();
int reposition_window(int x, int y, int w);
int resize_event(int w, int h);
 
BC_Pixmap *image;
VFrame *data;
};
 
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/bcnewfolder.inc
New file
0,0 → 1,8
#ifndef BC_NEWFOLDER_INC
#define BC_NEWFOLDER_INC
 
 
class BC_NewFolder;
 
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/file_reload_hi.png
New file
0,0 → 1,4
‰PNG

+IHDRK‹4 pHYs  šœtIMEÕà¦ætEXtCommentCreated with The GIMPïd%n¦IDATxÚݕÍ€ „[†÷e;8ƒ¸ŠyŠ[&_,¡”r=àJšuW ²/ÍzÉP«©‘@Ÿ‡†ƒÓL(ü&Í&…˜.F䤅hIUwXz\1Öã$%ʺGEÔK qÃÜ?jÜ€¥:þŒ5­Ô^]ì›xú-Ë;Œ@d“ðÐÂÏëôv¸übíuJ·ûÓ.8q;{ôÖqg5áàÿñ…ì~4í.IEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/images/file_reload_dn.png
New file
0,0 → 1,5
‰PNG

+xºIEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/images/file_delete_hi_png.h
New file
0,0 → 1,30
#ifndef FILE_DELETE_HI_PNG_H
#define FILE_DELETE_HI_PNG_H
 
static unsigned char file_delete_hi_png[] =
{
0x00, 0x00, 0x01, 0x42,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x19, 0x08, 0x02, 0x00, 0x00, 0x00, 0x4b, 0x8b, 0x12,
0x34, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b,
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5,
0x06, 0x1d, 0x05, 0x34, 0x1c, 0x0a, 0xf4, 0x30, 0x8d, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58,
0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64,
0x25, 0x6e, 0x00, 0x00, 0x00, 0xb8, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xad, 0x55, 0x4b, 0x12,
0xc5, 0x20, 0x08, 0x33, 0x19, 0xef, 0x7f, 0x65, 0xde, 0xa2, 0x2d, 0xc3, 0xa0, 0xf2, 0xe9, 0x2b,
0xbb, 0x16, 0x09, 0x21, 0x6a, 0x84, 0x88, 0x8c, 0x27, 0x00, 0x8c, 0x66, 0xd8, 0xf2, 0x69, 0x81,
0x6c, 0xa2, 0x18, 0xb6, 0x8a, 0x29, 0x10, 0x80, 0x80, 0xaf, 0x88, 0x68, 0x96, 0x29, 0x90, 0x88,
0xd8, 0x82, 0x15, 0x57, 0xb3, 0x70, 0x33, 0x9f, 0xf8, 0xeb, 0xe7, 0xa9, 0x31, 0x00, 0x8e, 0xef,
0x82, 0x15, 0x51, 0xed, 0x2c, 0x76, 0xde, 0x12, 0x56, 0xac, 0xe0, 0xa9, 0xfd, 0x2c, 0x6e, 0x7c,
0x69, 0x59, 0xa0, 0x7d, 0xf7, 0xa0, 0xcd, 0x6d, 0xe7, 0x14, 0x7d, 0x2b, 0x02, 0xb5, 0xf8, 0x8a,
0xfa, 0xd5, 0x59, 0x07, 0xe7, 0x0b, 0x5d, 0xf2, 0x33, 0x71, 0x01, 0xfd, 0x43, 0x8d, 0x2d, 0x99,
0x62, 0xee, 0x6c, 0x99, 0x84, 0x5b, 0xe6, 0xa8, 0x31, 0xb6, 0xa4, 0xe2, 0x01, 0xde, 0xeb, 0x15,
0xd8, 0xce, 0x0a, 0xe4, 0x7e, 0x4e, 0xcb, 0x65, 0xeb, 0x27, 0x41, 0x33, 0x87, 0xde, 0xd8, 0xbb,
0x78, 0xc6, 0x9e, 0xe7, 0x04, 0x0e, 0x71, 0xeb, 0x95, 0xae, 0xa8, 0xc0, 0xdd, 0x5e, 0xa4, 0x4a,
0xbd, 0xbe, 0xe1, 0x5a, 0xcb, 0x22, 0xff, 0x8a, 0x88, 0xf8, 0xf0, 0x7d, 0xfc, 0x01, 0x7b, 0x83,
0x99, 0x35, 0x94, 0xd4, 0x0b, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42,
0x60, 0x82
};
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/file_delete_dn_png.h
New file
0,0 → 1,31
#ifndef FILE_DELETE_DN_PNG_H
#define FILE_DELETE_DN_PNG_H
 
static unsigned char file_delete_dn_png[] =
{
0x00, 0x00, 0x01, 0x51,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x19, 0x08, 0x02, 0x00, 0x00, 0x00, 0x4b, 0x8b, 0x12,
0x34, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b,
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5,
0x06, 0x1d, 0x05, 0x35, 0x19, 0x63, 0x85, 0xf5, 0x43, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58,
0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64,
0x25, 0x6e, 0x00, 0x00, 0x00, 0xc7, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xad, 0x95, 0x41, 0x12,
0xc3, 0x20, 0x08, 0x45, 0x81, 0xf1, 0xdc, 0x7f, 0xc1, 0xc5, 0xe9, 0x22, 0xad, 0xa5, 0x09, 0x82,
0x24, 0x65, 0x99, 0x0c, 0x8f, 0x27, 0x32, 0xc8, 0x66, 0x46, 0x9f, 0x60, 0x66, 0x6a, 0x86, 0x4f,
0x1f, 0x1e, 0xa4, 0xaa, 0x5d, 0x16, 0x33, 0x4f, 0x9c, 0x94, 0x20, 0x00, 0x00, 0x56, 0x2c, 0x55,
0x9d, 0xa7, 0x91, 0x12, 0xa4, 0xaa, 0xaa, 0x3a, 0x71, 0x57, 0xee, 0xc4, 0x49, 0x09, 0x9a, 0x09,
0xa5, 0x9d, 0xd0, 0xff, 0x62, 0xc9, 0xf2, 0x52, 0x5e, 0x2d, 0x11, 0x94, 0x4d, 0x90, 0xff, 0xb5,
0x2a, 0x3f, 0x76, 0xe4, 0x93, 0xfc, 0x9f, 0xf9, 0x38, 0xe4, 0x9f, 0x37, 0x0b, 0xc0, 0x08, 0x2b,
0x97, 0xf4, 0xb0, 0x09, 0x32, 0x93, 0x8f, 0xd8, 0xb4, 0x08, 0x6f, 0x40, 0x6e, 0xf4, 0xa5, 0x9e,
0x89, 0x03, 0xf4, 0x44, 0x4d, 0x5a, 0x6d, 0xca, 0xdd, 0xa5, 0x1c, 0xa8, 0xa4, 0xe5, 0x27, 0x35,
0x09, 0xe5, 0xbb, 0x03, 0x1c, 0xf7, 0x2b, 0x59, 0x3b, 0x57, 0xd0, 0xe9, 0xe3, 0xf0, 0x2e, 0xe1,
0x3e, 0x49, 0x8a, 0x9d, 0xe8, 0x8d, 0xb9, 0xcf, 0xcf, 0x08, 0xa0, 0xb1, 0x73, 0xf2, 0x15, 0x46,
0x44, 0x62, 0x66, 0xfb, 0x23, 0xba, 0xc2, 0x01, 0x30, 0xb3, 0xf7, 0xe6, 0xbf, 0xf7, 0x70, 0x78,
0xd0, 0xf7, 0x1e, 0x5b, 0x76, 0x21, 0x88, 0x88, 0xf8, 0x8f, 0xef, 0xe3, 0x0b, 0x41, 0x56, 0x99,
0x36, 0x20, 0xfd, 0x0a, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60,
0x82
};
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/file_icons_hi.png
New file
0,0 → 1,4
‰PNG

+IHDRK‹4 pHYs  šœtIMEÕ5-B1ötEXtCommentCreated with The GIMPïd%nžIDATxÚ͕ဠ„åæû¿2ýÀ3ƒK݊MùìOQÕr†ˆ”—áÓ«ù2|V@ö_—±!¨“f 6ù3ŒãÀ‚l&úµÊbTƒD˜ÑC:>iÕ)–ª‚½õªOÒøQHX݅¿ßÿ¡êºb _Ì׿YÍL¸>‚ñLÇzƒÃpÓм\+…åLû½Ï/!÷ñïãÊEx-Y>OIEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/images/file_updir_hi.png
New file
0,0 → 1,4
‰PNG

+IHDRK‹4 pHYs  šœtIMEÕ7*îcö×tEXtCommentCreated with The GIMPïd%nIDATxÚՕÁ€ DÝÿÿ—íÐdŒ#È¥=êðJ°Æí €Œ,ï$7œ‘U<Ýï5OÃЂÃrætÐ؋âht4Š£1š(ŽÆŒ£8 (,˜Äí¢Öânׇn []*YÝs¡ªè~¥|>é_ýJ|Ø{VZA¥ýJ¸ES nÑÔ„[4µ ðÿxÈ*`8œÐþgIEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/images/file_newfolder_hi.png
New file
0,0 → 1,6
‰PNG

+IHDRK‹4 pHYs  šœtIMEÕ6*÷xǖtEXtCommentCreated with The GIMPïd%n{IDATxÚí•ÁÀ C-ñÿ™–-„Ì
+~¥R…§¾dCŠ¬YȼQ|âÇýx~Q3Ë#÷IEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/images/file_delete_up.png
New file
0,0 → 1,5
‰PNG

+IHDRK‹4 pHYs  šœtIMEÕ4B|¦tEXtCommentCreated with The GIMPïd%n™IDATxÚՕQ
+À C—âý¯œ}£jm«Æúå^cŒ$¯C%×¹ŠY` IòÁ9\ Au¬qŸú¥EiiŽ@I‚ôÒ¬}ɈOž#fµ˜Ã¦ ýT…fĎ8Ùð%ÎD^Ñ,½²dSê9r<꤉)~5À¶_γc„ l?\]µéó”?¸…=n„àÕûåãðÛÿP¾nzic44ÌãŒIEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/images/file_text_hi_png.h
New file
0,0 → 1,25
#ifndef FILE_TEXT_HI_PNG_H
#define FILE_TEXT_HI_PNG_H
 
static unsigned char file_text_hi_png[] =
{
0x00, 0x00, 0x00, 0xf8,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x19, 0x08, 0x02, 0x00, 0x00, 0x00, 0x4b, 0x8b, 0x12,
0x34, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b,
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5,
0x06, 0x1d, 0x05, 0x37, 0x0f, 0xa5, 0x67, 0x22, 0x90, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58,
0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64,
0x25, 0x6e, 0x00, 0x00, 0x00, 0x6e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x95, 0xc1, 0x0e,
0xc0, 0x20, 0x08, 0x43, 0x29, 0xf1, 0xff, 0x7f, 0xb9, 0x3b, 0xb8, 0x39, 0x86, 0x17, 0x44, 0x4f,
0x0b, 0xbd, 0x19, 0xe5, 0x85, 0x1a, 0x42, 0x41, 0x52, 0x1e, 0x01, 0x90, 0x45, 0xd9, 0xf2, 0x66,
0x41, 0xf6, 0x22, 0x28, 0x5b, 0xa5, 0x3b, 0xa0, 0xde, 0xd7, 0x70, 0xa3, 0x3b, 0xa0, 0x19, 0x27,
0x24, 0x2d, 0xcb, 0x1d, 0x23, 0xac, 0xfe, 0x1e, 0xee, 0xff, 0xd2, 0x02, 0xa0, 0x72, 0x4e, 0x6d,
0x1e, 0x88, 0xbb, 0xe1, 0xf0, 0x7c, 0x0c, 0x5b, 0xe5, 0xb1, 0x3c, 0x96, 0xc7, 0x9f, 0x7a, 0xfc,
0x6c, 0xc5, 0x0d, 0x10, 0x49, 0xf5, 0x4b, 0x36, 0x0b, 0x7a, 0xb3, 0x23, 0x8d, 0xb3, 0x59, 0x81,
0x83, 0xf9, 0x78, 0x01, 0xc1, 0xe4, 0x72, 0x1d, 0x01, 0x6a, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00,
0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/bar_png.h
New file
0,0 → 1,19
#ifndef BAR_PNG_H
#define BAR_PNG_H
 
static unsigned char bar_png[] =
{
0x00, 0x00, 0x00, 0x97,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x00, 0x00, 0x00, 0x99, 0xb0, 0x31,
0xe1, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b,
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5,
0x07, 0x08, 0x05, 0x0a, 0x28, 0x30, 0x22, 0x51, 0x58, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58,
0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64,
0x25, 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x18, 0x05,
0x03, 0x0a, 0x00, 0x01, 0x81, 0x00, 0x01, 0xec, 0x9d, 0x39, 0x65, 0x00, 0x00, 0x00, 0x00, 0x49,
0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/file_reload_up_png.h
New file
0,0 → 1,26
#ifndef FILE_RELOAD_UP_PNG_H
#define FILE_RELOAD_UP_PNG_H
 
static unsigned char file_reload_up_png[] =
{
0x00, 0x00, 0x01, 0x10,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x19, 0x08, 0x02, 0x00, 0x00, 0x00, 0x4b, 0x8b, 0x12,
0x34, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b,
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5,
0x06, 0x1d, 0x06, 0x1f, 0x0e, 0x8d, 0x7b, 0x02, 0xf5, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58,
0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64,
0x25, 0x6e, 0x00, 0x00, 0x00, 0x86, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x55, 0x41, 0x0e,
0xc0, 0x20, 0x08, 0xa3, 0xc4, 0xff, 0x7f, 0xd9, 0x1d, 0x76, 0xc3, 0x16, 0x98, 0x31, 0x59, 0xb2,
0x8c, 0x9b, 0x08, 0x05, 0xa9, 0x55, 0xcc, 0x39, 0xed, 0x90, 0xb9, 0x9d, 0xb3, 0xf7, 0xb0, 0x00,
0x00, 0x50, 0xbb, 0xa3, 0x8f, 0x62, 0x66, 0xf9, 0x70, 0x47, 0x13, 0xa8, 0x43, 0x51, 0x1d, 0x44,
0x0f, 0x45, 0xb3, 0xea, 0x79, 0xd1, 0x34, 0x5a, 0x00, 0x2a, 0x34, 0xf8, 0xd7, 0x79, 0xad, 0x31,
0xae, 0x6a, 0x86, 0xca, 0x77, 0x5a, 0x70, 0x86, 0xa5, 0xab, 0xe6, 0xd7, 0x7e, 0x29, 0x9c, 0xe4,
0x31, 0x01, 0xca, 0xfd, 0xf2, 0x8c, 0xdb, 0x0a, 0xfd, 0x86, 0x1e, 0x1f, 0x60, 0x95, 0x4c, 0xe5,
0x77, 0xd5, 0xfb, 0xa1, 0x25, 0xdd, 0x28, 0x25, 0x42, 0x05, 0x40, 0xe9, 0x96, 0xda, 0xce, 0x5b,
0xe3, 0x1d, 0x6c, 0xbc, 0x13, 0xb2, 0xfc, 0xff, 0x77, 0x3c, 0xb2, 0x0b, 0x1b, 0x95, 0x4e, 0x2c,
0xf3, 0xad, 0xf1, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/file_delete_hi.png
New file
0,0 → 1,6
‰PNG

+IHDRK‹4 pHYs  šœtIMEÕ4
+ô0tEXtCommentCreated with The GIMPïd%n¸IDATxÚ­UKÅ 3ïeÞ¢-àòé+» !j„ˆŒ'ŒfØòil¢¶Š)€€¯ˆh–)ˆØ‚W³p3Ÿøëç©1Žï‚Qí,vÞV¬à©ý,n|iY }÷ Ímç}+µøŠúÕYç ]ò3qýC-™bîl™„[æ¨1¶¤âÞëØÎ
+ä~NËeë'A3‡ÞØ»xƞçq땮¨ÀÝ^¤J½¾áZË"ÿŠˆøð}ü{ƒ™5”Ô èIEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/images/file_delete_dn.png
New file
0,0 → 1,5
‰PNG

+IHDRK‹4 pHYs  šœtIMEÕ5c…õCtEXtCommentCreated with The GIMPïd%nÇIDATxÚ­•Aà EñÜÁÅé"­¥ ‚$e™ '2ÈfFŸ`fj†O¤ª]3Oœ” V,U§‘¤ªª:qWîÄI š ¥ÐÿbÉòR^-”Mÿµ*?vä“üŸù8äŸ7 À+—ô° 2“Ø´o@nô¥ž‰ôDMZmÊÝ¥¨¤å'5 å»÷+Y;WÐéãð.á>IŠè¹ÏÏ ±sòFDbfû#ºÂ0³÷æ¿÷pxÐ÷[v!ˆˆøïã AV™6 ý
+ÍIEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/images/file_reload_hi_png.h
New file
0,0 → 1,28
#ifndef FILE_RELOAD_HI_PNG_H
#define FILE_RELOAD_HI_PNG_H
 
static unsigned char file_reload_hi_png[] =
{
0x00, 0x00, 0x01, 0x30,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x19, 0x08, 0x02, 0x00, 0x00, 0x00, 0x4b, 0x8b, 0x12,
0x34, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b,
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5,
0x06, 0x1d, 0x06, 0x1f, 0x1b, 0xe0, 0xa6, 0xe6, 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58,
0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64,
0x25, 0x6e, 0x00, 0x00, 0x00, 0xa6, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xdd, 0x95, 0xcd, 0x12,
0x80, 0x20, 0x08, 0x84, 0x5b, 0x86, 0xf7, 0x7f, 0x65, 0x3b, 0x38, 0x19, 0x83, 0xb8, 0x8a, 0x79,
0x8a, 0x5b, 0x26, 0x5f, 0x2c, 0x7f, 0xa1, 0x94, 0x72, 0x3d, 0x06, 0xe0, 0x4a, 0x9a, 0x75, 0x57,
0x0b, 0xb2, 0x2f, 0x16, 0xcd, 0x7a, 0xc9, 0x17, 0x50, 0x8d, 0xab, 0xa9, 0x91, 0x14, 0x08, 0x40,
0x9f, 0x87, 0x86, 0x83, 0xd3, 0x4c, 0x28, 0xfc, 0x26, 0x00, 0xcd, 0x26, 0x85, 0x98, 0x2e, 0x46,
0xe4, 0xa4, 0x85, 0x68, 0x49, 0x55, 0x9d, 0x77, 0x8f, 0x90, 0x58, 0x7a, 0x5c, 0x31, 0xd6, 0xe3,
0x24, 0x25, 0xca, 0x1d, 0xba, 0x47, 0x19, 0x45, 0xd4, 0x4b, 0x0b, 0x71, 0xc3, 0xdc, 0x13, 0x10,
0x3f, 0x1f, 0x6a, 0xdc, 0x1b, 0x80, 0xa5, 0x3a, 0xfe, 0x8c, 0x35, 0xad, 0xd4, 0x81, 0x5e, 0x5d,
0xec, 0x9b, 0x78, 0xfa, 0x2d, 0xcb, 0x3b, 0x8c, 0x40, 0x64, 0x93, 0xf0, 0xd0, 0xc2, 0xcf, 0xeb,
0xf4, 0x76, 0xb8, 0xfc, 0x62, 0xed, 0x75, 0x4a, 0xb7, 0xfb, 0xd3, 0x2e, 0x38, 0x71, 0x3b, 0x7b,
0x1b, 0xf4, 0xd6, 0x71, 0x1b, 0x67, 0x35, 0xe1, 0xe0, 0xff, 0xf1, 0x06, 0x85, 0xec, 0x7e, 0x34,
0xed, 0x07, 0x2e, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/file_reload_dn_png.h
New file
0,0 → 1,29
#ifndef FILE_RELOAD_DN_PNG_H
#define FILE_RELOAD_DN_PNG_H
 
static unsigned char file_reload_dn_png[] =
{
0x00, 0x00, 0x01, 0x3d,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x19, 0x08, 0x02, 0x00, 0x00, 0x00, 0x4b, 0x8b, 0x12,
0x34, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b,
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5,
0x06, 0x1d, 0x06, 0x1f, 0x21, 0x26, 0xaa, 0x3f, 0xac, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58,
0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64,
0x25, 0x6e, 0x00, 0x00, 0x00, 0xb3, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xdd, 0x95, 0x31, 0x16,
0xc4, 0x20, 0x08, 0x44, 0x85, 0xe7, 0xb9, 0xa7, 0xe0, 0xe2, 0xa4, 0x48, 0xd6, 0xe5, 0x19, 0x21,
0xe0, 0xa6, 0x5a, 0x3a, 0x8d, 0xf9, 0x32, 0x82, 0x23, 0xa9, 0x6a, 0xfb, 0x04, 0x11, 0xb5, 0x62,
0xd8, 0xdf, 0xbb, 0x05, 0x89, 0x48, 0x95, 0x45, 0x44, 0x03, 0xc7, 0xbf, 0x80, 0x5a, 0x6b, 0x22,
0x32, 0xd4, 0x70, 0x09, 0x04, 0x00, 0x80, 0x87, 0xa3, 0x73, 0x90, 0xa1, 0xc4, 0x2b, 0x01, 0xf4,
0x64, 0x3a, 0x99, 0xfd, 0x7a, 0x32, 0xa3, 0x49, 0xda, 0x12, 0xcd, 0x99, 0xd3, 0xf5, 0x36, 0x48,
0xb1, 0xbc, 0x2c, 0xc4, 0xc4, 0x1d, 0xc7, 0x25, 0x51, 0xd3, 0xe4, 0x34, 0x64, 0x2f, 0xa3, 0xbb,
0xb4, 0x25, 0xce, 0x3d, 0xfb, 0x00, 0x14, 0xcf, 0xbb, 0x1a, 0xf7, 0x2e, 0x40, 0xaa, 0x8e, 0x7f,
0xc6, 0x7a, 0xac, 0xd4, 0x0b, 0xbd, 0x9a, 0xec, 0x9b, 0xb5, 0x4f, 0x58, 0xd6, 0xf4, 0xd5, 0x03,
0x01, 0xa0, 0xd2, 0x8d, 0x0b, 0xfa, 0x26, 0xf2, 0x9c, 0xb1, 0x7a, 0x69, 0x7e, 0x6b, 0xbf, 0x56,
0xd5, 0x6d, 0x83, 0xb6, 0x49, 0xa9, 0x2a, 0x9f, 0x6f, 0x49, 0xa6, 0x76, 0x31, 0xe8, 0x5b, 0xc7,
0x6d, 0xdc, 0x00, 0x5d, 0x1a, 0xdf, 0x7a, 0x1f, 0x0f, 0x7d, 0xe2, 0x7f, 0xab, 0x05, 0x0d, 0x78,
0xba, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/file_icons_hi_png.h
New file
0,0 → 1,28
#ifndef FILE_ICONS_HI_PNG_H
#define FILE_ICONS_HI_PNG_H
 
static unsigned char file_icons_hi_png[] =
{
0x00, 0x00, 0x01, 0x28,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x19, 0x08, 0x02, 0x00, 0x00, 0x00, 0x4b, 0x8b, 0x12,
0x34, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b,
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5,
0x06, 0x1d, 0x05, 0x35, 0x2d, 0x42, 0x31, 0x01, 0xf6, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58,
0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64,
0x25, 0x6e, 0x00, 0x00, 0x00, 0x9e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xcd, 0x95, 0xe1, 0x0e,
0x80, 0x20, 0x08, 0x84, 0xe5, 0xe6, 0xfb, 0xbf, 0x32, 0xfd, 0xc0, 0x1a, 0x33, 0x83, 0x4b, 0xdd,
0x8a, 0x7f, 0x4d, 0xf9, 0xec, 0x00, 0x4f, 0x51, 0xd5, 0x72, 0x86, 0x88, 0x94, 0x97, 0xe1, 0xd3,
0xab, 0x07, 0xf9, 0x05, 0x32, 0x7c, 0x16, 0x56, 0x40, 0xf6, 0x5f, 0x97, 0x1a, 0xb1, 0x8f, 0x21,
0xa8, 0x93, 0x1c, 0x1c, 0x66, 0x04, 0x09, 0x36, 0xf9, 0x33, 0x8c, 0x1b, 0xe3, 0xc0, 0x14, 0x82,
0x6c, 0x0e, 0x26, 0xfa, 0xb5, 0xca, 0x62, 0x02, 0x54, 0x83, 0x44, 0x98, 0xd1, 0x43, 0x3a, 0x3e,
0x69, 0xd5, 0x29, 0x96, 0xaa, 0x1a, 0x82, 0x1c, 0xbd, 0x9d, 0xf5, 0xaa, 0x4f, 0xd2, 0xf8, 0x51,
0x48, 0x58, 0xdd, 0x85, 0xbf, 0xdf, 0xff, 0xa1, 0xea, 0xba, 0x62, 0x0c, 0x5f, 0xcc, 0xd7, 0xbf,
0x59, 0xcd, 0x4c, 0xb8, 0x3e, 0x82, 0xf1, 0x4c, 0x12, 0xc7, 0x7a, 0x0e, 0x83, 0xc3, 0x70, 0xd3,
0xd0, 0xbc, 0x02, 0x5c, 0x2b, 0x85, 0xe5, 0x4c, 0xfb, 0xbd, 0xcf, 0x05, 0x2f, 0x21, 0xf7, 0xf1,
0x8d, 0xef, 0xe3, 0x01, 0xca, 0x45, 0x78, 0x2d, 0x59, 0x3e, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/file_text_hi.png
New file
0,0 → 1,5
‰PNG

+IõK6 z³#³YƒùxÁärjxxIEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/images/bar.png
New file
0,0 → 1,7
‰PNG

+IHDR€™°1á pHYs  šœtIMEÕ
+IDATxÚc`
+ì9eIEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/images/file_reload_up.png
New file
0,0 → 1,5
‰PNG

+IHDRK‹4 pHYs  šœtIMEՍ{õtEXtCommentCreated with The GIMPïd%n†IDATxÚíUAÀ £ÄÿÙvØ1Y²Œ›©UÌ9퐹³÷°P»£bfùpG¨CQDE³êyÑ4Z*4ø×y­1®j†ÊwZp†¥«æ×~)œä1ÊýòŒÛ
+ý†`•LåwÕû¡%Ý(%B@é–ÚÎ[ãl¼²üÿw<² •N,ó­ñIEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/images/file_updir_hi_png.h
New file
0,0 → 1,27
#ifndef FILE_UPDIR_HI_PNG_H
#define FILE_UPDIR_HI_PNG_H
 
static unsigned char file_updir_hi_png[] =
{
0x00, 0x00, 0x01, 0x19,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x19, 0x08, 0x02, 0x00, 0x00, 0x00, 0x4b, 0x8b, 0x12,
0x34, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b,
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5,
0x06, 0x1d, 0x05, 0x37, 0x2a, 0xee, 0x63, 0xf6, 0xd7, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58,
0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64,
0x25, 0x6e, 0x00, 0x00, 0x00, 0x8f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xd5, 0x95, 0xc1, 0x12,
0x80, 0x20, 0x08, 0x44, 0xdd, 0x1d, 0xff, 0xff, 0x97, 0xed, 0xd0, 0x64, 0x8c, 0x23, 0x04, 0xc8,
0xa5, 0x3d, 0xea, 0xf0, 0x4a, 0xb0, 0x17, 0xc6, 0x18, 0xed, 0x09, 0x80, 0x16, 0x8c, 0x2c, 0xef,
0x12, 0x24, 0x37, 0x9c, 0x91, 0x55, 0x3c, 0x01, 0xdd, 0xef, 0x35, 0x4f, 0xc3, 0x13, 0xd0, 0x82,
0xc3, 0x72, 0xe6, 0x74, 0x00, 0xd0, 0xd8, 0x8b, 0xe2, 0x68, 0x74, 0x34, 0x8a, 0xa3, 0x31, 0x9a,
0x28, 0x8e, 0xc6, 0x8c, 0xa3, 0x38, 0x1a, 0xa0, 0x28, 0xee, 0x9d, 0xa3, 0x2c, 0x98, 0xc4, 0xed,
0xa2, 0xd6, 0xe2, 0x6e, 0xd7, 0x87, 0x6e, 0x0c, 0x5b, 0x5d, 0x2a, 0x59, 0xdd, 0x73, 0xa1, 0x9d,
0xaa, 0xe8, 0x7e, 0xa5, 0x7c, 0x3e, 0xe9, 0x5f, 0xfd, 0x4a, 0x7c, 0xd8, 0x7b, 0x56, 0x5a, 0x41,
0xa5, 0xfd, 0x4a, 0xb8, 0x45, 0x53, 0x0b, 0x13, 0x6e, 0xd1, 0xd4, 0xc2, 0x84, 0x5b, 0x34, 0xb5,
0xa0, 0xf0, 0xff, 0x78, 0x01, 0xc8, 0x2a, 0x60, 0x38, 0x9c, 0xd0, 0xfe, 0x67, 0x00, 0x00, 0x00,
0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/file_newfolder_hi_png.h
New file
0,0 → 1,26
#ifndef FILE_NEWFOLDER_HI_PNG_H
#define FILE_NEWFOLDER_HI_PNG_H
 
static unsigned char file_newfolder_hi_png[] =
{
0x00, 0x00, 0x01, 0x05,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x19, 0x08, 0x02, 0x00, 0x00, 0x00, 0x4b, 0x8b, 0x12,
0x34, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b,
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5,
0x06, 0x1d, 0x05, 0x36, 0x2a, 0xf7, 0x78, 0xc7, 0x96, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58,
0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64,
0x25, 0x6e, 0x00, 0x00, 0x00, 0x7b, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x95, 0xc1, 0x0e,
0xc0, 0x20, 0x08, 0x43, 0x2d, 0xf1, 0xff, 0x7f, 0x99, 0x1d, 0x96, 0x2d, 0x84, 0xcc, 0x0a, 0x32,
0x6f, 0xf6, 0x6a, 0x7c, 0x42, 0x25, 0x05, 0xaa, 0xda, 0x1e, 0x01, 0x68, 0x49, 0xd9, 0xeb, 0xdd,
0x82, 0xec, 0x41, 0x50, 0xf6, 0x96, 0x54, 0x40, 0x77, 0x5d, 0x6f, 0x37, 0x52, 0x01, 0x39, 0x1c,
0x5c, 0xcf, 0xce, 0xb5, 0xf8, 0x1b, 0x00, 0x3a, 0xe9, 0x3f, 0x5b, 0xb2, 0x10, 0x90, 0xb3, 0x63,
0xaa, 0xf9, 0x3f, 0x72, 0xdc, 0xf7, 0x4c, 0x04, 0x87, 0x68, 0xe4, 0xac, 0xef, 0xb1, 0xa8, 0xc3,
0x3a, 0xac, 0x9d, 0xac, 0x4e, 0xe6, 0x78, 0x9d, 0x55, 0x89, 0xb0, 0x0d, 0x7e, 0xa5, 0x52, 0x85,
0xa7, 0xbe, 0x64, 0x43, 0x8a, 0xac, 0x0f, 0x59, 0xc8, 0xbc, 0x51, 0x7c, 0xe2, 0xc7, 0xfd, 0x78,
0x01, 0x08, 0x7e, 0x51, 0x33, 0xcb, 0x23, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e,
0x44, 0xae, 0x42, 0x60, 0x82
};
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/file_delete_up_png.h
New file
0,0 → 1,28
#ifndef FILE_DELETE_UP_PNG_H
#define FILE_DELETE_UP_PNG_H
 
static unsigned char file_delete_up_png[] =
{
0x00, 0x00, 0x01, 0x23,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x19, 0x08, 0x02, 0x00, 0x00, 0x00, 0x4b, 0x8b, 0x12,
0x34, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b,
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5,
0x06, 0x1d, 0x05, 0x34, 0x10, 0x03, 0x42, 0x7c, 0xa6, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58,
0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64,
0x25, 0x6e, 0x00, 0x00, 0x00, 0x99, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xd5, 0x95, 0x51, 0x0a,
0xc0, 0x20, 0x0c, 0x43, 0x97, 0xe2, 0xfd, 0xaf, 0x9c, 0x7d, 0x08, 0xa3, 0x6a, 0x6d, 0xab, 0x13,
0xc6, 0xfa, 0xe5, 0x14, 0x5e, 0x63, 0x8c, 0x0e, 0x24, 0xaf, 0x43, 0x25, 0xd7, 0xb9, 0x8a, 0x59,
0x00, 0x00, 0x1c, 0x60, 0x01, 0x20, 0x49, 0xf2, 0xc1, 0x39, 0x5c, 0x09, 0x41, 0x75, 0xac, 0x71,
0x9f, 0xfa, 0xa5, 0x45, 0x69, 0x69, 0x8e, 0x40, 0x49, 0x82, 0xf4, 0xd2, 0xac, 0x7d, 0xc9, 0x88,
0x4f, 0x9e, 0x23, 0x0e, 0x66, 0xb5, 0x98, 0x9d, 0xc3, 0x06, 0xa6, 0x09, 0xfd, 0x54, 0x85, 0x66,
0xc4, 0x8e, 0x38, 0xd9, 0xf0, 0x25, 0xce, 0x44, 0x5e, 0xd1, 0x2c, 0xbd, 0xb2, 0x64, 0x53, 0xea,
0x0e, 0x39, 0x81, 0x72, 0x3c, 0xea, 0xa4, 0x89, 0x29, 0x7e, 0x35, 0xc0, 0xb6, 0x5f, 0xce, 0xb3,
0x63, 0x84, 0xa0, 0x9d, 0x6c, 0x3f, 0x06, 0x5c, 0x5d, 0x9d, 0xb5, 0xe9, 0xf3, 0x94, 0x3f, 0xb8,
0x85, 0x3d, 0x6e, 0x84, 0xe0, 0xd5, 0xfb, 0xe5, 0xe3, 0xf0, 0xdb, 0xff, 0x50, 0xbe, 0x6e, 0x7a,
0x69, 0x63, 0x34, 0x34, 0xcc, 0xe3, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae,
0x42, 0x60, 0x82
};
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/images/filebox.xcf.bz2
New file
0,0 → 1,11
BZh91AY&SY„ ™ÿÿÿÿæmcÿ…¦}"?ïþàòÀA° @
+C€Ð €24H”Ñ&&˜jbOM Èщ  Ð@КÐӈ›†$\Œ˜ÙO–XNè¡2eSt2ë¾zýöXߜòUëH H‚)HÜàu©Ôc³ºp¾%M£" ZäCw[Vå 1ø Ñ|§E
+.ñPƆ‘2t4ˆd½@œ„3àgÄ4LÄ3åò^çV—ŽWÊ\/)BЈJçФW p¼)A4ð.þUVüÀnþ¡wñ²ï6ªøvybìn”ؐ!”KTÄ5¦U6¥`,)ގ
+‰•$™/†ÏoeÖs¦éíÚªV÷0·è÷åΐ‘@7a´µmËǑ``LÝEZAuPS^Œhe2xD
+ CȇiTVÞS„š$©RaaN‰’Ë S”Ë,PÉ#—,¥ p$¾#²<a5BÌ-Šp¸.^qZ‡*Ö¡ §Šâ‰«¡uÙ©I Å¸él`Àׁ$¡Ó)‰†tF·DzBŸ}[P&q è&‚H?@‘ü )p’ÚŒ§3Æ ¼11 †C#).Pˆé®œŒ¨Dq¡C@ ¥&MÚä,
+†ÐÄP†`\!R!ICHJ.•dm±̶äd×U$‚HÃU‰ ›ÀH*8/á„ÚcÔ5«žr 5Ï°ѨKPüäÛÅJœ|ÍQ­Ëæpq\°ë×0š£lzX ›€¸²I<,-ºQ‰r˜ŒÓ;=*µÀÖ5Ê¥\Ȝ©‚§˜¹OG`Žþìõ¦ÃÚUu1Å=Â1!–$@ X 1Nž_›n_4A4°×X Y~ð ႎD‡¥€À¢‡˜>‹3à¿t# ‚ö6dØI¨ÊÁTRÊ
+k†ÀËà«â&l‹Ä´×_!\¹p  ¶=±4Å; )µdÀ«¬ƒi’ÓBËÛԁuŦ,±OK8КGGG“yÈϑŒám€Ó û³{'8¦hc
+"Ð@ˆ’V*ÖXéÝÄÇ'¢‰îÊQ=— $iFDÊ~
+®g
+W¨«RuŠÀ1®¡¤”èè)еÿ5Óþ.äŠp¡!42
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/guicast/bcnewfolder.C
New file
0,0 → 1,143
#include "condition.h"
#include "bcfilebox.h"
#include "bcnewfolder.h"
#include "bctitle.h"
#include "filesystem.h"
#include "language.h"
 
#include <sys/stat.h>
 
 
 
 
 
 
 
BC_NewFolder::BC_NewFolder(int x, int y, BC_FileBox *filebox)
: BC_Window(filebox->get_newfolder_title(),
x,
y,
320,
120,
0,
0,
0,
0,
1)
{
}
 
BC_NewFolder::~BC_NewFolder()
{
}
 
 
int BC_NewFolder::create_objects()
{
int x = 10, y = 10;
add_tool(new BC_Title(x, y, _("Enter the name of the folder:")));
y += 20;
add_subwindow(textbox = new BC_TextBox(x, y, 300, 1, _("Untitled")));
y += 30;
add_subwindow(new BC_OKButton(this));
x = get_w() - 100;
add_subwindow(new BC_CancelButton(this));
show_window();
return 0;
}
 
char* BC_NewFolder::get_text()
{
return textbox->get_text();
}
 
 
BC_NewFolderThread::BC_NewFolderThread(BC_FileBox *filebox)
: Thread(0, 0, 0)
{
this->filebox = filebox;
window = 0;
change_lock = new Mutex("BC_NewFolderThread::change_lock");
completion_lock = new Condition(1, "BC_NewFolderThread::completion_lock");
}
 
BC_NewFolderThread::~BC_NewFolderThread()
{
interrupt();
delete change_lock;
delete completion_lock;
}
 
void BC_NewFolderThread::run()
{
int x = filebox->get_abs_cursor_x(1);
int y = filebox->get_abs_cursor_y(1);
change_lock->lock("BC_NewFolderThread::run 1");
window = new BC_NewFolder(x,
y,
filebox);
window->create_objects();
change_lock->unlock();
 
 
int result = window->run_window();
 
if(!result)
{
char new_folder[BCTEXTLEN];
filebox->fs->join_names(new_folder, filebox->fs->get_current_dir(), window->get_text());
mkdir(new_folder, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
filebox->lock_window("BC_NewFolderThread::run");
filebox->refresh();
filebox->unlock_window();
}
 
change_lock->lock("BC_NewFolderThread::run 2");
delete window;
window = 0;
change_lock->unlock();
 
completion_lock->unlock();
}
 
int BC_NewFolderThread::interrupt()
{
change_lock->lock("BC_NewFolderThread::interrupt");
if(window)
{
window->lock_window("BC_NewFolderThread::interrupt");
window->set_done(1);
window->unlock_window();
}
 
change_lock->unlock();
 
completion_lock->lock("BC_NewFolderThread::interrupt");
completion_lock->unlock();
return 0;
}
 
int BC_NewFolderThread::start_new_folder()
{
change_lock->lock();
 
if(window)
{
window->lock_window("BC_NewFolderThread::start_new_folder");
window->raise_window();
window->unlock_window();
change_lock->unlock();
}
else
{
change_lock->unlock();
completion_lock->lock("BC_NewFolderThread::start_new_folder");
 
Thread::start();
}
 
 
return 0;
}
 
 
/branches/automake-1_1_5/hvirtual/guicast/bcdelete.inc
New file
0,0 → 1,8
#ifndef BCDELETE_INC
#define BCDELETE_INC
 
 
class BC_DeleteThread;
 
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/bcbar.inc
New file
0,0 → 1,7
#ifndef BCBAR_INC
#define BCBAR_INC
 
 
class BC_Bar;
 
#endif
/branches/automake-1_1_5/hvirtual/guicast/bcdelete.C
New file
0,0 → 1,121
#include "bcdelete.h"
#include "bcsignals.h"
#include "filesystem.h"
#include "language.h"
 
 
 
 
 
BC_DeleteFile::BC_DeleteFile(BC_FileBox *filebox, int x, int y)
: BC_Window(filebox->get_delete_title(),
x,
y,
320,
480,
0,
0,
0,
0,
1)
{
this->filebox = filebox;
data = 0;
}
 
BC_DeleteFile::~BC_DeleteFile()
{
delete data;
}
 
void BC_DeleteFile::create_objects()
{
int x = 10, y = 10;
data = new ArrayList<BC_ListBoxItem*>;
int i = 1;
char *path;
FileSystem fs;
 
while((path = filebox->get_path(i)))
{
data->append(new BC_ListBoxItem(path));
i++;
}
BC_Title *title;
add_subwindow(title = new BC_Title(x, y, _("Really delete the following files?")));
y += title->get_h() + 5;
BC_DeleteList *list;
add_subwindow(list = new BC_DeleteList(filebox,
x,
y,
get_w() - x * 2,
get_h() - y - BC_OKButton::calculate_h() - 20,
data));
y += list->get_h() + 5;
add_subwindow(new BC_OKButton(this));
add_subwindow(new BC_CancelButton(this));
show_window();
}
 
 
 
 
 
BC_DeleteList::BC_DeleteList(BC_FileBox *filebox,
int x,
int y,
int w,
int h,
ArrayList<BC_ListBoxItem*> *data)
: BC_ListBox(x,
y,
w,
h,
LISTBOX_TEXT,
data)
{
this->filebox = filebox;
}
 
 
 
 
 
 
 
 
 
 
BC_DeleteThread::BC_DeleteThread(BC_FileBox *filebox)
: BC_DialogThread()
{
this->filebox = filebox;
}
 
void BC_DeleteThread::handle_done_event(int result)
{
if(!result)
{
filebox->lock_window("BC_DeleteThread::handle_done_event");
filebox->delete_files();
filebox->unlock_window();
}
}
 
BC_Window* BC_DeleteThread::new_gui()
{
int x = filebox->get_abs_cursor_x(1);
int y = filebox->get_abs_cursor_y(1);
BC_DeleteFile *result = new BC_DeleteFile(filebox, x, y);
result->create_objects();
return result;
}
 
 
 
 
 
 
 
 
/branches/automake-1_1_5/hvirtual/guicast/bcbar.C
New file
0,0 → 1,61
#include "bcbar.h"
#include "bcpixmap.h"
#include "bcresources.h"
#include "vframe.h"
 
 
 
 
BC_Bar::BC_Bar(int x, int y, int w, VFrame *data)
: BC_SubWindow(x, y, w, 0, -1)
{
this->data = data;
image = 0;
}
 
BC_Bar::~BC_Bar()
{
delete image;
}
 
int BC_Bar::initialize()
{
if(data)
set_image(data);
else
set_image(get_resources()->bar_data);
 
// Create the subwindow
BC_SubWindow::initialize();
 
draw();
return 0;
}
 
void BC_Bar::set_image(VFrame *data)
{
delete image;
image = new BC_Pixmap(parent_window, data, PIXMAP_ALPHA);
h = image->get_h();
}
 
int BC_Bar::reposition_window(int x, int y, int w)
{
BC_WindowBase::reposition_window(x, y, w, -1);
draw();
return 0;
}
 
int BC_Bar::resize_event(int w, int h)
{
reposition_window(x, y, get_w());
return 1;
}
 
 
void BC_Bar::draw()
{
draw_top_background(parent_window, 0, 0,w, h);
draw_3segmenth(0, 0, w, 0, w, image);
flash();
}
/branches/automake-1_1_5/hvirtual/libmpeg3/mpeg3bits.c
New file
0,0 → 1,177
#include "mpeg3private.h"
#include "mpeg3protos.h"
 
#include <stdlib.h>
 
mpeg3_bits_t* mpeg3bits_new_stream(mpeg3_t *file, mpeg3_demuxer_t *demuxer)
{
mpeg3_bits_t *stream = malloc(sizeof(mpeg3_bits_t));
stream->bfr = 0;
stream->bfr_size = 0;
stream->bit_number = 0;
stream->file = file;
stream->demuxer = demuxer;
stream->input_ptr = 0;
return stream;
}
 
int mpeg3bits_delete_stream(mpeg3_bits_t* stream)
{
free(stream);
return 0;
}
 
 
/* Fill a buffer. Only works if bit_number is on an 8 bit boundary */
int mpeg3bits_read_buffer(mpeg3_bits_t* stream, unsigned char *buffer, int bytes)
{
int result, i = 0;
while(stream->bit_number > 0)
{
stream->bit_number -= 8;
mpeg3demux_read_prev_char(stream->demuxer);
}
 
stream->bit_number = 0;
stream->bfr_size = 0;
stream->bfr = 0;
result = mpeg3demux_read_data(stream->demuxer, buffer, bytes);
return result;
}
 
/* For mp3 decompression use a pointer in a buffer for getbits. */
int mpeg3bits_use_ptr(mpeg3_bits_t* stream, unsigned char *buffer)
{
stream->bfr_size = stream->bit_number = 0;
stream->bfr = 0;
stream->input_ptr = buffer;
return 0;
}
 
/* Go back to using the demuxer for getbits in mp3. */
int mpeg3bits_use_demuxer(mpeg3_bits_t* stream)
{
if(stream->input_ptr)
{
stream->bfr_size = stream->bit_number = 0;
stream->input_ptr = 0;
stream->bfr = 0;
}
 
return 0;
}
 
/* Reconfigure for reverse operation */
/* Default is forward operation */
void mpeg3bits_start_reverse(mpeg3_bits_t* stream)
{
int i;
for(i = 0; i < stream->bfr_size; i += 8)
{
if(stream->input_ptr)
stream->input_ptr--;
else
mpeg3demux_read_prev_char(stream->demuxer);
}
}
 
/* Reconfigure for forward operation */
void mpeg3bits_start_forward(mpeg3_bits_t* stream)
{
int i;
 
// If already at the bof, the buffer is already invalid.
if(stream->demuxer && mpeg3bits_bof(stream))
{
stream->bfr_size = 0;
stream->bit_number = 0;
stream->bfr = 0;
stream->input_ptr = 0;
mpeg3demux_read_char(stream->demuxer);
}
else
for(i = 0; i < stream->bfr_size; i += 8)
{
if(stream->input_ptr)
stream->input_ptr++;
else
mpeg3demux_read_char(stream->demuxer);
}
}
 
/* Erase the buffer with the next 4 bytes in the file. */
int mpeg3bits_refill(mpeg3_bits_t* stream)
{
stream->bit_number = 32;
stream->bfr_size = 32;
 
if(stream->input_ptr)
{
stream->bfr = (unsigned int)(*stream->input_ptr++) << 24;
stream->bfr |= (unsigned int)(*stream->input_ptr++) << 16;
stream->bfr |= (unsigned int)(*stream->input_ptr++) << 8;
stream->bfr |= *stream->input_ptr++;
}
else
{
stream->bfr = mpeg3demux_read_char(stream->demuxer) << 24;
stream->bfr |= mpeg3demux_read_char(stream->demuxer) << 16;
stream->bfr |= mpeg3demux_read_char(stream->demuxer) << 8;
stream->bfr |= mpeg3demux_read_char(stream->demuxer);
}
return mpeg3demux_eof(stream->demuxer);
}
 
/* Erase the buffer with the previous 4 bytes in the file. */
int mpeg3bits_refill_backwards(mpeg3_bits_t* stream)
{
stream->bit_number = 0;
stream->bfr_size = 32;
stream->bfr = mpeg3demux_read_prev_char(stream->demuxer);
stream->bfr |= (unsigned int)mpeg3demux_read_prev_char(stream->demuxer) << 8;
stream->bfr |= (unsigned int)mpeg3demux_read_prev_char(stream->demuxer) << 16;
stream->bfr |= (unsigned int)mpeg3demux_read_prev_char(stream->demuxer) << 24;
return mpeg3demux_eof(stream->demuxer);
}
 
int mpeg3bits_byte_align(mpeg3_bits_t *stream)
{
stream->bit_number = (stream->bit_number + 7) & 0xf8;
return 0;
}
 
int mpeg3bits_open_title(mpeg3_bits_t* stream, int title)
{
stream->bfr_size = stream->bit_number = 0;
return mpeg3demux_open_title(stream->demuxer, title);
}
 
/*
* int mpeg3bits_seek_time(mpeg3_bits_t* stream, double time_position)
* {
* stream->bfr_size = stream->bit_number = 0;
* return mpeg3demux_seek_time(stream->demuxer, time_position);
* }
*/
 
int mpeg3bits_seek_byte(mpeg3_bits_t* stream, int64_t position)
{
stream->bfr_size = stream->bit_number = 0;
return mpeg3demux_seek_byte(stream->demuxer, position);
}
 
void mpeg3bits_reset(mpeg3_bits_t *stream)
{
stream->bfr_size = stream->bit_number = 0;
}
 
int64_t mpeg3bits_tell(mpeg3_bits_t* stream)
{
return mpeg3demux_tell_byte(stream->demuxer);
}
 
int mpeg3bits_getbitoffset(mpeg3_bits_t *stream)
{
return stream->bit_number & 7;
}
 
/branches/automake-1_1_5/hvirtual/libmpeg3/mpeg3tocutil.c
New file
0,0 → 1,1173
#include "libmpeg3.h"
#include "mpeg3protos.h"
 
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
static uint32_t read_int32(unsigned char *buffer, int *position)
{
uint32_t temp;
 
if(MPEG3_LITTLE_ENDIAN)
{
((unsigned char*)&temp)[3] = buffer[(*position)++];
((unsigned char*)&temp)[2] = buffer[(*position)++];
((unsigned char*)&temp)[1] = buffer[(*position)++];
((unsigned char*)&temp)[0] = buffer[(*position)++];
}
else
{
((unsigned char*)&temp)[0] = buffer[(*position)++];
((unsigned char*)&temp)[1] = buffer[(*position)++];
((unsigned char*)&temp)[2] = buffer[(*position)++];
((unsigned char*)&temp)[3] = buffer[(*position)++];
}
return temp;
}
 
static uint64_t read_int64(unsigned char *buffer, int *position)
{
uint64_t temp;
 
if(MPEG3_LITTLE_ENDIAN)
{
((unsigned char*)&temp)[7] = buffer[(*position)++];
((unsigned char*)&temp)[6] = buffer[(*position)++];
((unsigned char*)&temp)[5] = buffer[(*position)++];
((unsigned char*)&temp)[4] = buffer[(*position)++];
((unsigned char*)&temp)[3] = buffer[(*position)++];
((unsigned char*)&temp)[2] = buffer[(*position)++];
((unsigned char*)&temp)[1] = buffer[(*position)++];
((unsigned char*)&temp)[0] = buffer[(*position)++];
}
else
{
((unsigned char*)&temp)[0] = buffer[(*position)++];
((unsigned char*)&temp)[1] = buffer[(*position)++];
((unsigned char*)&temp)[2] = buffer[(*position)++];
((unsigned char*)&temp)[3] = buffer[(*position)++];
((unsigned char*)&temp)[4] = buffer[(*position)++];
((unsigned char*)&temp)[5] = buffer[(*position)++];
((unsigned char*)&temp)[6] = buffer[(*position)++];
((unsigned char*)&temp)[7] = buffer[(*position)++];
}
 
return temp;
}
 
static int read_data(unsigned char *buffer,
int *position,
unsigned char *output,
int bytes)
{
memcpy(output, buffer + *position, bytes);
*position += bytes;
}
 
int mpeg3_read_toc(mpeg3_t *file, int *atracks_return, int *vtracks_return)
{
unsigned char *buffer;
int file_type;
int position = 4;
int stream_type;
int i, j;
int is_vfs = 0;
int vfs_len = strlen(RENDERFARM_FS_PREFIX);
int toc_version;
int64_t current_byte = 0;
 
//printf("read_toc 1\n");
// Fix title paths for Cinelerra VFS
if(!strncmp(file->fs->path, RENDERFARM_FS_PREFIX, vfs_len))
is_vfs = 1;
 
buffer = malloc(mpeg3io_total_bytes(file->fs));
mpeg3io_seek(file->fs, 0);
mpeg3io_read_data(buffer, mpeg3io_total_bytes(file->fs), file->fs);
 
// Test version
if((toc_version = buffer[position++]) != MPEG3_TOC_VERSION)
{
fprintf(stderr,
"read_toc: invalid TOC version %x\n",
toc_version);
return 1;
}
 
//printf("read_toc %lld\n", mpeg3io_total_bytes(file->fs));
 
// File type
file_type = buffer[position++];
switch(file_type)
{
case FILE_TYPE_PROGRAM:
file->is_program_stream = 1;
break;
case FILE_TYPE_TRANSPORT:
file->is_transport_stream = 1;
break;
case FILE_TYPE_AUDIO:
file->is_audio_stream = 1;
break;
case FILE_TYPE_VIDEO:
file->is_video_stream = 1;
break;
}
 
//printf("read_toc 10\n");
 
// Stream ID's
while((stream_type = buffer[position]) != TITLE_PATH)
{
int offset;
int stream_id;
 
//printf("read_toc %d %x\n", position, buffer[position]);
position++;
offset = read_int32(buffer, &position);
stream_id = read_int32(buffer, &position);
 
if(stream_type == STREAM_AUDIO)
{
file->demuxer->astream_table[offset] = stream_id;
}
 
if(stream_type == STREAM_VIDEO)
{
file->demuxer->vstream_table[offset] = stream_id;
}
}
 
 
 
//printf("read_toc 10\n");
 
 
// Titles
while(buffer[position] == TITLE_PATH)
{
char string[MPEG3_STRLEN];
int string_len = 0;
mpeg3_title_t *title;
FILE *test_fd;
 
// Construct title path from VFS prefix and path.
position++;
if(is_vfs)
{
strcpy(string, RENDERFARM_FS_PREFIX);
string_len = vfs_len;
}
while(buffer[position] != 0) string[string_len++] = buffer[position++];
string[string_len++] = 0;
position++;
 
// Test title availability
test_fd = fopen(string, "r");
if(test_fd)
{
fclose(test_fd);
}
else
{
// Try concatenating title and toc directory if title is not absolute and
// toc path has a directory section.
if((!is_vfs && string[0] != '/') ||
(is_vfs && string[vfs_len] != '/'))
{
// Get toc filename without path
char *ptr = strrchr(file->fs->path, '/');
if(ptr)
{
char string2[MPEG3_STRLEN];
 
// Stack filename on toc path
strcpy(string2, file->fs->path);
if(!is_vfs)
strcpy(&string2[ptr - file->fs->path + 1], string);
else
strcpy(&string2[ptr - file->fs->path + 1], string + vfs_len);
 
test_fd = fopen(string2, "r");
if(test_fd)
{
fclose(test_fd);
strcpy(string, string2);
}
else
{
fprintf(stderr,
"read_toc: failed to open %s or %s\n",
string,
string2);
return 1;
}
}
else
{
fprintf(stderr,
"read_toc: failed to open %s\n",
string);
return 1;
}
}
else
{
fprintf(stderr,
"read_toc: failed to open %s\n",
string);
return 1;
}
}
 
title =
file->demuxer->titles[file->demuxer->total_titles++] =
mpeg3_new_title(file, string);
 
title->total_bytes = read_int64(buffer, &position);
title->start_byte = current_byte;
title->end_byte = title->start_byte + title->total_bytes;
current_byte = title->end_byte;
 
// Cells
title->cell_table_size =
title->cell_table_allocation =
read_int32(buffer, &position);
title->cell_table = calloc(title->cell_table_size, sizeof(mpeg3_cell_t));
for(i = 0; i < title->cell_table_size; i++)
{
mpeg3_cell_t *cell = &title->cell_table[i];
cell->title_start = read_int64(buffer, &position);
cell->title_end = read_int64(buffer, &position);
cell->program_start = read_int64(buffer, &position);
cell->program_end = read_int64(buffer, &position);
cell->program = read_int32(buffer, &position);
}
}
//printf("read_toc 10\n");
 
 
 
// Audio streams
// Skip ATRACK_COUNT
position++;
*atracks_return = read_int32(buffer, &position);
//printf("read_toc 1 %d\n", *atracks_return);
 
// Skip VTRACK_COUNT
position++;
*vtracks_return = read_int32(buffer, &position);
//printf("read_toc 2 %d\n", *vtracks_return);
 
 
if(*atracks_return)
{
file->channel_counts = calloc(sizeof(int), *atracks_return);
file->sample_offsets = calloc(sizeof(int64_t*), *atracks_return);
file->total_sample_offsets = calloc(sizeof(int*), *atracks_return);
file->audio_eof = calloc(sizeof(int64_t), *atracks_return);
 
for(i = 0; i < *atracks_return; i++)
{
file->audio_eof[i] = read_int64(buffer, &position);
file->channel_counts[i] = read_int32(buffer, &position);
file->total_sample_offsets[i] = read_int32(buffer, &position);
file->sample_offsets[i] = malloc(file->total_sample_offsets[i] * sizeof(int64_t));
for(j = 0; j < file->total_sample_offsets[i]; j++)
{
file->sample_offsets[i][j] = read_int64(buffer, &position);
}
//printf("samples %d %x %llx\n", i, file->sample_offsets[i][0]);
}
}
//printf("read_toc 10\n");
 
if(*vtracks_return)
{
file->frame_offsets = calloc(sizeof(int64_t*), *vtracks_return);
file->total_frame_offsets = calloc(sizeof(int*), *vtracks_return);
file->keyframe_numbers = calloc(sizeof(int64_t*), *vtracks_return);
file->total_keyframe_numbers = calloc(sizeof(int*), *vtracks_return);
file->video_eof = calloc(sizeof(int64_t), *vtracks_return);
 
for(i = 0; i < *vtracks_return; i++)
{
file->video_eof[i] = read_int64(buffer, &position);
file->total_frame_offsets[i] = read_int32(buffer, &position);
file->frame_offsets[i] = malloc(file->total_frame_offsets[i] * sizeof(int64_t));
for(j = 0; j < file->total_frame_offsets[i]; j++)
{
file->frame_offsets[i][j] = read_int64(buffer, &position);
//printf("frame %llx\n", file->frame_offsets[i][j]);
}
 
 
file->total_keyframe_numbers[i] = read_int32(buffer, &position);
file->keyframe_numbers[i] = malloc(file->total_keyframe_numbers[i] * sizeof(int64_t));
for(j = 0; j < file->total_keyframe_numbers[i]; j++)
{
file->keyframe_numbers[i][j] = read_int64(buffer, &position);
}
}
}
 
 
 
// Indexes. ATracks aren't created yet so we need to put the indexes somewhere
// else.
file->indexes = calloc(sizeof(mpeg3_index_t*), *atracks_return);
file->total_indexes = *atracks_return;
for(i = 0; i < *atracks_return; i++)
{
mpeg3_index_t *index = file->indexes[i] = mpeg3_new_index();
index->index_size = read_int32(buffer, &position);
index->index_zoom = read_int32(buffer, &position);
//printf("mpeg3_read_toc %d %d %d\n", i, index->index_size, index->index_zoom);
int channels = index->index_channels = file->channel_counts[i];
if(channels)
{
index->index_data = calloc(sizeof(float*), channels);
for(j = 0; j < channels; j++)
{
index->index_data[j] = calloc(sizeof(float),
index->index_size * 2);
read_data(buffer,
&position,
(unsigned char*)index->index_data[j],
sizeof(float) * index->index_size * 2);
}
}
}
 
 
 
 
 
free(buffer);
//printf("read_toc 10\n");
 
 
 
//printf("read_toc 1\n");
mpeg3demux_open_title(file->demuxer, 0);
//printf("read_toc 10\n");
 
return 0;
}
 
 
mpeg3_t* mpeg3_start_toc(char *path, char *toc_path, int64_t *total_bytes)
{
*total_bytes = 0;
mpeg3_t *file = mpeg3_new(path);
 
file->toc_fd = fopen(toc_path, "w");
if(!file->toc_fd)
{
printf("mpeg3_start_toc: can't open \"%s\". %s\n",
toc_path,
strerror(errno));
mpeg3_delete(file);
return 0;
}
 
file->seekable = 0;
 
/* Authenticate encryption before reading a single byte */
if(mpeg3io_open_file(file->fs))
{
mpeg3_delete(file);
return 0;
}
 
// Determine file type
int toc_atracks = 0, toc_vtracks = 0;
if(mpeg3_get_file_type(file, 0, 0, 0)) return 0;
 
 
 
// Create title without scanning for tracks
if(!file->demuxer->total_titles)
{
mpeg3_title_t *title;
title = file->demuxer->titles[0] = mpeg3_new_title(file, file->fs->path);
file->demuxer->total_titles = 1;
mpeg3demux_open_title(file->demuxer, 0);
title->total_bytes = mpeg3io_total_bytes(title->fs);
title->start_byte = 0;
title->end_byte = title->total_bytes;
mpeg3_new_cell(title,
0,
title->end_byte,
0,
title->end_byte,
0);
}
 
// mpeg3demux_seek_byte(file->demuxer, 0x1734e4800LL);
mpeg3demux_seek_byte(file->demuxer, 0);
file->demuxer->read_all = 1;
*total_bytes = mpeg3demux_movie_size(file->demuxer);
 
return file;
}
 
void mpeg3_set_index_bytes(mpeg3_t *file, int64_t bytes)
{
file->index_bytes = bytes;
}
 
 
 
 
 
static void divide_index(mpeg3_t *file, int track_number)
{
if(file->total_indexes <= track_number) return;
 
 
int i, j;
mpeg3_atrack_t *atrack = file->atrack[track_number];
mpeg3_index_t *index = file->indexes[track_number];
 
 
index->index_size /= 2;
index->index_zoom *= 2;
for(i = 0; i < index->index_channels; i++)
{
float *current_channel = index->index_data[i];
float *out = current_channel;
float *in = current_channel;
 
for(j = 0; j < index->index_size; j++)
{
float max = MAX(in[0], in[2]);
float min = MIN(in[1], in[3]);
*out++ = max;
*out++ = min;
in += 4;
}
}
 
}
 
 
 
 
int mpeg3_update_index(mpeg3_t *file,
int track_number,
int flush)
{
int i, j, k;
mpeg3_atrack_t *atrack = file->atrack[track_number];
mpeg3_index_t *index = file->indexes[track_number];
 
 
while((flush && atrack->audio->output_size) ||
(!flush && atrack->audio->output_size > MPEG3_AUDIO_CHUNKSIZE))
{
int fragment = MPEG3_AUDIO_CHUNKSIZE;
if(atrack->audio->output_size < fragment)
fragment = atrack->audio->output_size;
 
int index_fragments = fragment /
index->index_zoom;
if(flush) index_fragments++;
 
int new_index_samples;
new_index_samples = index_fragments +
index->index_size;
 
// Update number of channels
if(index->index_allocated &&
index->index_channels < atrack->channels)
{
float **new_index_data = calloc(sizeof(float*), atrack->channels);
for(i = 0; i < index->index_channels; i++)
{
new_index_data[i] = index->index_data[i];
}
for(i = index->index_channels; i < atrack->channels; i++)
{
new_index_data[i] = calloc(sizeof(float),
index->index_allocated * 2);
}
index->index_channels = atrack->channels;
free(index->index_data);
index->index_data = new_index_data;
}
 
// Allocate index buffer
if(new_index_samples > index->index_allocated)
{
// Double current number of samples
index->index_allocated = new_index_samples * 2;
if(!index->index_data)
{
index->index_data = calloc(sizeof(float*), atrack->channels);
}
 
// Allocate new size in high and low pairs
for(i = 0; i < atrack->channels; i++)
index->index_data[i] = realloc(index->index_data[i],
index->index_allocated * sizeof(float) * 2);
index->index_channels = atrack->channels;
}
 
 
 
// Calculate new index chunk
for(i = 0; i < atrack->channels; i++)
{
float *in_channel = atrack->audio->output[i];
float *out_channel = index->index_data[i] +
index->index_size * 2;
float min = 0;
float max = 0;
 
// Calculate index frames
for(j = 0; j < index_fragments; j++)
{
int remaining_fragment = fragment - j * index->index_zoom;
// Incomplete index frame
if(remaining_fragment < index->index_zoom)
{
for(k = 0; k < remaining_fragment; k++)
{
if(k == 0)
{
min = max = *in_channel++;
}
else
{
if(*in_channel > max) max = *in_channel;
else
if(*in_channel < min) min = *in_channel;
in_channel++;
}
}
}
else
{
min = max = *in_channel++;
for(k = 1; k < index->index_zoom; k++)
{
if(*in_channel > max) max = *in_channel;
else
if(*in_channel < min) min = *in_channel;
in_channel++;
}
}
*out_channel++ = max;
*out_channel++ = min;
}
}
 
index->index_size = new_index_samples;
 
// Shift audio buffer
mpeg3_shift_audio(atrack->audio, fragment);
 
 
// Create new toc entry
mpeg3_append_samples(atrack, atrack->prev_offset);
 
atrack->current_position += fragment;
}
 
// Divide index by 2 and increase zoom
if(index->index_size * atrack->channels * sizeof(float) * 2 >
file->index_bytes &&
!(index->index_size % 2))
{
divide_index(file, track_number);
}
}
 
 
 
int mpeg3_toc_audio(mpeg3_t *file,
int track_number)
{
int i, j, k;
mpeg3_atrack_t *atrack = file->atrack[track_number];
 
// Assume last packet of stream
atrack->audio_eof = mpeg3demux_tell_byte(file->demuxer);
 
// Append demuxed data to track buffer
mpeg3demux_append_data(atrack->demuxer,
file->demuxer->audio_buffer,
file->demuxer->audio_size);
 
 
// Decode samples
mpeg3audio_decode_audio(atrack->audio,
0,
0,
0,
MPEG3_AUDIO_HISTORY);
 
// When a chunk is available,
// add downsampled samples to the index buffer and create toc entry.
mpeg3_update_index(file, track_number, 0);
 
return 0;
}
 
int mpeg3_toc_video(mpeg3_t *file,
mpeg3_vtrack_t *vtrack)
{
mpeg3video_t *video = vtrack->video;
 
/*
* static FILE *test = 0;
* if(!test) test = fopen("test.m2v", "w");
* fwrite(file->demuxer->data_buffer, 1, file->demuxer->data_size, test);
* static int counter = 0;
* printf("%x %d\n", vtrack->pid, counter++);
*/
// Assume last packet of stream
vtrack->video_eof = mpeg3demux_tell_byte(file->demuxer);
 
// Append demuxed data to track buffer
mpeg3demux_append_data(vtrack->demuxer,
file->demuxer->video_buffer,
file->demuxer->video_size);
 
 
if(vtrack->demuxer->data_size - vtrack->demuxer->data_position <
MPEG3_VIDEO_STREAM_SIZE) return 0;
 
// Scan for a start code a certain number of bytes from the end of the
// buffer. Then scan the header using the video decoder to get the
// repeat count.
unsigned char *ptr = &vtrack->demuxer->data_buffer[
vtrack->demuxer->data_position];
uint32_t code = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
ptr += 4;
while(vtrack->demuxer->data_size - vtrack->demuxer->data_position >
MPEG3_VIDEO_STREAM_SIZE)
{
if(code == MPEG3_SEQUENCE_START_CODE ||
code == MPEG3_GOP_START_CODE ||
code == MPEG3_PICTURE_START_CODE)
{
 
// Use video decoder to get repeat count and field type. Should never hit EOF in here.
// This rereads up to the current ptr since data_position isn't updated by
// mpeg3_toc_video.
if(!mpeg3video_get_header(video, 0))
{
if(video->pict_struct == BOTTOM_FIELD ||
video->pict_struct == FRAME_PICTURE ||
!video->pict_struct)
{
int is_keyframe = (video->pict_type == I_TYPE);
 
// Add entry for every repeat count.
mpeg3_append_frame(vtrack, vtrack->prev_offset, is_keyframe);
video->current_repeat += 100;
while(video->repeat_count - video->current_repeat >= 100)
{
mpeg3_append_frame(vtrack, vtrack->prev_offset, is_keyframe);
video->current_repeat += 100;
}
 
ptr = &vtrack->demuxer->data_buffer[
vtrack->demuxer->data_position];
code = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
ptr += 4;
 
// Shift out data from before frame
mpeg3demux_shift_data(vtrack->demuxer, vtrack->demuxer->data_position);
}
}
else
{
// Try this offset again with more data
break;
}
}
else
{
vtrack->demuxer->data_position++;
code <<= 8;
code |= *ptr++;
}
}
vtrack->demuxer->data_position -= 4;
 
 
return 0;
}
 
int mpeg3_do_toc(mpeg3_t *file, int64_t *bytes_processed)
{
int i, j, k;
// Starting byte before our packet read
int64_t start_byte;
 
start_byte = mpeg3demux_tell_byte(file->demuxer);
 
int result = mpeg3_read_next_packet(file->demuxer);
 
// Determine program and stream id for current packet. Should be only one.
int program = mpeg3demux_tell_program(file->demuxer);
 
 
/*
* if(start_byte > 0x1b0000 &&
* start_byte < 0x1c0000)
* printf("mpeg3_do_toc 1 start_byte=%llx custum_id=%x got_audio=%d got_video=%d audio_size=%d video_size=%d data_size=%d\n",
* start_byte,
* file->demuxer->custom_id,
* file->demuxer->got_audio,
* file->demuxer->got_video,
* file->demuxer->audio_size,
* file->demuxer->video_size,
* file->demuxer->data_size);
*/
 
// Only handle program 0
if(program == 0)
{
// Find current PID in tracks.
int custom_id = file->demuxer->custom_id;
int got_it = 0;
 
 
// In a transport stream the PID's are unique for all audio and video but in
// other streams the PID's are shared.
if(file->demuxer->got_audio ||
file->is_transport_stream ||
file->is_audio_stream)
{
for(i = 0; i < file->total_astreams && !got_it; i++)
{
mpeg3_atrack_t *atrack = file->atrack[i];
if(custom_id == atrack->pid)
{
//printf("mpeg3_do_toc 2 %x\n", atrack->pid);
// Update an audio track
mpeg3_toc_audio(file, i);
atrack->prev_offset = start_byte;
got_it = 1;
break;
}
}
 
if(!got_it && ((file->demuxer->got_audio &&
file->demuxer->astream_table[custom_id]) ||
file->is_audio_stream))
{
mpeg3_atrack_t *atrack =
file->atrack[file->total_astreams] =
mpeg3_new_atrack(file,
custom_id,
file->demuxer->astream_table[custom_id],
file->demuxer,
file->total_astreams);
 
if(atrack)
{
// Create index table
file->total_indexes++;
file->indexes = realloc(file->indexes,
file->total_indexes * sizeof(mpeg3_index_t*));
file->indexes[file->total_indexes - 1] =
mpeg3_new_index();
 
 
file->total_astreams++;
// Make the first offset correspond to the start of the first packet.
mpeg3_append_samples(atrack, start_byte);
mpeg3_toc_audio(file, file->total_astreams - 1);
atrack->prev_offset = start_byte;
}
}
 
}
 
 
if(file->demuxer->got_video ||
file->is_transport_stream ||
file->is_video_stream)
{
got_it = 0;
for(i = 0; i < file->total_vstreams && !got_it; i++)
{
mpeg3_vtrack_t *vtrack = file->vtrack[i];
if(vtrack->pid == custom_id)
{
// Update a video track
mpeg3_toc_video(file, vtrack);
vtrack->prev_offset = start_byte;
got_it = 1;
break;
}
}
 
 
 
if(!got_it && ((file->demuxer->got_video &&
file->demuxer->vstream_table[custom_id]) ||
file->is_video_stream))
{
mpeg3_vtrack_t *vtrack =
file->vtrack[file->total_vstreams] =
mpeg3_new_vtrack(file,
custom_id,
file->demuxer,
file->total_vstreams);
 
// Make the first offset correspond to the start of the first packet.
if(vtrack)
{
file->total_vstreams++;
// Create table entry for frame 0
mpeg3_append_frame(vtrack, start_byte, 1);
mpeg3_toc_video(file, vtrack);
vtrack->prev_offset = start_byte;
}
}
}
}
 
 
// Make user value independant of data type in packet
*bytes_processed = mpeg3demux_tell_byte(file->demuxer);
//printf("mpeg3_do_toc 1000 %llx\n", *bytes_processed);
}
 
 
 
 
 
#define PUT_INT32(x) \
{ \
if(MPEG3_LITTLE_ENDIAN) \
{ \
fputc(((unsigned char*)&x)[3], file->toc_fd); \
fputc(((unsigned char*)&x)[2], file->toc_fd); \
fputc(((unsigned char*)&x)[1], file->toc_fd); \
fputc(((unsigned char*)&x)[0], file->toc_fd); \
} \
else \
{ \
fputc(((unsigned char*)&x)[0], file->toc_fd); \
fputc(((unsigned char*)&x)[1], file->toc_fd); \
fputc(((unsigned char*)&x)[2], file->toc_fd); \
fputc(((unsigned char*)&x)[3], file->toc_fd); \
} \
}
 
 
 
 
#define PUT_INT64(x) \
{ \
if(MPEG3_LITTLE_ENDIAN) \
{ \
fputc(((unsigned char*)&x)[7], file->toc_fd); \
fputc(((unsigned char*)&x)[6], file->toc_fd); \
fputc(((unsigned char*)&x)[5], file->toc_fd); \
fputc(((unsigned char*)&x)[4], file->toc_fd); \
fputc(((unsigned char*)&x)[3], file->toc_fd); \
fputc(((unsigned char*)&x)[2], file->toc_fd); \
fputc(((unsigned char*)&x)[1], file->toc_fd); \
fputc(((unsigned char*)&x)[0], file->toc_fd); \
} \
else \
{ \
fwrite(&x, 1, 8, file->toc_fd); \
} \
}
 
 
 
 
 
void mpeg3_stop_toc(mpeg3_t *file)
{
// Create final chunk for audio tracks to count the last samples.
int i, j;
for(i = 0; i < file->total_astreams; i++)
{
mpeg3_atrack_t *atrack = file->atrack[i];
mpeg3_append_samples(atrack, atrack->prev_offset);
}
 
// Flush audio indexes
for(i = 0; i < file->total_astreams; i++)
mpeg3_update_index(file, i, 1);
 
// Make all indexes the same scale
int max_scale = 1;
for(i = 0; i < file->total_astreams; i++)
{
mpeg3_atrack_t *atrack = file->atrack[i];
mpeg3_index_t *index = file->indexes[i];
if(index->index_data && index->index_zoom > max_scale)
max_scale = index->index_zoom;
}
 
for(i = 0; i < file->total_astreams; i++)
{
mpeg3_atrack_t *atrack = file->atrack[i];
mpeg3_index_t *index = file->indexes[i];
if(index->index_data && index->index_zoom < max_scale)
{
while(index->index_zoom < max_scale)
divide_index(file, i);
}
}
 
 
 
 
// Sort tracks by PID
int done = 0;
while(!done)
{
done = 1;
for(i = 0; i < file->total_astreams - 1; i++)
{
mpeg3_atrack_t *atrack1 = file->atrack[i];
mpeg3_atrack_t *atrack2 = file->atrack[i + 1];
if(atrack1->pid > atrack2->pid)
{
done = 0;
file->atrack[i + 1] = atrack1;
file->atrack[i] = atrack2;
mpeg3_index_t *index1 = file->indexes[i];
mpeg3_index_t *index2 = file->indexes[i + 1];
file->indexes[i] = index2;
file->indexes[i + 1] = index1;
}
}
}
 
 
done = 0;
while(!done)
{
done = 1;
for(i = 0; i < file->total_vstreams - 1; i++)
{
mpeg3_vtrack_t *vtrack1 = file->vtrack[i];
mpeg3_vtrack_t *vtrack2 = file->vtrack[i + 1];
if(vtrack1->pid > vtrack2->pid)
{
done = 0;
file->vtrack[i + 1] = vtrack1;
file->vtrack[i] = vtrack2;
}
}
}
 
 
 
// Output toc to file
// Write file type
fputc('T', file->toc_fd);
fputc('O', file->toc_fd);
fputc('C', file->toc_fd);
fputc(' ', file->toc_fd);
 
// Write version
fputc(MPEG3_TOC_VERSION, file->toc_fd);
 
// Write stream type
if(file->is_program_stream)
{
fputc(FILE_TYPE_PROGRAM, file->toc_fd);
}
else
if(file->is_transport_stream)
{
fputc(FILE_TYPE_TRANSPORT, file->toc_fd);
}
else
if(file->is_audio_stream)
{
fputc(FILE_TYPE_AUDIO, file->toc_fd);
}
else
if(file->is_video_stream)
{
fputc(FILE_TYPE_VIDEO, file->toc_fd);
}
 
// Write stream ID's
// Only program and transport streams have these
for(i = 0; i < MPEG3_MAX_STREAMS; i++)
{
if(file->demuxer->astream_table[i])
{
fputc(STREAM_AUDIO, file->toc_fd);
PUT_INT32(i);
PUT_INT32(file->demuxer->astream_table[i]);
}
 
if(file->demuxer->vstream_table[i])
{
fputc(STREAM_VIDEO, file->toc_fd);
PUT_INT32(i);
PUT_INT32(file->demuxer->vstream_table[i]);
}
}
 
// Write titles
for(i = 0; i < file->demuxer->total_titles; i++)
{
mpeg3_title_t *title = file->demuxer->titles[i];
// Path
fputc(TITLE_PATH, file->toc_fd);
fprintf(file->toc_fd, title->fs->path);
fputc(0, file->toc_fd);
// Total bytes
PUT_INT64(title->total_bytes);
// Byte offsets of cells
PUT_INT32(file->demuxer->titles[i]->cell_table_size);
for(j = 0; j < title->cell_table_size; j++)
{
mpeg3_cell_t *cell = &title->cell_table[j];
PUT_INT64(cell->title_start);
PUT_INT64(cell->title_end);
PUT_INT64(cell->program_start);
PUT_INT64(cell->program_end);
PUT_INT32(cell->program);
}
}
 
 
 
fputc(ATRACK_COUNT, file->toc_fd);
PUT_INT32(file->total_astreams);
 
fputc(VTRACK_COUNT, file->toc_fd);
PUT_INT32(file->total_vstreams);
 
// Audio streams
for(j = 0; j < file->total_astreams; j++)
{
mpeg3_atrack_t *atrack = file->atrack[j];
PUT_INT64(atrack->audio_eof);
PUT_INT32(atrack->channels);
PUT_INT32(atrack->total_sample_offsets);
for(i = 0; i < atrack->total_sample_offsets; i++)
{
PUT_INT64(atrack->sample_offsets[i]);
}
}
 
 
 
 
 
// Video streams
for(j = 0; j < file->total_vstreams; j++)
{
mpeg3_vtrack_t *vtrack = file->vtrack[j];
PUT_INT64(vtrack->video_eof);
PUT_INT32(vtrack->total_frame_offsets);
for(i = 0; i < vtrack->total_frame_offsets; i++)
{
PUT_INT64(vtrack->frame_offsets[i]);
}
 
PUT_INT32(vtrack->total_keyframe_numbers);
for(i = 0; i < vtrack->total_keyframe_numbers; i++)
{
PUT_INT64(vtrack->keyframe_numbers[i]);
}
}
 
 
// Audio indexes
// Write indexes
for(i = 0; i < file->total_astreams; i++)
{
mpeg3_atrack_t *atrack = file->atrack[i];
mpeg3_index_t *index = file->indexes[i];
if(index->index_data)
{
PUT_INT32(index->index_size);
PUT_INT32(index->index_zoom);
for(j = 0; j < atrack->channels; j++)
{
fwrite(index->index_data[j],
sizeof(float) * 2,
index->index_size,
file->toc_fd);
}
}
}
 
 
 
 
fclose(file->toc_fd);
 
 
mpeg3_delete(file);
}
 
 
 
 
 
 
 
 
 
int mpeg3_index_tracks(mpeg3_t *file)
{
return file->total_indexes;
}
 
int mpeg3_index_channels(mpeg3_t *file, int track)
{
if(!file->total_indexes) return 0;
return file->indexes[track]->index_channels;
}
 
int mpeg3_index_zoom(mpeg3_t *file)
{
if(!file->total_indexes) return 0;
 
return file->indexes[0]->index_zoom;
}
 
int mpeg3_index_size(mpeg3_t *file, int track)
{
if(!file->total_indexes) return 0;
return file->indexes[track]->index_size;
}
 
float* mpeg3_index_data(mpeg3_t *file, int track, int channel)
{
if(!file->total_indexes) return 0;
return file->indexes[track]->index_data[channel];
}
 
 
int mpeg3_has_toc(mpeg3_t *file)
{
if(file->frame_offsets || file->sample_offsets) return 1;
return 0;
}
 
 
 
 
 
/branches/automake-1_1_5/hvirtual/libmpeg3/mpeg3peek.c
New file
0,0 → 1,43
#include "libmpeg3.h"
#include <stdlib.h>
 
 
 
 
int main(int argc, char *argv[])
{
mpeg3_t *file;
if(argc < 3)
{
printf("Usage: mpeg3peek <table of contents> <frame number>\n");
printf("Print the byte offset of a given frame.\n");
printf("Only works for video. Requires table of contents.\n");
printf("Example: mpeg3peek heroine.toc 123\n");
exit(1);
}
 
 
file = mpeg3_open(argv[1]);
if(file)
{
if(!mpeg3_total_vstreams(file))
{
printf("Need a video stream.\n");
exit(1);
}
 
if(!file->vtrack[0]->total_frame_offsets)
{
printf("Zero length track. Did you load a table of contents?\n");
exit(1);
}
 
int frame_number = atoi(argv[2]);
if(frame_number < 0) frame_number = 0;
if(frame_number > file->vtrack[0]->total_frame_offsets)
frame_number = file->vtrack[0]->total_frame_offsets - 1;
printf("frame=%d offset=0x%llx\n",
frame_number,
file->vtrack[0]->frame_offsets[frame_number]);
}
}
/branches/automake-1_1_5/hvirtual/cinelerra/iec61883input.h
New file
0,0 → 1,102
#ifndef IEC61883INPUT_H
#define IEC61883INPUT_H
 
 
 
#ifdef HAVE_FIREWIRE
 
#include "condition.inc"
#include "iec61883.h"
#include "libdv.h"
#include "mutex.inc"
#include "thread.h"
#include "vframe.inc"
 
// Common 1394 input for audio and video
 
// Extracts video and audio from the single DV stream
class IEC61883Input : public Thread
{
public:
IEC61883Input();
~IEC61883Input();
 
int open(int port,
int channel,
int length,
int channels,
int samplerate,
int bits,
int w,
int h);
void run();
void increment_counter(int *counter);
void decrement_counter(int *counter);
 
// Read a video frame with timed blocking
 
int read_video(VFrame *data);
 
 
// Read audio with timed blocking
 
int read_audio(char *data, int samples);
 
 
int write_frame(unsigned char *data, int len, int complete);
 
raw1394handle_t handle;
iec61883_dv_fb_t frame;
int fd;
 
 
 
 
 
 
 
 
 
// Storage of all frames
char **buffer;
int *buffer_valid;
int buffer_size;
int total_buffers;
int current_inbuffer;
 
// For extracting audio
dv_t *decoder;
 
// Storage of audio data
char *audio_buffer;
int audio_samples;
 
// number of next video buffer to read
int current_outbuffer;
unsigned char *input_buffer;
 
Mutex *buffer_lock;
Condition *video_lock;
Condition *audio_lock;
int done;
 
int port;
int channel;
int length;
int channels;
int samplerate;
int bits;
int w;
int h;
int is_pal;
};
 
 
 
 
 
#endif
 
 
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/CHANGELOG.1.2.3
New file
0,0 → 1,116
H.264 Video, MPEG-4 Audio and Video encoding in Quicktime, compatible with Quicktime player.
- The ffmpeg front end has been improved to where it generates useful quality.
- Certain frame rates and compression options don't work in Win.
 
Refurbished MPEG table of contents.
- Tables of contents now detect changes in PID.
- Tables of contents are created twice as fast.
- Load any MPEG or IFO file with video in Cinelerra and a table of
contents is automatically created.
- Audio indexes are created simultaneously with MPEG tables of contents.
- Still possible to create permanent tables of contents with mpeg3toc.
- Using MPEG files in a renderfarm still requires mpeg3toc due to the fact that the
automatic .toc files are hidden.
 
Fewer lockups when resizing video window.
Fewer crashes due to socket timeouts in background rendering.
Directory search boxes only contain relevant information for directories.
Hourglass displayed in main window during time consuming operations.
Having shared effect off but sharing instance on doesn't create mono sound anymore.
Tool options get closed when CWindow is closed.
Picture settings retained after recording from V4L2. Workaround for V4L2 driver
where 2 different picture settings must be uploaded.
Bitrate displayed in asset info box.
64 bit plugins are stored in /usr/lib64 so 64 bit executables can be run on the
same systems as 32 bit executables without renaming the directory.
Color picker in compositor window allows selecting colors from the output frame
for use in effects.
Refurbushed chroma key:
- uses color cube instead of hue for color comparison
- uses the color picker to select the color
Support for raw digital camera importing.
- Uses dcraw to decode the images into floating point RGB.
- tested on Canon .cr2 and .tiff files.
- Linearize effect is provided to convert gamma values.
White balance function in colorbalance effect.
- Select the grey color in the compositor window.
- Hit the white balance button.
 
YUV 16 bit colormodels have been depreciated. The only practical
colormodels have been 8 bit and floating point. Even with raw sensor
data, the precision needs to be higher to handle the gamma correction.
 
Difference key using different tracks.
Undo buffers use compression to reduce memory usage.
Undo supports effect tweeks.
Nudge textboxes are ganged.
Mouse wheel changes nudge value.
 
Holding CTRL when doing any playback operation causes the in/out points to be used
for the playback range.
 
Moved from the unified camera and projector keyframes to discrete x
and y curves.
- Z was already made discrete out of necessary utility.
- Too much information was drawn on the Compositor window.
- The timeline functionality is extended to better handle curves.
 
Alt+up and Alt+down zoom the automation vertically.
 
Dedicated window provided for selecting which automation overlays to show.
 
The problem with virtual filesystem:
- VFS was developed back when we wanted to use some high powered servers but
didn't have root access to mount filesystems on them. That situation ended and
it was taking an enourmous amount of effort to work VFS around the number of
strange things libraries do like accessing megabytes using fgetc.
VFS has now been phased out.
 
Fixed lockups due to MWindow locking CWindow when MWindow was still locked.
Fixed problems loading ulaw sound files.
 
Tip of the day shown.
Filebox supports deleting files and refreshing.
Extra zoom levels added to Compositor window.
 
Highlighted region overrides in/out points if it is nonzero length.
 
Blond theme has not been updated. Instead it has been replaced by the
SUV theme. The SUV theme is extremely manly and dark and should make
the media stand out more.
 
MPEG4 audio decodes on x86_64. Had to put stdint.h in faad.h and
change all the unsigned long to uint32_t because those structures were
redefined in structs.h with uint32_t.
 
Channel changing for Video4Linux2 ported to kernel 2.6.7. Automatic
channel scanning and sorting is supported for the 1 guy who still uses
these cards.
 
Pressing ALT while clicking in cropping window causes translation of
all 4 cropping points.
 
Rotation effect supports a variable pivot and drawing of the pivot in
the frame.
 
DV support migrated to latest API rewrite: libIEC61883
 
MPEG video encoding provides a graphical interface for YUV 4:2:0
encoding on the mjpegtools version of mpeg2enc.
 
The audio playback options support a global offset for audio
synchronization. This doesn't affect the audio playback or the
rendering. It just compensates for inaccuracy in the Linux sound
drivers.
 
The ALSA options allow compensation for lockups at end of playback
depending on the ALSA version, soundcard, and ALSA rewrite.
 
Press Tab while the cursor is anywhere over a track to toggle the track
arming status. Press Shift-Tab while the cursor is over a track to
toggle the arming status of every other track.
 
Resample effect changed to match the behavior of the Reframe effects.
Scale factors > 1 shorten the length of the audio.
 
 
/branches/automake-1_1_5/hvirtual/cinelerra/tipwindow.inc
New file
0,0 → 1,10
#ifndef TIPWINDOW_INC
#define TIPWINDOW_INC
 
 
class TipWindow;
class TipWindowGUI;
 
 
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/fileogg.C
New file
0,0 → 1,903
 
#include "clip.h"
#include "asset.h"
#include "bcsignals.h"
#include "byteorder.h"
#include "edit.h"
#include "file.h"
#include "fileogg.h"
#include "guicast.h"
#include "language.h"
#include "mwindow.inc"
#include "quicktime.h"
#include "vframe.h"
#include "videodevice.inc"
#include "cmodel_permutation.h"
 
 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
 
FileOGG::FileOGG(Asset *asset, File *file)
: FileBase(asset, file)
{
if(asset->format == FILE_UNKNOWN)
asset->format = FILE_OGG;
asset->byte_order = 0;
reset_parameters();
}
 
FileOGG::~FileOGG()
{
 
int i = 0;
if (tf) delete tf;
if (temp_frame) delete temp_frame;
if(stream) close_file();
 
}
 
void FileOGG::get_parameters(BC_WindowBase *parent_window,
Asset *asset,
BC_WindowBase* &format_window,
int audio_options,
int video_options)
{
if(audio_options)
{
OGGConfigAudio *window = new OGGConfigAudio(parent_window, asset);
format_window = window;
window->create_objects();
window->run_window();
delete window;
}
else
if(video_options)
{
OGGConfigVideo *window = new OGGConfigVideo(parent_window, asset);
format_window = window;
window->create_objects();
window->run_window();
delete window;
}
 
}
 
int FileOGG::reset_parameters_derived()
{
tf = 0;
temp_frame = 0;
stream = 0;
}
 
int FileOGG::open_file(int rd, int wr)
{
 
TRACE("FileOGG::open_file 10")
if (!tf)
tf = new theoraframes_info_t;
if(wr)
{
 
TRACE("FileOGG::open_file 20")
 
if((stream = fopen(asset->path, "w+b")) == 0)
{
perror(_("FileOGG::open_file rdwr"));
return 1;
}
 
tf->audio_bytesout = 0;
tf->video_bytesout = 0;
tf->videoflag = 0;
tf->audioflag = 0;
tf->videotime = 0;
tf->audiotime = 0;
/* yayness. Set up Ogg output stream */
srand (time (NULL));
ogg_stream_init (&tf->vo, rand ());
 
if(asset->video_data)
{
ogg_stream_init (&tf->to, rand ()); /* oops, add one ot the above */
theora_info_init (&tf->ti);
tf->ti.width = asset->width;
tf->ti.height = asset->height;
tf->ti.frame_width = ((asset->width + 15) >>4)<<4; // round up to the nearest multiple of 16
tf->ti.frame_height = ((asset->height + 15) >>4)<<4; // round up to the nearest multiple of 16
if (tf->ti.width != tf->ti.frame_width || tf->ti.height != tf->ti.width)
printf("FileOGG: WARNING: Width and hegiht must be dividable by 16\n");
 
tf->ti.offset_x = 0;
tf->ti.offset_y = 0;
tf->ti.fps_numerator = (unsigned int)(asset->frame_rate * 1000000);
tf->ti.fps_denominator = 1000000;
if (asset->aspect_ratio > 0)
{
// Cinelerra uses frame aspect ratio, theora uses pixel aspect ratio
float pixel_aspect = asset->aspect_ratio / asset->width * asset->height;
tf->ti.aspect_numerator = (unsigned int)(pixel_aspect * 1000000);
tf->ti.aspect_denominator = 1000000;
} else
{
tf->ti.aspect_numerator = 1000000;
tf->ti.aspect_denominator = 1000000;
}
if(EQUIV(asset->frame_rate, 25) || EQUIV(asset->frame_rate, 50))
tf->ti.colorspace = OC_CS_ITU_REC_470BG;
else if((asset->frame_rate > 29 && asset->frame_rate < 31) || (asset->frame_rate > 59 && asset->frame_rate < 61) )
tf->ti.colorspace = OC_CS_ITU_REC_470M;
else
tf->ti.colorspace = OC_CS_UNSPECIFIED;
 
if (asset->theora_fix_bitrate)
{
tf->ti.target_bitrate = asset->theora_bitrate;
tf->ti.quality = 0;
} else
{
tf->ti.target_bitrate = 0;
tf->ti.quality = asset->theora_quality; // video quality 0-63
}
tf->ti.dropframes_p = 0;
tf->ti.quick_p = 1;
tf->ti.keyframe_auto_p = 1;
tf->ti.keyframe_frequency = asset->theora_keyframe_frequency;
tf->ti.keyframe_frequency_force = asset->theora_keyframe_force_frequency;
tf->ti.keyframe_data_target_bitrate = (unsigned int) (tf->ti.target_bitrate * 1.5) ;
tf->ti.keyframe_auto_threshold = 80;
tf->ti.keyframe_mindistance = 8;
tf->ti.noise_sensitivity = 1;
tf->ti.sharpness = 2;
theora_encode_init (&tf->td, &tf->ti);
}
/* init theora done */
 
/* initialize Vorbis too, if we have audio. */
if(asset->audio_data)
{
vorbis_info_init (&tf->vi);
/* Encoding using a VBR quality mode. */
int ret;
if(!asset->vorbis_vbr)
{
ret = vorbis_encode_init(&tf->vi,
asset->channels,
asset->sample_rate,
asset->vorbis_max_bitrate,
asset->vorbis_bitrate,
asset->vorbis_min_bitrate);
} else
{
// Set true VBR as demonstrated by http://svn.xiph.org/trunk/vorbis/doc/vorbisenc/examples.html
ret = vorbis_encode_setup_managed(&tf->vi,
asset->channels,
asset->sample_rate,
-1,
asset->vorbis_bitrate,
-1);
ret |= vorbis_encode_ctl(&tf->vi, OV_ECTL_RATEMANAGE2_SET, NULL);
ret |= vorbis_encode_setup_init(&tf->vi);
}
if (ret)
{
fprintf (stderr,
"The Vorbis encoder could not set up a mode according to\n"
"the requested quality or bitrate.\n\n");
return 1;
}
 
vorbis_comment_init (&tf->vc);
vorbis_comment_add_tag (&tf->vc, "ENCODER", PACKAGE_STRING);
/* set up the analysis state and auxiliary encoding storage */
vorbis_analysis_init (&tf->vd, &tf->vi);
vorbis_block_init (&tf->vd, &tf->vb);
 
}
/* audio init done */
 
/* write the bitstream header packets with proper page interleave */
 
/* first packet will get its own page automatically */
if(asset->video_data)
{
theora_encode_header (&tf->td, &tf->op);
ogg_stream_packetin (&tf->to, &tf->op);
if (ogg_stream_pageout (&tf->to, &tf->og) != 1)
{
fprintf (stderr, "Internal Ogg library error.\n");
return 1;
}
fwrite (tf->og.header, 1, tf->og.header_len, stream);
fwrite (tf->og.body, 1, tf->og.body_len, stream);
 
/* create the remaining theora headers */
theora_comment_init (&tf->tc);
theora_comment_add_tag (&tf->tc, "ENCODER", PACKAGE_STRING);
theora_encode_comment (&tf->tc, &tf->op);
ogg_stream_packetin (&tf->to, &tf->op);
theora_comment_clear(&tf->tc);
 
theora_encode_tables (&tf->td, &tf->op);
ogg_stream_packetin (&tf->to, &tf->op);
}
if(asset->audio_data){
ogg_packet header;
ogg_packet header_comm;
ogg_packet header_code;
 
vorbis_analysis_headerout (&tf->vd, &tf->vc, &header,
&header_comm, &header_code);
ogg_stream_packetin (&tf->vo, &header); /* automatically placed in its own
* page */
if (ogg_stream_pageout (&tf->vo, &tf->og) != 1)
{
fprintf (stderr, "Internal Ogg library error.\n");
return 1;
}
fwrite (tf->og.header, 1, tf->og.header_len, stream);
fwrite (tf->og.body, 1, tf->og.body_len, stream);
 
/* remaining vorbis header packets */
ogg_stream_packetin (&tf->vo, &header_comm);
ogg_stream_packetin (&tf->vo, &header_code);
}
 
/* Flush the rest of our headers. This ensures
* the actual data in each stream will start
* on a new page, as per spec. */
while (1 && asset->video_data)
{
int result = ogg_stream_flush (&tf->to, &tf->og);
if (result < 0)
{
/* can't get here */
fprintf (stderr, "Internal Ogg library error.\n");
return 1;
}
if (result == 0)
break;
fwrite (tf->og.header, 1, tf->og.header_len, stream);
fwrite (tf->og.body, 1, tf->og.body_len, stream);
}
while (1 && asset->audio_data)
{
int result = ogg_stream_flush (&tf->vo, &tf->og);
if (result < 0)
{
/* can't get here */
fprintf (stderr, "Internal Ogg library error.\n");
return 1;
}
if (result == 0)
break;
fwrite (tf->og.header, 1, tf->og.header_len, stream);
fwrite (tf->og.body, 1, tf->og.body_len, stream);
}
 
 
}
if (rd)
return 1;
return 0;
}
 
int FileOGG::check_sig(Asset *asset)
{
return 0;
}
 
int FileOGG::close_file()
{
if (wr)
{
if (asset->video_data)
write_frames_theora(0, 0, 1); // set eos
if (asset->audio_data)
write_samples_vorbis(0, 0, 1); // set eos
flush_ogg(1);
if (asset->audio_data)
{
vorbis_block_clear (&tf->vb);
vorbis_dsp_clear (&tf->vd);
vorbis_comment_clear (&tf->vc);
vorbis_info_clear (&tf->vi);
}
if (asset->video_data)
{
theora_info_clear (&tf->ti);
ogg_stream_clear (&tf->to);
theora_clear (&tf->td);
 
}
ogg_stream_clear (&tf->vo);
if (stream) fclose(stream);
stream = 0;
}
}
 
int FileOGG::close_file_derived()
{
//printf("FileOGG::close_file_derived(): 1\n");
if (stream) fclose(stream);
stream = 0;
}
 
int64_t FileOGG::get_video_position()
{
return 0;
}
 
int64_t FileOGG::get_audio_position()
{
return 0;
}
 
int FileOGG::set_video_position(int64_t x)
{
return 1;
}
 
int FileOGG::set_audio_position(int64_t x)
{
return 1;
}
 
int FileOGG::flush_ogg(int e_o_s)
{
/* flush out the ogg pages to stream */
 
int flushloop=1;
 
while(flushloop)
{
int video = -1;
flushloop=0;
//some debuging
//fprintf(stderr,"\ndiff: %f\n",info->audiotime-info->videotime);
while(asset->video_data && (e_o_s ||
((tf->videotime <= tf->audiotime || !asset->video_data) && tf->videoflag == 1)))
{
tf->videoflag = 0;
while(ogg_stream_pageout (&tf->to, &tf->videopage) > 0)
{
tf->videotime=
theora_granule_time (&tf->td, ogg_page_granulepos(&tf->videopage));
/* flush a video page */
tf->video_bytesout +=
fwrite (tf->videopage.header, 1, tf->videopage.header_len, stream);
tf->video_bytesout +=
fwrite (tf->videopage.body, 1, tf->videopage.body_len, stream);
// tf->vkbps = rint (tf->video_bytesout * 8. / tf->videotime * .001);
 
// print_stats(info, tf->videotime);
video=1;
tf->videoflag = 1;
flushloop=1;
}
if(e_o_s)
break;
}
 
while (asset->audio_data && (e_o_s ||
((tf->audiotime < tf->videotime || !asset->video_data) && tf->audioflag==1)))
{
tf->audioflag = 0;
while(ogg_stream_pageout (&tf->vo, &tf->audiopage) > 0){
/* flush an audio page */
tf->audiotime=
vorbis_granule_time (&tf->vd, ogg_page_granulepos(&tf->audiopage));
tf->audio_bytesout +=
fwrite (tf->audiopage.header, 1, tf->audiopage.header_len, stream);
tf->audio_bytesout +=
fwrite (tf->audiopage.body, 1, tf->audiopage.body_len, stream);
 
// tf->akbps = rint (tf->audio_bytesout * 8. / tf->audiotime * .001);
// print_stats(info, tf->audiotime);
video=0;
tf->audioflag = 1;
flushloop=1;
}
if(e_o_s)
break;
}
}
return 0;
}
 
int FileOGG::write_samples_vorbis(double **buffer, int64_t len, int e_o_s)
{
int i,j, count = 0;
float **vorbis_buffer;
if(e_o_s)
{
vorbis_analysis_wrote (&tf->vd, 0);
} else
{
vorbis_buffer = vorbis_analysis_buffer (&tf->vd, len);
/* uninterleave samples */
for(i = 0; i<asset->channels; i++){
for (j = 0; j < len; j++){
vorbis_buffer[i][j] = buffer[i][j];
}
}
vorbis_analysis_wrote (&tf->vd, len);
}
while(vorbis_analysis_blockout (&tf->vd, &tf->vb) == 1){
/* analysis, assume we want to use bitrate management */
vorbis_analysis (&tf->vb, NULL);
vorbis_bitrate_addblock (&tf->vb);
/* weld packets into the bitstream */
while (vorbis_bitrate_flushpacket (&tf->vd, &tf->op)){
ogg_stream_packetin (&tf->vo, &tf->op);
}
 
}
tf->audioflag=1;
flush_ogg(0);
return 0;
 
 
}
 
int FileOGG::write_samples(double **buffer, int64_t len)
{
if (len > 0)
return write_samples_vorbis(buffer, len, 0);
return 0;
}
 
int FileOGG::write_frames_theora(VFrame ***frames, int len, int e_o_s)
{
// due to clumsy theora's design we need to delay writing out by one frame
// always stay one frame behind, so we can correctly encode e_o_s
 
int i, j, result = 0;
 
if(!stream) return 0;
 
if (temp_frame) // encode previous frame if available
{
yuv_buffer yuv;
yuv.y_width = tf->ti.frame_width;
yuv.y_height = tf->ti.frame_height;
yuv.y_stride = temp_frame->get_bytes_per_line();
 
yuv.uv_width = tf->ti.frame_width / 2;
yuv.uv_height = tf->ti.frame_height / 2;
yuv.uv_stride = temp_frame->get_bytes_per_line() /2;
 
yuv.y = temp_frame->get_y();
yuv.u = temp_frame->get_u();
yuv.v = temp_frame->get_v();
theora_encode_YUVin (&tf->td, &yuv);
theora_encode_packetout (&tf->td, e_o_s, &tf->op);
ogg_stream_packetin (&tf->to, &tf->op);
tf->videoflag=1;
flush_ogg(0);
}
if (!e_o_s)
{
if (!temp_frame)
{
temp_frame = new VFrame (0,
tf->ti.frame_width,
tf->ti.frame_height,
BC_YUV420P);
}
for(j = 0; j < len && !result; j++)
{
VFrame *frame = frames[0][j];
int in_color_model = frame->get_color_model();
if (in_color_model == BC_YUV422P &&
temp_frame->get_w() == frame->get_w() &&
temp_frame->get_h() == frame->get_h() &&
temp_frame->get_bytes_per_line() == frame->get_bytes_per_line())
{
temp_frame->copy_from(frame);
} else
{
 
cmodel_transfer(temp_frame->get_rows(),
frame->get_rows(),
temp_frame->get_y(),
temp_frame->get_u(),
temp_frame->get_v(),
frame->get_y(),
frame->get_u(),
frame->get_v(),
0,
0,
frame->get_w(),
frame->get_h(),
0,
0,
frame->get_w(), // temp_frame can be larger than frame if width not dividable by 16
frame->get_h(), // CHECK: does cmodel_transfer to 420 work in above situation ?
frame->get_color_model(),
BC_YUV420P,
0,
frame->get_bytes_per_line(),
temp_frame->get_bytes_per_line());
 
}
}
}
return 0;
}
 
 
int FileOGG::write_frames(VFrame ***frames, int len)
{
return write_frames_theora(frames, len, 0);
}
 
int FileOGG::colormodel_supported(int colormodel)
{
return colormodel;
}
 
 
int FileOGG::get_best_colormodel(Asset *asset, int driver)
{
switch(driver)
{
case PLAYBACK_X11:
return BC_RGB888;
break;
case PLAYBACK_X11_XV:
return BC_YUV422;
break;
case PLAYBACK_DV1394:
case PLAYBACK_FIREWIRE:
return BC_COMPRESSED;
break;
case PLAYBACK_LML:
case PLAYBACK_BUZ:
return BC_YUV422P;
break;
case VIDEO4LINUX:
case VIDEO4LINUX2:
case CAPTURE_BUZ:
case CAPTURE_LML:
case VIDEO4LINUX2JPEG:
return BC_YUV422;
break;
case CAPTURE_FIREWIRE:
return BC_COMPRESSED;
break;
}
return BC_RGB888;
}
 
 
OGGConfigAudio::OGGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
: BC_Window(PROGRAM_NAME ": Audio Compression",
parent_window->get_abs_cursor_x(1),
parent_window->get_abs_cursor_y(1),
350,
250)
{
this->parent_window = parent_window;
this->asset = asset;
}
 
OGGConfigAudio::~OGGConfigAudio()
{
 
}
 
int OGGConfigAudio::create_objects()
{
// add_tool(new BC_Title(10, 10, _("There are no audio options for this format")));
 
int x = 10, y = 10;
int x1 = 150;
char string[BCTEXTLEN];
 
add_tool(fixed_bitrate = new OGGVorbisFixedBitrate(x, y, this));
add_tool(variable_bitrate = new OGGVorbisVariableBitrate(x1, y, this));
 
y += 30;
sprintf(string, "%d", asset->vorbis_min_bitrate);
add_tool(new BC_Title(x, y, _("Min bitrate:")));
add_tool(new OGGVorbisMinBitrate(x1, y, this, string));
 
y += 30;
add_tool(new BC_Title(x, y, _("Avg bitrate:")));
sprintf(string, "%d", asset->vorbis_bitrate);
add_tool(new OGGVorbisAvgBitrate(x1, y, this, string));
 
y += 30;
add_tool(new BC_Title(x, y, _("Max bitrate:")));
sprintf(string, "%d", asset->vorbis_max_bitrate);
add_tool(new OGGVorbisMaxBitrate(x1, y, this, string));
 
 
add_subwindow(new BC_OKButton(this));
show_window();
flush();
return 0;
 
 
 
}
 
int OGGConfigAudio::close_event()
{
set_done(0);
return 1;
}
 
OGGVorbisFixedBitrate::OGGVorbisFixedBitrate(int x, int y, OGGConfigAudio *gui)
: BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Average bitrate"))
{
this->gui = gui;
}
int OGGVorbisFixedBitrate::handle_event()
{
gui->asset->vorbis_vbr = 0;
gui->variable_bitrate->update(0);
return 1;
}
 
OGGVorbisVariableBitrate::OGGVorbisVariableBitrate(int x, int y, OGGConfigAudio *gui)
: BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate"))
{
this->gui = gui;
}
int OGGVorbisVariableBitrate::handle_event()
{
gui->asset->vorbis_vbr = 1;
gui->fixed_bitrate->update(0);
return 1;
}
 
 
OGGVorbisMinBitrate::OGGVorbisMinBitrate(int x,
int y,
OGGConfigAudio *gui,
char *text)
: BC_TextBox(x, y, 180, 1, text)
{
this->gui = gui;
}
int OGGVorbisMinBitrate::handle_event()
{
gui->asset->vorbis_min_bitrate = atol(get_text());
return 1;
}
 
 
 
OGGVorbisMaxBitrate::OGGVorbisMaxBitrate(int x,
int y,
OGGConfigAudio *gui,
char *text)
: BC_TextBox(x, y, 180, 1, text)
{
this->gui = gui;
}
int OGGVorbisMaxBitrate::handle_event()
{
gui->asset->vorbis_max_bitrate = atol(get_text());
return 1;
}
 
 
 
OGGVorbisAvgBitrate::OGGVorbisAvgBitrate(int x, int y, OGGConfigAudio *gui, char *text)
: BC_TextBox(x, y, 180, 1, text)
{
this->gui = gui;
}
int OGGVorbisAvgBitrate::handle_event()
{
gui->asset->vorbis_bitrate = atol(get_text());
return 1;
}
 
 
 
 
 
OGGConfigVideo::OGGConfigVideo(BC_WindowBase *parent_window, Asset *asset)
: BC_Window(PROGRAM_NAME ": Video Compression",
parent_window->get_abs_cursor_x(1),
parent_window->get_abs_cursor_y(1),
450,
220)
{
this->parent_window = parent_window;
this->asset = asset;
}
 
OGGConfigVideo::~OGGConfigVideo()
{
 
}
 
int OGGConfigVideo::create_objects()
{
// add_tool(new BC_Title(10, 10, _("There are no video options for this format")));
int x = 10, y = 10;
int x1 = x + 150;
int x2 = x + 300;
 
add_subwindow(new BC_Title(x, y + 5, _("Bitrate:")));
add_subwindow(new OGGTheoraBitrate(x1, y, this));
add_subwindow(fixed_bitrate = new OGGTheoraFixedBitrate(x2, y, this));
y += 30;
 
add_subwindow(new BC_Title(x, y, _("Quality:")));
add_subwindow(new BC_ISlider(x + 80,
y,
0,
200,
200,
0,
63,
asset->theora_quality,
0,
0,
&asset->theora_quality));
 
add_subwindow(fixed_quality = new OGGTheoraFixedQuality(x2, y, this));
y += 30;
 
add_subwindow(new BC_Title(x, y, _("Keyframe frequency:")));
OGGTheoraKeyframeFrequency *keyframe_frequency =
new OGGTheoraKeyframeFrequency(x1 + 60, y, this);
keyframe_frequency->create_objects();
y += 30;
add_subwindow(new BC_Title(x, y, _("Keyframe force frequency:")));
OGGTheoraKeyframeForceFrequency *keyframe_force_frequency =
new OGGTheoraKeyframeForceFrequency(x1 + 60, y, this);
keyframe_force_frequency->create_objects();
y += 30;
 
add_subwindow(new BC_Title(x, y, _("Sharpness:")));
OGGTheoraSharpness *sharpness =
new OGGTheoraSharpness(x1 + 60, y, this);
sharpness->create_objects();
y += 30;
 
add_subwindow(new BC_OKButton(this));
return 0;
}
 
 
 
 
int OGGConfigVideo::close_event()
{
set_done(0);
return 1;
}
 
OGGTheoraBitrate::OGGTheoraBitrate(int x, int y, OGGConfigVideo *gui)
: BC_TextBox(x, y, 100, 1, gui->asset->theora_bitrate)
{
this->gui = gui;
}
 
 
int OGGTheoraBitrate::handle_event()
{
// TODO: MIN / MAX check
gui->asset->theora_bitrate = atol(get_text());
return 1;
};
 
 
 
 
OGGTheoraFixedBitrate::OGGTheoraFixedBitrate(int x, int y, OGGConfigVideo *gui)
: BC_Radial(x, y, gui->asset->theora_fix_bitrate, _("Fixed bitrate"))
{
this->gui = gui;
}
 
int OGGTheoraFixedBitrate::handle_event()
{
update(1);
gui->asset->theora_fix_bitrate = 1;
gui->fixed_quality->update(0);
return 1;
};
 
OGGTheoraFixedQuality::OGGTheoraFixedQuality(int x, int y, OGGConfigVideo *gui)
: BC_Radial(x, y, !gui->asset->theora_fix_bitrate, _("Fixed quality"))
{
this->gui = gui;
}
 
int OGGTheoraFixedQuality::handle_event()
{
update(1);
gui->asset->theora_fix_bitrate = 0;
gui->fixed_bitrate->update(0);
return 1;
};
 
OGGTheoraKeyframeFrequency::OGGTheoraKeyframeFrequency(int x, int y, OGGConfigVideo *gui)
: BC_TumbleTextBox(gui,
(int64_t)gui->asset->theora_keyframe_frequency,
(int64_t)1,
(int64_t)500,
x,
y,
40)
{
this->gui = gui;
}
 
int OGGTheoraKeyframeFrequency::handle_event()
{
gui->asset->theora_keyframe_frequency = atol(get_text());
return 1;
}
 
OGGTheoraKeyframeForceFrequency::OGGTheoraKeyframeForceFrequency(int x, int y, OGGConfigVideo *gui)
: BC_TumbleTextBox(gui,
(int64_t)gui->asset->theora_keyframe_frequency,
(int64_t)1,
(int64_t)500,
x,
y,
40)
{
this->gui = gui;
}
 
int OGGTheoraKeyframeForceFrequency::handle_event()
{
gui->asset->theora_keyframe_frequency = atol(get_text());
return 1;
}
 
 
OGGTheoraSharpness::OGGTheoraSharpness(int x, int y, OGGConfigVideo *gui)
: BC_TumbleTextBox(gui,
(int64_t)gui->asset->theora_sharpness,
(int64_t)0,
(int64_t)2,
x,
y,
40)
{
this->gui = gui;
}
 
int OGGTheoraSharpness::handle_event()
{
gui->asset->theora_sharpness = atol(get_text());
return 1;
}
 
 
/branches/automake-1_1_5/hvirtual/cinelerra/tipwindow.C
New file
0,0 → 1,261
#include "bcdisplayinfo.h"
#include "bcsignals.h"
#include "keys.h"
#include "language.h"
#include "mainsession.h"
#include "mwindow.h"
#include "preferences.h"
#include "theme.h"
#include "tipwindow.h"
 
 
 
// Table of tips of the day
static char *tips[] =
{
"When configuring slow effects, disable playback for the track. After configuring it,\n"
"re-enable playback to process a single frame.",
 
"Ctrl + any transport command causes playback to only cover\n"
"the region defined by the in/out points.",
 
"Shift + clicking a patch causes all other patches except the\n"
"selected one to toggle.",
 
"Clicking on a patch and dragging across other tracks causes\n"
"the other patches to match the first one.",
 
"Shift + clicking on an effect boundary causes dragging to affect\n"
"just the one effect.",
 
"Load multiple files by clicking on one file and shift + clicking on\n"
"another file. Ctrl + clicking toggles individual files.",
 
"Ctrl + left clicking on the time bar cycles forward a time format.\n"
"Ctrl + middle clicking on the time bar cycles backward a time format.",
 
"Use the +/- keys in the Compositor window to zoom in and out.\n",
 
"Pressing Alt while clicking in the cropping window causes translation of\n"
"all 4 points.\n",
 
"Pressing Tab over a track toggles the Record status.\n"
"Pressing Shift-Tab over a track toggles the Record status of all the other tracks.\n"
};
 
static int total_tips = sizeof(tips) / sizeof(char*);
 
 
 
 
TipWindow::TipWindow(MWindow *mwindow)
: BC_DialogThread()
{
this->mwindow = mwindow;
}
 
BC_Window* TipWindow::new_gui()
{
BC_DisplayInfo display_info;
int x = display_info.get_abs_cursor_x();
int y = display_info.get_abs_cursor_y();
TipWindowGUI *gui = this->gui = new TipWindowGUI(mwindow,
this,
x,
y);
gui->create_objects();
return gui;
}
 
char* TipWindow::get_current_tip()
{
CLAMP(mwindow->session->current_tip, 0, total_tips - 1);
char *result = tips[mwindow->session->current_tip];
mwindow->session->current_tip++;
if(mwindow->session->current_tip >= total_tips)
mwindow->session->current_tip = 0;
mwindow->save_defaults();
return result;
}
 
void TipWindow::next_tip()
{
gui->tip_text->update(get_current_tip());
}
 
void TipWindow::prev_tip()
{
for(int i = 0; i < 2; i++)
{
mwindow->session->current_tip--;
if(mwindow->session->current_tip < 0)
mwindow->session->current_tip = total_tips - 1;
}
 
gui->tip_text->update(get_current_tip());
}
 
 
 
 
 
 
TipWindowGUI::TipWindowGUI(MWindow *mwindow,
TipWindow *thread,
int x,
int y)
: BC_Window(PROGRAM_NAME ": Tip of the day",
x,
y,
640,
100,
640,
100,
0,
0,
1)
{
this->mwindow = mwindow;
this->thread = thread;
}
 
void TipWindowGUI::create_objects()
{
int x = 10, y = 10;
SET_TRACE
add_subwindow(tip_text = new BC_Title(x, y, thread->get_current_tip()));
y = get_h() - 30;
SET_TRACE
BC_CheckBox *checkbox;
add_subwindow(checkbox = new TipDisable(mwindow, this, x, y));
SET_TRACE
BC_Button *button;
y = get_h() - TipClose::calculate_h(mwindow) - 10;
x = get_w() - TipClose::calculate_w(mwindow) - 10;
add_subwindow(button = new TipClose(mwindow, this, x, y));
SET_TRACE
x -= TipNext::calculate_w(mwindow) + 10;
add_subwindow(button = new TipNext(mwindow, this, x, y));
SET_TRACE
x -= TipPrev::calculate_w(mwindow) + 10;
add_subwindow(button = new TipPrev(mwindow, this, x, y));
SET_TRACE
x += button->get_w() + 10;
 
show_window();
raise_window();
}
 
int TipWindowGUI::keypress_event()
{
switch(get_keypress())
{
case RETURN:
case ESC:
case 'w':
set_done(0);
break;
}
return 0;
}
 
 
 
 
 
 
 
TipDisable::TipDisable(MWindow *mwindow, TipWindowGUI *gui, int x, int y)
: BC_CheckBox(x,
y,
mwindow->preferences->use_tipwindow,
_("Show tip of the day."))
{
this->mwindow = mwindow;
this->gui = gui;
}
 
int TipDisable::handle_event()
{
mwindow->preferences->use_tipwindow = get_value();
return 1;
}
 
 
 
TipNext::TipNext(MWindow *mwindow, TipWindowGUI *gui, int x, int y)
: BC_Button(x,
y,
mwindow->theme->get_image_set("next_tip"))
{
this->mwindow = mwindow;
this->gui = gui;
set_tooltip(_("Next tip"));
}
int TipNext::handle_event()
{
gui->thread->next_tip();
return 1;
}
 
int TipNext::calculate_w(MWindow *mwindow)
{
return mwindow->theme->get_image_set("next_tip")[0]->get_w();
}
 
 
 
 
 
 
TipPrev::TipPrev(MWindow *mwindow, TipWindowGUI *gui, int x, int y)
: BC_Button(x, y, mwindow->theme->get_image_set("prev_tip"))
{
this->mwindow = mwindow;
this->gui = gui;
set_tooltip(_("Previous tip"));
}
 
int TipPrev::handle_event()
{
gui->thread->prev_tip();
return 1;
}
int TipPrev::calculate_w(MWindow *mwindow)
{
return mwindow->theme->get_image_set("prev_tip")[0]->get_w();
}
 
 
 
 
 
 
 
 
 
TipClose::TipClose(MWindow *mwindow, TipWindowGUI *gui, int x, int y)
: BC_Button(x, y, mwindow->theme->get_image_set("close_tip"))
{
this->mwindow = mwindow;
this->gui = gui;
set_tooltip(_("Close"));
}
 
int TipClose::handle_event()
{
gui->set_done(0);
return 1;
}
 
int TipClose::calculate_w(MWindow *mwindow)
{
return mwindow->theme->get_image_set("close_tip")[0]->get_w();
}
int TipClose::calculate_h(MWindow *mwindow)
{
return mwindow->theme->get_image_set("close_tip")[0]->get_h();
}
 
 
 
/branches/automake-1_1_5/hvirtual/cinelerra/filecr2.inc
New file
0,0 → 1,8
#ifndef FILECR2_INC
#define FILECR2_INC
 
 
class FileCR2;
 
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/fileogg.h
New file
0,0 → 1,229
#ifndef FILEOGG_H
#define FILEOGG_H
 
#include "../config.h"
#include "filebase.h"
#include "file.inc"
 
#include <theora/theora.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisenc.h>
 
 
#include <libdv/dv.h>
 
// TODO: Do we need a thread for audio/video encoding?
 
typedef struct
{
int scale;
int wide;
double start;
double end;
ogg_page videopage;
ogg_page audiopage;
int audioflag;
int videoflag;
double audiotime;
double videotime;
// int vkbps;
// int akbps;
ogg_int64_t audio_bytesout;
ogg_int64_t video_bytesout;
 
ogg_stream_state to; /* take physical pages, weld into a logical
* stream of packets */
ogg_stream_state vo; /* take physical pages, weld into a logical
* stream of packets */
ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
ogg_packet op; /* one raw packet of data for decode */
 
theora_info ti;
theora_comment tc;
theora_state td;
 
 
vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */
vorbis_comment vc; /* struct that stores all the user comments */
 
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
vorbis_block vb; /* local working space for packet->PCM decode */
}
theoraframes_info_t;
 
class FileOGG : public FileBase
{
public:
FileOGG(Asset *asset, File *file);
~FileOGG();
 
static void get_parameters(BC_WindowBase *parent_window,
Asset *asset,
BC_WindowBase* &format_window,
int audio_options,
int video_options);
int reset_parameters_derived();
int open_file(int rd, int wr);
static int check_sig(Asset *asset);
int close_file();
int close_file_derived();
int64_t get_video_position();
int64_t get_audio_position();
int set_video_position(int64_t x);
int set_audio_position(int64_t x);
int write_samples(double **buffer, int64_t len);
int write_frames(VFrame ***frames, int len);
int colormodel_supported(int colormodel);
static int get_best_colormodel(Asset *asset, int driver);
private:
int write_samples_vorbis(double **buffer, int64_t len, int e_o_s);
int write_frames_theora(VFrame ***frames, int len, int e_o_s);
int flush_ogg(int e_o_s);
FILE *stream;
theoraframes_info_t *tf;
VFrame *temp_frame;
};
 
class OGGConfigAudio;
class OGGConfigVideo;
 
class OGGVorbisFixedBitrate : public BC_Radial
{
public:
OGGVorbisFixedBitrate(int x, int y, OGGConfigAudio *gui);
int handle_event();
OGGConfigAudio *gui;
};
 
class OGGVorbisVariableBitrate : public BC_Radial
{
public:
OGGVorbisVariableBitrate(int x, int y, OGGConfigAudio *gui);
int handle_event();
OGGConfigAudio *gui;
};
 
class OGGVorbisMinBitrate : public BC_TextBox
{
public:
OGGVorbisMinBitrate(int x,
int y,
OGGConfigAudio *gui,
char *text);
int handle_event();
OGGConfigAudio *gui;
};
 
class OGGVorbisMaxBitrate : public BC_TextBox
{
public:
OGGVorbisMaxBitrate(int x,
int y,
OGGConfigAudio *gui,
char *text);
int handle_event();
OGGConfigAudio *gui;
};
 
class OGGVorbisAvgBitrate : public BC_TextBox
{
public:
OGGVorbisAvgBitrate(int x,
int y,
OGGConfigAudio *gui,
char *text);
int handle_event();
OGGConfigAudio *gui;
};
 
 
class OGGConfigAudio: public BC_Window
{
public:
OGGConfigAudio(BC_WindowBase *parent_window, Asset *asset);
~OGGConfigAudio();
 
int create_objects();
int close_event();
 
Asset *asset;
OGGVorbisFixedBitrate *fixed_bitrate;
OGGVorbisVariableBitrate *variable_bitrate;
private:
BC_WindowBase *parent_window;
char string[BCTEXTLEN];
};
 
 
class OGGTheoraBitrate : public BC_TextBox
{
public:
OGGTheoraBitrate(int x, int y, OGGConfigVideo *gui);
int handle_event();
OGGConfigVideo *gui;
};
 
class OGGTheoraKeyframeFrequency : public BC_TumbleTextBox
{
public:
OGGTheoraKeyframeFrequency(int x, int y, OGGConfigVideo *gui);
int handle_event();
OGGConfigVideo *gui;
};
 
class OGGTheoraKeyframeForceFrequency : public BC_TumbleTextBox
{
public:
OGGTheoraKeyframeForceFrequency(int x, int y, OGGConfigVideo *gui);
int handle_event();
OGGConfigVideo *gui;
};
 
class OGGTheoraSharpness : public BC_TumbleTextBox
{
public:
OGGTheoraSharpness(int x, int y, OGGConfigVideo *gui);
int handle_event();
OGGConfigVideo *gui;
};
 
class OGGTheoraFixedBitrate : public BC_Radial
{
public:
OGGTheoraFixedBitrate(int x, int y, OGGConfigVideo *gui);
int handle_event();
OGGConfigVideo *gui;
};
 
class OGGTheoraFixedQuality : public BC_Radial
{
public:
OGGTheoraFixedQuality(int x, int y, OGGConfigVideo *gui);
int handle_event();
OGGConfigVideo *gui;
};
 
 
 
class OGGConfigVideo: public BC_Window
{
public:
OGGConfigVideo(BC_WindowBase *parent_window, Asset *asset);
~OGGConfigVideo();
 
int create_objects();
int close_event();
 
OGGTheoraFixedBitrate *fixed_bitrate;
OGGTheoraFixedQuality *fixed_quality;
Asset *asset;
private:
BC_WindowBase *parent_window;
};
 
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/gwindowgui.C
New file
0,0 → 1,297
#include "autoconf.h"
#include "bcsignals.h"
#include "clip.h"
#include "edl.h"
#include "edlsession.h"
#include "gwindowgui.h"
#include "mainmenu.h"
#include "mainsession.h"
#include "mwindow.h"
#include "mwindowgui.h"
#include "trackcanvas.h"
 
 
 
 
 
GWindowGUI::GWindowGUI(MWindow *mwindow,
int w,
int h)
: BC_Window(PROGRAM_NAME ": Overlays",
mwindow->session->gwindow_x,
mwindow->session->gwindow_y,
w,
h,
w,
h,
0,
0,
1)
{
this->mwindow = mwindow;
}
 
static char *other_text[OTHER_TOGGLES] =
{
"Assets",
"Titles",
"Transitions",
"Plugin Autos"
};
 
static char *auto_text[] =
{
"Mute",
"Camera X",
"Camera Y",
"Camera Z",
"Projector X",
"Projector Y",
"Projector Z",
"Fade",
"Pan",
"Mode",
"Mask",
"Nudge"
};
 
void GWindowGUI::calculate_extents(BC_WindowBase *gui, int *w, int *h)
{
int temp1, temp2, temp3, temp4, temp5, temp6, temp7;
int current_w, current_h;
*w = 10;
*h = 10;
for(int i = 0; i < OTHER_TOGGLES; i++)
{
BC_Toggle::calculate_extents(gui,
BC_WindowBase::get_resources()->checkbox_images,
0,
&temp1,
&current_w,
&current_h,
&temp2,
&temp3,
&temp4,
&temp5,
&temp6,
&temp7,
other_text[i]);
*w = MAX(current_w, *w);
*h += current_h + 5;
}
 
for(int i = 0; i < AUTOMATION_TOTAL; i++)
{
BC_Toggle::calculate_extents(gui,
BC_WindowBase::get_resources()->checkbox_images,
0,
&temp1,
&current_w,
&current_h,
&temp2,
&temp3,
&temp4,
&temp5,
&temp6,
&temp7,
auto_text[i]);
*w = MAX(current_w, *w);
*h += current_h + 5;
}
*h += 10;
*w += 20;
}
 
 
 
void GWindowGUI::create_objects()
{
int x = 10, y = 10;
 
 
for(int i = 0; i < OTHER_TOGGLES; i++)
{
add_tool(other[i] = new GWindowToggle(mwindow,
this,
x,
y,
-1,
i,
other_text[i]));
y += other[i]->get_h() + 5;
}
 
for(int i = 0; i < AUTOMATION_TOTAL; i++)
{
add_tool(auto_toggle[i] = new GWindowToggle(mwindow,
this,
x,
y,
i,
-1,
auto_text[i]));
y += auto_toggle[i]->get_h() + 5;
}
}
 
void GWindowGUI::update_mwindow()
{
unlock_window();
mwindow->gui->mainmenu->update_toggles(1);
lock_window("GWindowGUI::update_mwindow");
}
 
void GWindowGUI::update_toggles(int use_lock)
{
if(use_lock) lock_window("GWindowGUI::update_toggles");
 
for(int i = 0; i < OTHER_TOGGLES; i++)
{
other[i]->update();
}
 
for(int i = 0; i < AUTOMATION_TOTAL; i++)
{
auto_toggle[i]->update();
}
 
if(use_lock) unlock_window();
}
 
int GWindowGUI::translation_event()
{
mwindow->session->gwindow_x = get_x();
mwindow->session->gwindow_y = get_y();
return 0;
}
 
int GWindowGUI::close_event()
{
hide_window();
mwindow->session->show_gwindow = 0;
unlock_window();
 
mwindow->gui->lock_window("GWindowGUI::close_event");
mwindow->gui->mainmenu->show_gwindow->set_checked(0);
mwindow->gui->unlock_window();
 
lock_window("GWindowGUI::close_event");
mwindow->save_defaults();
return 1;
}
 
int GWindowGUI::keypress_event()
{
switch(get_keypress())
{
case 'w':
case 'W':
if(ctrl_down())
{
close_event();
return 1;
}
break;
}
return 0;
}
 
 
 
 
 
 
GWindowToggle::GWindowToggle(MWindow *mwindow,
GWindowGUI *gui,
int x,
int y,
int subscript,
int other,
char *text)
: BC_CheckBox(x,
y,
*get_main_value(mwindow, subscript, other),
text)
{
this->mwindow = mwindow;
this->gui = gui;
this->subscript = subscript;
this->other = other;
}
 
int GWindowToggle::handle_event()
{
*get_main_value(mwindow, subscript, other) = get_value();
gui->update_mwindow();
 
 
// Update stuff in MWindow
unlock_window();
mwindow->gui->lock_window("GWindowToggle::handle_event");
if(subscript >= 0)
{
mwindow->gui->canvas->draw_overlays();
mwindow->gui->canvas->flash();
}
else
{
switch(other)
{
case ASSETS:
case TITLES:
mwindow->gui->update(1,
1,
0,
0,
1,
0,
0);
break;
 
case TRANSITIONS:
case PLUGIN_AUTOS:
mwindow->gui->canvas->draw_overlays();
mwindow->gui->canvas->flash();
break;
}
}
 
mwindow->gui->unlock_window();
lock_window("GWindowToggle::handle_event");
 
return 1;
}
 
int* GWindowToggle::get_main_value(MWindow *mwindow, int subscript, int other)
{
if(subscript >= 0)
{
return &mwindow->edl->session->auto_conf->autos[subscript];
}
else
{
switch(other)
{
case ASSETS:
return &mwindow->edl->session->show_assets;
break;
case TITLES:
return &mwindow->edl->session->show_titles;
break;
case TRANSITIONS:
return &mwindow->edl->session->auto_conf->transitions;
break;
case PLUGIN_AUTOS:
return &mwindow->edl->session->auto_conf->plugins;
break;
}
}
}
 
void GWindowToggle::update()
{
set_value(*get_main_value(mwindow, subscript, other));
}
 
 
 
/branches/automake-1_1_5/hvirtual/cinelerra/filecr2.C
New file
0,0 → 1,123
#include "asset.h"
#include "colormodels.h"
#include "filecr2.h"
#include "mutex.h"
#include <string.h>
#include <unistd.h>
 
// Only allow one instance of the decoder to run simultaneously.
static Mutex cr2_mutex;
 
 
FileCR2::FileCR2(Asset *asset, File *file)
: FileBase(asset, file)
{
reset();
}
 
FileCR2::~FileCR2()
{
close_file();
}
 
 
void FileCR2::reset()
{
}
 
int FileCR2::check_sig(Asset *asset)
{
cr2_mutex.lock("FileCR2::check_sig");
char string[BCTEXTLEN];
int argc = 3;
 
strcpy(string, asset->path);
 
char *argv[4];
argv[0] = "dcraw";
argv[1] = "-i";
argv[2] = string;
argv[3] = 0;
 
int result = dcraw_main(argc, argv);
 
cr2_mutex.unlock();
 
return !result;
}
 
int FileCR2::open_file(int rd, int wr)
{
cr2_mutex.lock("FileCR2::check_sig");
 
int argc = 3;
char *argv[3] =
{
"dcraw",
"-i",
asset->path
};
 
int result = dcraw_main(argc, argv);
if(!result) format_to_asset();
 
cr2_mutex.unlock();
return result;
}
 
 
int FileCR2::close_file()
{
return 0;
}
 
void FileCR2::format_to_asset()
{
asset->video_data = 1;
asset->layers = 1;
sscanf(dcraw_info, "%d %d", &asset->width, &asset->height);
if(!asset->frame_rate) asset->frame_rate = 1;
asset->video_length = -1;
}
 
 
int FileCR2::read_frame(VFrame *frame)
{
cr2_mutex.lock("FileCR2::check_sig");
if(frame->get_color_model() == BC_RGBA_FLOAT)
dcraw_alpha = 1;
else
dcraw_alpha = 0;
 
 
// output to stdout
int argc = 3;
char *argv[3] =
{
"dcraw",
"-c",
asset->path
};
dcraw_data = (float**)frame->get_rows();
 
int result = dcraw_main(argc, argv);
 
cr2_mutex.unlock();
return 0;
}
 
int FileCR2::colormodel_supported(int colormodel)
{
if(colormodel == BC_RGB_FLOAT ||
colormodel == BC_RGBA_FLOAT)
return colormodel;
return BC_RGB_FLOAT;
}
 
 
 
 
 
 
 
 
/branches/automake-1_1_5/hvirtual/cinelerra/tipwindow.h
New file
0,0 → 1,85
#ifndef TIPWINDOW_H
#define TIPWINDOW_H
 
#include "bcdialog.h"
#include "guicast.h"
#include "mwindow.inc"
#include "tipwindow.inc"
 
 
 
// Tip of the day to be run at initialization
 
 
class TipWindow : public BC_DialogThread
{
public:
TipWindow(MWindow *mwindow);
 
BC_Window* new_gui();
char* get_current_tip();
void next_tip();
void prev_tip();
 
MWindow *mwindow;
TipWindowGUI *gui;
};
 
 
class TipWindowGUI : public BC_Window
{
public:
TipWindowGUI(MWindow *mwindow,
TipWindow *thread,
int x,
int y);
void create_objects();
int keypress_event();
MWindow *mwindow;
TipWindow *thread;
BC_Title *tip_text;
};
 
class TipDisable : public BC_CheckBox
{
public:
TipDisable(MWindow *mwindow, TipWindowGUI *gui, int x, int y);
int handle_event();
TipWindowGUI *gui;
MWindow *mwindow;
};
 
class TipNext : public BC_Button
{
public:
TipNext(MWindow *mwindow, TipWindowGUI *gui, int x, int y);
int handle_event();
static int calculate_w(MWindow *mwindow);
TipWindowGUI *gui;
MWindow *mwindow;
};
 
class TipPrev : public BC_Button
{
public:
TipPrev(MWindow *mwindow, TipWindowGUI *gui, int x, int y);
int handle_event();
static int calculate_w(MWindow *mwindow);
TipWindowGUI *gui;
MWindow *mwindow;
};
 
class TipClose : public BC_Button
{
public:
TipClose(MWindow *mwindow, TipWindowGUI *gui, int x, int y);
int handle_event();
static int calculate_w(MWindow *mwindow);
static int calculate_h(MWindow *mwindow);
TipWindowGUI *gui;
MWindow *mwindow;
};
 
 
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/iec61883output.C
New file
0,0 → 1,542
#ifdef HAVE_FIREWIRE
 
 
 
#include "audiodevice.h"
#include "condition.h"
#include "iec61883output.h"
#include "mutex.h"
#include "playbackconfig.h"
#include "bctimer.h"
#include "vframe.h"
#include "videodevice.h"
 
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/utsname.h>
 
 
 
 
 
// Crazy DV internals
#define CIP_N_NTSC 2436
#define CIP_D_NTSC 38400
#define CIP_N_PAL 1
#define CIP_D_PAL 16
#define OUTPUT_SAMPLES 262144
#define BUFFER_TIMEOUT 500000
 
 
IEC61883Output::IEC61883Output(AudioDevice *adevice)
: Thread(1, 0, 0)
{
reset();
this->adevice = adevice;
}
 
IEC61883Output::IEC61883Output(VideoDevice *vdevice)
: Thread(1, 0, 0)
{
reset();
this->vdevice = vdevice;
}
 
IEC61883Output::~IEC61883Output()
{
if(Thread::running())
{
done = 1;
start_lock->unlock();
Thread::cancel();
Thread::join();
}
 
if(buffer)
{
for(int i = 0; i < total_buffers; i++)
{
if(buffer[i]) delete [] buffer[i];
}
delete [] buffer;
delete [] buffer_size;
delete [] buffer_valid;
}
 
if(audio_lock) delete audio_lock;
if(video_lock) delete video_lock;
if(start_lock) delete start_lock;
if(audio_buffer) delete [] audio_buffer;
 
if(temp_frame) delete temp_frame;
if(temp_frame2) delete temp_frame2;
if(video_encoder) dv_delete(video_encoder);
if(audio_encoder) dv_delete(audio_encoder);
if(buffer_lock) delete buffer_lock;
if(position_lock) delete position_lock;
if(frame) iec61883_dv_close(frame);
if(handle) raw1394_destroy_handle(handle);
}
 
 
void IEC61883Output::reset()
{
handle = 0;
fd = 0;
frame = 0;
out_position = 0;
out_buffer = 0;
out_size = 0;
 
buffer = 0;
buffer_size = 0;
total_buffers = 0;
current_inbuffer = 0;
current_outbuffer = 0;
done = 0;
audio_lock = 0;
video_lock = 0;
start_lock = 0;
buffer_lock = 0;
position_lock = 0;
video_encoder = 0;
audio_encoder = 0;
audio_buffer = 0;
audio_samples = 0;
temp_frame = 0;
temp_frame2 = 0;
audio_position = 0;
interrupted = 0;
have_video = 0;
adevice = 0;
vdevice = 0;
is_pal = 0;
}
 
 
 
static int read_frame_static(unsigned char *data, int n, unsigned int dropped, void *ptr)
{
IEC61883Output *output = (IEC61883Output*)ptr;
return output->read_frame(data, n, dropped);
}
 
 
 
 
 
int IEC61883Output::open(int port,
int channel,
int length,
int channels,
int bits,
int samplerate,
int syt)
{
this->channels = channels;
this->bits = bits;
this->samplerate = samplerate;
this->total_buffers = length;
this->syt = syt;
 
// Set PAL mode based on frame height
if(vdevice) is_pal = (vdevice->out_h == 576);
 
 
 
 
if(!handle)
{
handle = raw1394_new_handle_on_port(port);
if(handle)
{
frame = iec61883_dv_xmit_init(handle,
is_pal,
read_frame_static,
(void *)this);
if(frame)
{
if(!iec61883_dv_xmit_start(frame, channel))
{
fd = raw1394_get_fd(handle);
}
}
}
 
// Create buffers
buffer = new char*[total_buffers];
for(int i = 0; i < length; i++)
buffer[i] = new char[DV_PAL_SIZE];
buffer_size = new int[total_buffers];
buffer_valid = new int[total_buffers];
bzero(buffer_size, sizeof(int) * total_buffers);
bzero(buffer_valid, sizeof(int) * total_buffers);
bzero(buffer, sizeof(char*) * total_buffers);
video_lock = new Condition(0, "IEC61883Output::video_lock");
audio_lock = new Condition(0, "IEC61883Output::audio_lock");
start_lock = new Condition(0, "IEC61883Output::start_lock");
buffer_lock = new Mutex("IEC61883Output::buffer_lock");
position_lock = new Mutex("IEC61883Output::position_lock");
encoder = dv_new();
audio_buffer = new char[OUTPUT_SAMPLES * channels * bits / 8];
Thread::start();
}
return 0;
}
 
void IEC61883Output::run()
{
Thread::enable_cancel();
start_lock->lock("IEC61883Output::run");
Thread::disable_cancel();
 
while(!done)
{
struct timeval tv;
fd_set rfds;
FD_ZERO (&rfds);
FD_SET (fd, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 20000;
if(select(fd + 1, &rfds, 0, 0, &tv) > 0)
raw1394_loop_iterate (handle);
}
}
 
 
 
int IEC61883Output::read_frame(unsigned char *data, int n, unsigned int dropped)
{
// Next frame
if(!out_buffer || out_position + 480 > out_size)
{
buffer_lock->lock("IEC61883Output read_frame 1");
 
out_buffer = buffer[current_outbuffer];
out_size = buffer_size[current_outbuffer];
out_position = 0;
 
 
// No video. Put in a fake frame for audio only
if(!have_video)
{
#include "data/fake_ntsc_dv.h"
out_size = sizeof(fake_ntsc_dv) - 4;
out_buffer = (char*)fake_ntsc_dv + 4;
}
 
 
 
 
 
 
 
 
// Calculate number of samples needed based on given pattern for
// norm.
int samples_per_frame = 2048;
 
// Encode audio
if(audio_samples > samples_per_frame)
{
int samples_written = dv_write_audio(encoder,
(unsigned char*)out_buffer,
(unsigned char*)audio_buffer,
samples_per_frame,
channels,
bits,
samplerate,
is_pal ? DV_PAL : DV_NTSC);
memcpy(audio_buffer,
audio_buffer + samples_written * bits * channels / 8,
(audio_samples - samples_written) * bits * channels / 8);
audio_samples -= samples_written;
position_lock->lock("IEC61883Output::run");
audio_position += samples_written;
position_lock->unlock();
 
 
audio_lock->unlock();
}
 
 
buffer_lock->unlock();
}
 
 
 
 
// Write next chunk of current frame
if(out_buffer && out_position + 480 <= out_size)
{
memcpy(data, out_buffer + out_position, 480);
out_position += 480;
 
 
 
if(out_position >= out_size)
{
buffer_lock->lock("IEC61883Output read_frame 2");
buffer_valid[current_outbuffer] = 0;
 
// Advance buffer number if possible
increment_counter(&current_outbuffer);
 
// Reuse same buffer next time
if(!buffer_valid[current_outbuffer])
{
decrement_counter(&current_outbuffer);
}
else
// Wait for user to reach current buffer before unlocking any more.
{
video_lock->unlock();
}
 
buffer_lock->unlock();
}
}
}
 
 
 
 
void IEC61883Output::write_frame(VFrame *input)
{
VFrame *ptr = 0;
int result = 0;
 
//printf("IEC61883Output::write_frame 1\n");
 
if(fd <= 0) return;
if(interrupted) return;
 
// Encode frame to DV
if(input->get_color_model() != BC_COMPRESSED)
{
if(!temp_frame) temp_frame = new VFrame;
if(!encoder) encoder = dv_new();
ptr = temp_frame;
 
// Exact resolution match. Don't do colorspace conversion
if(input->get_color_model() == BC_YUV422 &&
input->get_w() == 720 &&
(input->get_h() == 480 ||
input->get_h() == 576))
{
int norm = is_pal ? DV_PAL : DV_NTSC;
int data_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
temp_frame->allocate_compressed_data(data_size);
temp_frame->set_compressed_size(data_size);
 
dv_write_video(encoder,
temp_frame->get_data(),
input->get_rows(),
BC_YUV422,
norm);
ptr = temp_frame;
}
else
// Convert resolution and color model before compressing
{
if(!temp_frame2)
{
int h = input->get_h();
// Default to NTSC if unknown
if(h != 480 && h != 576) h = 480;
 
temp_frame2 = new VFrame(0,
720,
h,
BC_YUV422);
}
 
int norm = is_pal ? DV_PAL : DV_NTSC;
int data_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
temp_frame->allocate_compressed_data(data_size);
temp_frame->set_compressed_size(data_size);
 
 
cmodel_transfer(temp_frame2->get_rows(), /* Leave NULL if non existent */
input->get_rows(),
temp_frame2->get_y(), /* Leave NULL if non existent */
temp_frame2->get_u(),
temp_frame2->get_v(),
input->get_y(), /* Leave NULL if non existent */
input->get_u(),
input->get_v(),
0, /* Dimensions to capture from input frame */
0,
MIN(temp_frame2->get_w(), input->get_w()),
MIN(temp_frame2->get_h(), input->get_h()),
0, /* Dimensions to project on output frame */
0,
MIN(temp_frame2->get_w(), input->get_w()),
MIN(temp_frame2->get_h(), input->get_h()),
input->get_color_model(),
BC_YUV422,
0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
input->get_bytes_per_line(), /* For planar use the luma rowspan */
temp_frame2->get_bytes_per_line()); /* For planar use the luma rowspan */
 
dv_write_video(encoder,
temp_frame->get_data(),
temp_frame2->get_rows(),
BC_YUV422,
norm);
 
 
 
ptr = temp_frame;
}
}
else
ptr = input;
 
 
 
 
 
 
 
 
 
 
 
// Take over buffer table
buffer_lock->lock("IEC61883Output::write_frame 1");
have_video = 1;
// Wait for buffer to become available with timeout
while(buffer_valid[current_inbuffer] && !result && !interrupted)
{
buffer_lock->unlock();
result = video_lock->timed_lock(BUFFER_TIMEOUT);
buffer_lock->lock("IEC61883Output::write_frame 2");
}
 
 
 
// Write buffer if there's room
if(!buffer_valid[current_inbuffer])
{
if(!buffer[current_inbuffer])
{
buffer[current_inbuffer] = new char[ptr->get_compressed_size()];
buffer_size[current_inbuffer] = ptr->get_compressed_size();
}
memcpy(buffer[current_inbuffer], ptr->get_data(), ptr->get_compressed_size());
buffer_valid[current_inbuffer] = 1;
increment_counter(&current_inbuffer);
}
else
// Ignore it if there isn't room.
{
;
}
 
buffer_lock->unlock();
start_lock->unlock();
//printf("IEC61883Output::write_frame 100\n");
}
 
void IEC61883Output::write_samples(char *data, int samples)
{
//printf("IEC61883Output::write_samples 1\n");
int result = 0;
int timeout = (int64_t)samples *
(int64_t)1000000 *
(int64_t)2 /
(int64_t)samplerate;
if(interrupted) return;
 
//printf("IEC61883Output::write_samples 2\n");
 
// Check for maximum sample count exceeded
if(samples > OUTPUT_SAMPLES)
{
printf("IEC61883Output::write_samples samples=%d > OUTPUT_SAMPLES=%d\n",
samples,
OUTPUT_SAMPLES);
return;
}
 
//printf("IEC61883Output::write_samples 3\n");
// Take over buffer table
buffer_lock->lock("IEC61883Output::write_samples 1");
// Wait for buffer to become available with timeout
while(audio_samples > OUTPUT_SAMPLES - samples && !result && !interrupted)
{
buffer_lock->unlock();
result = audio_lock->timed_lock(BUFFER_TIMEOUT);
buffer_lock->lock("IEC61883Output::write_samples 2");
}
 
if(!interrupted && audio_samples <= OUTPUT_SAMPLES - samples)
{
//printf("IEC61883Output::write_samples 4 %d\n", audio_samples);
memcpy(audio_buffer + audio_samples * channels * bits / 8,
data,
samples * channels * bits / 8);
audio_samples += samples;
}
buffer_lock->unlock();
start_lock->unlock();
//printf("IEC61883Output::write_samples 100\n");
}
 
long IEC61883Output::get_audio_position()
{
position_lock->lock("IEC61883Output::get_audio_position");
long result = audio_position;
position_lock->unlock();
return result;
}
 
void IEC61883Output::interrupt()
{
interrupted = 1;
// Break write_samples out of a lock
video_lock->unlock();
audio_lock->unlock();
// Playback should stop when the object is deleted.
}
 
void IEC61883Output::flush()
{
}
 
void IEC61883Output::increment_counter(int *counter)
{
(*counter)++;
if(*counter >= total_buffers) *counter = 0;
}
 
void IEC61883Output::decrement_counter(int *counter)
{
(*counter)--;
if(*counter < 0) *counter = total_buffers - 1;
}
 
 
 
 
 
 
 
 
 
 
 
#endif // HAVE_FIREWIRE
 
 
 
 
 
 
/branches/automake-1_1_5/hvirtual/cinelerra/dcraw.c
New file
0,0 → 1,5048
/*
dcraw.c -- Dave Coffin's raw photo decoder
Copyright 1997-2004 by Dave Coffin, dcoffin a cybercom o net
 
This is a portable ANSI C program to convert raw image files from
any digital camera into PPM format. TIFF and CIFF parsing are
based upon public specifications, but no such documentation is
available for the raw sensor data, so writing this program has
been an immense effort.
 
This code is freely licensed for all uses, commercial and
otherwise. Comments, questions, and encouragement are welcome.
 
$Revision: 1.251 $
$Date: 2004/10/29 01:52:38 $
*/
 
#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/*
By defining NO_JPEG, you lose only the ability to
decode compressed .KDC files from the Kodak DC120.
*/
#ifndef NO_JPEG
#include <jpeglib.h>
#endif
 
#ifdef WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define strcasecmp stricmp
typedef __int64 INT64;
#else
#include <unistd.h>
#include <netinet/in.h>
typedef long long INT64;
#endif
 
#ifdef LJPEG_DECODE
#error Please compile dcraw.c by itself.
#error Do not link it with ljpeg_decode.
#endif
 
#ifndef LONG_BIT
#define LONG_BIT (8 * sizeof (long))
#endif
 
#define ushort UshORt
typedef unsigned char uchar;
typedef unsigned short ushort;
 
#define ABS_MAX ((ushort) -1)
#define RGB_MAX ((ushort) -1)
 
/*
All global variables are defined here, and all functions that
access them are prefixed with "CLASS". Note that a thread-safe
C++ class cannot have non-const static local variables.
*/
 
 
 
// Cinelerra
char dcraw_info[1024];
float **dcraw_data;
int dcraw_alpha;
 
 
FILE *ifp;
short order;
char *ifname, make[64], model[64], model2[64];
time_t timestamp;
int data_offset, curve_offset, curve_length;
int tiff_data_compression, kodak_data_compression;
int raw_height, raw_width, top_margin, left_margin;
int height, width, colors, black, rgb_max;
int iheight, iwidth, shrink;
int is_canon, is_cmy, is_foveon, use_coeff, trim, flip, xmag, ymag;
int zero_after_ff;
unsigned filters;
ushort (*image)[4], white[8][8];
void (*load_raw)();
float gamma_val=0.6, bright=1.0, red_scale=1.0, blue_scale=1.0;
int four_color_rgb=0, document_mode=0, quick_interpolate=0;
int verbose=0, use_auto_wb=0, use_camera_wb=0, use_secondary=0;
float camera_red, camera_blue;
float pre_mul[4], coeff[3][4];
float k1=1.5, k2=0.5, juice=0.0;
int histogram[0x2000];
void write_ppm(FILE *);
 
 
void (*write_fun)(FILE *) = write_ppm;
 
 
jmp_buf failure;
 
float green_scale=1.0;
float saturation = 1.0;
float contrast = 1.0;
int autoexposure=0, use_pivot=0, use_neutral_wb=0;
int alternate_scale = 0;
int center_weight = 0;
int use_camera_black = 1;
int user_black = -1;
float pivot_value = 0.75, exposure_compensation=0.0;
unsigned pivot_point[4], pivot_base[4];
float white_point_fraction = 0.99;
 
struct decode {
struct decode *branch[2];
int leaf;
} first_decode[2048], *second_decode, *free_decode;
 
#define CLASS
 
/*
In order to inline this calculation, I make the risky
assumption that all filter patterns can be described
by a repeating pattern of eight rows and two columns
 
Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
*/
#define FC(row,col) \
(filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
 
#define BAYER(row,col) \
image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)]
 
/*
PowerShot 600 uses 0xe1e4e1e4:
 
0 1 2 3 4 5
0 G M G M G M
1 C Y C Y C Y
2 M G M G M G
3 C Y C Y C Y
 
PowerShot A5 uses 0x1e4e1e4e:
 
0 1 2 3 4 5
0 C Y C Y C Y
1 G M G M G M
2 C Y C Y C Y
3 M G M G M G
 
PowerShot A50 uses 0x1b4e4b1e:
 
0 1 2 3 4 5
0 C Y C Y C Y
1 M G M G M G
2 Y C Y C Y C
3 G M G M G M
4 C Y C Y C Y
5 G M G M G M
6 Y C Y C Y C
7 M G M G M G
 
PowerShot Pro70 uses 0x1e4b4e1b:
 
0 1 2 3 4 5
0 Y C Y C Y C
1 M G M G M G
2 C Y C Y C Y
3 G M G M G M
4 Y C Y C Y C
5 G M G M G M
6 C Y C Y C Y
7 M G M G M G
 
PowerShots Pro90 and G1 use 0xb4b4b4b4:
 
0 1 2 3 4 5
0 G M G M G M
1 Y C Y C Y C
 
All RGB cameras use one of these Bayer grids:
 
0x16161616: 0x61616161: 0x49494949: 0x94949494:
 
0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G
1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B
2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G
3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B
 
*/
 
#ifndef __GLIBC__
char *memmem (char *haystack, size_t haystacklen,
char *needle, size_t needlelen)
{
char *c;
for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
if (!memcmp (c, needle, needlelen))
return c;
return NULL;
}
#endif
 
void CLASS merror (void *ptr, char *where)
{
if (ptr) return;
fprintf (stderr, "%s: Out of memory in %s\n", ifname, where);
longjmp (failure, 1);
}
 
/*
Get a 2-byte integer, making no assumptions about CPU byte order.
Nor should we assume that the compiler evaluates left-to-right.
*/
ushort CLASS fget2 (FILE *f)
{
uchar a, b;
 
a = fgetc(f);
b = fgetc(f);
if (order == 0x4949) /* "II" means little-endian */
return a + (b << 8);
else /* "MM" means big-endian */
return (a << 8) + b;
}
 
/*
Same for a 4-byte integer.
*/
int CLASS fget4 (FILE *f)
{
uchar a, b, c, d;
 
a = fgetc(f);
b = fgetc(f);
c = fgetc(f);
d = fgetc(f);
if (order == 0x4949)
return a + (b << 8) + (c << 16) + (d << 24);
else
return (a << 24) + (b << 16) + (c << 8) + d;
}
 
void CLASS canon_600_load_raw()
{
uchar data[1120], *dp;
ushort pixel[896], *pix;
int irow, orow, col;
 
for (irow=orow=0; irow < height; irow++)
{
fread (data, 1120, 1, ifp);
for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8)
{
pix[0] = (dp[0] << 2) + (dp[1] >> 6 );
pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
pix[3] = (dp[4] << 2) + (dp[1] & 3);
pix[4] = (dp[5] << 2) + (dp[9] & 3);
pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
pix[7] = (dp[8] << 2) + (dp[9] >> 6 );
}
for (col=0; col < width; col++)
BAYER(orow,col) = pixel[col] << 4;
for (col=width; col < 896; col++)
black += pixel[col];
if ((orow+=2) > height)
orow = 1;
}
black = ((INT64) black << 4) / ((896 - width) * height);
}
 
void CLASS canon_a5_load_raw()
{
uchar data[1940], *dp;
ushort pixel[1552], *pix;
int row, col;
 
for (row=0; row < height; row++) {
fread (data, raw_width * 10 / 8, 1, ifp);
for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=10, pix+=8)
{
pix[0] = (dp[1] << 2) + (dp[0] >> 6);
pix[1] = (dp[0] << 4) + (dp[3] >> 4);
pix[2] = (dp[3] << 6) + (dp[2] >> 2);
pix[3] = (dp[2] << 8) + (dp[5] );
pix[4] = (dp[4] << 2) + (dp[7] >> 6);
pix[5] = (dp[7] << 4) + (dp[6] >> 4);
pix[6] = (dp[6] << 6) + (dp[9] >> 2);
pix[7] = (dp[9] << 8) + (dp[8] );
}
for (col=0; col < width; col++)
BAYER(row,col) = (pixel[col] & 0x3ff) << 4;
for (col=width; col < raw_width; col++)
black += pixel[col] & 0x3ff;
}
if (raw_width > width)
black = ((INT64) black << 4) / ((raw_width - width) * height);
}
 
/*
getbits(-1) initializes the buffer
getbits(n) where 0 <= n <= 25 returns an n-bit integer
*/
unsigned CLASS getbits (int nbits)
{
static unsigned long bitbuf=0;
static int vbits=0;
unsigned c, ret;
 
if (nbits == 0) return 0;
if (nbits == -1)
ret = bitbuf = vbits = 0;
else {
ret = bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - nbits);
vbits -= nbits;
}
while (vbits < LONG_BIT - 7) {
c = fgetc(ifp);
bitbuf = (bitbuf << 8) + c;
if (c == 0xff && zero_after_ff)
fgetc(ifp);
vbits += 8;
}
return ret;
}
 
void CLASS init_decoder ()
{
memset (first_decode, 0, sizeof first_decode);
free_decode = first_decode;
}
 
/*
Construct a decode tree according the specification in *source.
The first 16 bytes specify how many codes should be 1-bit, 2-bit
3-bit, etc. Bytes after that are the leaf values.
 
For example, if the source is
 
{ 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
 
then the code is
 
00 0x04
010 0x03
011 0x05
100 0x06
101 0x02
1100 0x07
1101 0x01
11100 0x08
11101 0x09
11110 0x00
111110 0x0a
1111110 0x0b
1111111 0xff
*/
uchar * CLASS make_decoder (const uchar *source, int level)
{
struct decode *cur;
static int leaf;
int i, next;
 
if (level==0) leaf=0;
cur = free_decode++;
if (free_decode > first_decode+2048) {
fprintf (stderr, "%s: decoder table overflow\n", ifname);
longjmp (failure, 2);
}
for (i=next=0; i <= leaf && next < 16; )
i += source[next++];
if (i > leaf) {
if (level < next) {
cur->branch[0] = free_decode;
make_decoder (source, level+1);
cur->branch[1] = free_decode;
make_decoder (source, level+1);
} else
cur->leaf = source[16 + leaf++];
}
return (uchar *) source + 16 + leaf;
}
 
void CLASS crw_init_tables (unsigned table)
{
static const uchar first_tree[3][29] = {
{ 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
 
{ 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0,
0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff },
 
{ 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0,
0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff },
};
 
static const uchar second_tree[3][180] = {
{ 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139,
0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08,
0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0,
0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42,
0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57,
0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9,
0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98,
0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6,
0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4,
0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7,
0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1,
0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64,
0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba,
0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4,
0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff },
 
{ 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140,
0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06,
0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32,
0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51,
0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26,
0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59,
0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9,
0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99,
0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85,
0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8,
0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a,
0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9,
0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8,
0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8,
0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff },
 
{ 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117,
0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08,
0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22,
0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34,
0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41,
0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48,
0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69,
0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8,
0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94,
0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a,
0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6,
0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62,
0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5,
0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3,
0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff }
};
 
if (table > 2) table = 2;
init_decoder();
make_decoder ( first_tree[table], 0);
second_decode = free_decode;
make_decoder (second_tree[table], 0);
}
 
/*
Return 0 if the image starts with compressed data,
1 if it starts with uncompressed low-order bits.
 
In Canon compressed data, 0xff is always followed by 0x00.
*/
int CLASS canon_has_lowbits()
{
uchar test[0x4000];
int ret=1, i;
 
fseek (ifp, 0, SEEK_SET);
fread (test, 1, sizeof test, ifp);
for (i=540; i < sizeof test - 1; i++)
if (test[i] == 0xff) {
if (test[i+1]) return 1;
ret=0;
}
return ret;
}
 
void CLASS canon_compressed_load_raw()
{
ushort *pixel, *prow;
int lowbits, shift, i, row, r, col, save, val;
unsigned irow, icol;
struct decode *decode, *dindex;
int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
uchar c;
INT64 bblack=0;
 
pixel = calloc (raw_width*8, sizeof *pixel);
merror (pixel, "canon_compressed_load_raw()");
lowbits = canon_has_lowbits();
shift = 4 - lowbits*2;
fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET);
zero_after_ff = 1;
getbits(-1);
 
for (row = 0; row < raw_height; row += 8) {
for (block=0; block < raw_width >> 3; block++) {
memset (diffbuf, 0, sizeof diffbuf);
decode = first_decode;
for (i=0; i < 64; i++ ) {
for (dindex=decode; dindex->branch[0]; )
dindex = dindex->branch[getbits(1)];
leaf = dindex->leaf;
decode = second_decode;
if (leaf == 0 && i) break;
if (leaf == 0xff) continue;
i += leaf >> 4;
len = leaf & 15;
if (len == 0) continue;
diff = getbits(len);
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
if (i < 64) diffbuf[i] = diff;
}
diffbuf[0] += carry;
carry = diffbuf[0];
for (i=0; i < 64; i++ ) {
if (pnum++ % raw_width == 0)
base[0] = base[1] = 512;
pixel[(block << 6) + i] = ( base[i & 1] += diffbuf[i] );
}
}
if (lowbits) {
save = ftell(ifp); /* Don't lose our place */
fseek (ifp, 26 + row*raw_width/4, SEEK_SET);
for (prow=pixel, i=0; i < raw_width*2; i++) {
c = fgetc(ifp);
for (r=0; r < 8; r+=2, prow++) {
val = (*prow << 2) + ((c >> r) & 3);
if (raw_width == 2672 && val < 512) val += 2;
*prow = val;
}
}
fseek (ifp, save, SEEK_SET);
}
for (r=0; r < 8; r++) {
irow = row - top_margin + r;
if (irow >= height) continue;
for (col = 0; col < raw_width; col++) {
icol = col - left_margin;
if (icol < width)
BAYER(irow,icol) = pixel[r*raw_width+col] << shift;
else
bblack += pixel[r*raw_width+col];
}
}
}
free(pixel);
if (raw_width > width)
black = (bblack << shift) / ((raw_width - width) * height);
}
 
void CLASS kodak_curve (ushort *curve)
{
int i, entries, tag, type, len, val;
 
for (i=0; i < 0x1000; i++)
curve[i] = i;
if (strcasecmp(make,"KODAK")) return;
if (!curve_offset) {
fseek (ifp, 12, SEEK_SET);
entries = fget2(ifp);
while (entries--) {
tag = fget2(ifp);
type = fget2(ifp);
len = fget4(ifp);
val = fget4(ifp);
if (tag == 0x90d) {
curve_offset = val;
curve_length = len;
}
}
}
if (curve_offset) {
fseek (ifp, curve_offset, SEEK_SET);
for (i=0; i < curve_length; i++)
curve[i] = fget2(ifp);
for ( ; i < 0x1000; i++)
curve[i] = curve[i-1];
rgb_max = curve[i-1] << 2;
}
fseek (ifp, data_offset, SEEK_SET);
}
 
/*
Not a full implementation of Lossless JPEG,
just enough to decode Canon and Kodak images.
*/
void CLASS lossless_jpeg_load_raw()
{
int tag, len, jhigh=0, jwide=0, jrow, jcol, jidx, diff, i, row, col;
uchar data[256], *dp;
int vpred[2] = { 0x800, 0x800 }, hpred[2];
struct decode *dstart[2], *dindex;
ushort curve[0x10000];
INT64 bblack=0;
int min=INT_MAX;
 
kodak_curve(curve);
order = 0x4d4d;
if (fget2(ifp) != 0xffd8) return;
 
do {
tag = fget2(ifp);
len = fget2(ifp) - 2;
if (tag <= 0xff00 || len > 255) return;
fread (data, 1, len, ifp);
switch (tag) {
case 0xffc3:
jhigh = (data[1] << 8) + data[2];
jwide =((data[3] << 8) + data[4])*2;
break;
case 0xffc4:
init_decoder();
dstart[0] = dstart[1] = free_decode;
for (dp = data; dp < data+len && *dp < 2; ) {
dstart[*dp] = free_decode;
dp = make_decoder (++dp, 0);
}
}
} while (tag != 0xffda);
 
zero_after_ff = 1;
getbits(-1);
for (jrow=0; jrow < jhigh; jrow++)
{
for (jcol=0; jcol < jwide; jcol++)
{
for (dindex = dstart[jcol & 1]; dindex->branch[0]; )
dindex = dindex->branch[getbits(1)];
len = dindex->leaf;
diff = getbits(len);
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
if (jcol < 2) {
vpred[jcol] += diff;
hpred[jcol] = vpred[jcol];
} else
hpred[jcol & 1] += diff;
diff = hpred[jcol & 1];
if (diff < 0) diff = 0;
jidx = jrow*jwide + jcol;
if (raw_width == 5108) {
i = jidx / (1680*jhigh);
if (i < 2) {
row = jidx / 1680 % jhigh;
col = jidx % 1680 + i*1680;
} else {
jidx -= 2*1680*jhigh;
row = jidx / 1748;
col = jidx % 1748 + 2*1680;
}
} else {
row = jidx / raw_width;
col = jidx % raw_width;
}
if ((unsigned) (row-top_margin) >= height)
continue;
if ((unsigned) (col-left_margin) < width) {
BAYER(row-top_margin,col-left_margin) = curve[diff] << 2;
if (min > curve[diff])
min = curve[diff];
} else
bblack += curve[diff];
}
}
 
 
 
 
 
 
 
 
 
 
 
if (raw_width > width)
black = (bblack << 2) / ((raw_width - width) * height);
if (!strcasecmp(make,"KODAK"))
black = min << 2;
}
 
void CLASS nikon_compressed_load_raw()
{
static const uchar nikon_tree[] = {
0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0,
5,4,3,6,2,7,1,0,8,9,11,10,12
};
int vpred[4], hpred[2], csize, row, col, i, len, diff;
ushort *curve;
struct decode *dindex;
 
init_decoder();
make_decoder (nikon_tree, 0);
 
fseek (ifp, curve_offset, SEEK_SET);
for (i=0; i < 4; i++)
vpred[i] = fget2(ifp);
csize = fget2(ifp);
curve = calloc (csize, sizeof *curve);
merror (curve, "nikon_compressed_load_raw()");
for (i=0; i < csize; i++)
curve[i] = fget2(ifp);
 
fseek (ifp, data_offset, SEEK_SET);
getbits(-1);
 
for (row=0; row < height; row++)
for (col=0; col < raw_width; col++)
{
for (dindex=first_decode; dindex->branch[0]; )
dindex = dindex->branch[getbits(1)];
len = dindex->leaf;
diff = getbits(len);
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
if (col < 2) {
i = 2*(row & 1) + (col & 1);
vpred[i] += diff;
hpred[col] = vpred[i];
} else
hpred[col & 1] += diff;
if ((unsigned) (col-left_margin) >= width) continue;
diff = hpred[col & 1];
if (diff < 0) diff = 0;
if (diff >= csize) diff = csize-1;
BAYER(row,col-left_margin) = curve[diff] << 2;
}
free(curve);
}
 
void CLASS nikon_load_raw()
{
int irow, row, col, i;
 
getbits(-1);
for (irow=0; irow < height; irow++) {
row = irow;
if (model[0] == 'E') {
row = irow * 2 % height + irow / (height/2);
if (row == 1 && atoi(model+1) < 5000) {
fseek (ifp, 0, SEEK_END);
fseek (ifp, ftell(ifp)/2, SEEK_SET);
getbits(-1);
}
}
for (col=0; col < raw_width; col++) {
i = getbits(12);
if ((unsigned) (col-left_margin) < width)
BAYER(row,col-left_margin) = i << 2;
if (tiff_data_compression == 34713 && (col % 10) == 9)
getbits(8);
}
}
}
 
/*
Figure out if a NEF file is compressed. These fancy heuristics
are only needed for the D100, thanks to a bug in some cameras
that tags all images as "compressed".
*/
int CLASS nikon_is_compressed()
{
uchar test[256];
int i;
 
if (tiff_data_compression != 34713)
return 0;
if (strcmp(model,"D100"))
return 1;
fseek (ifp, data_offset, SEEK_SET);
fread (test, 1, 256, ifp);
for (i=15; i < 256; i+=16)
if (test[i]) return 1;
return 0;
}
 
/*
Returns 1 for a Coolpix 990, 0 for a Coolpix 995.
*/
int CLASS nikon_e990()
{
int i, histo[256];
const uchar often[] = { 0x00, 0x55, 0xaa, 0xff };
 
memset (histo, 0, sizeof histo);
fseek (ifp, 2064*1540*3/4, SEEK_SET);
for (i=0; i < 2000; i++)
histo[fgetc(ifp)]++;
for (i=0; i < 4; i++)
if (histo[often[i]] > 400)
return 1;
return 0;
}
 
/*
Returns 1 for a Coolpix 2100, 0 for anything else.
*/
int CLASS nikon_e2100()
{
uchar t[12];
int i;
 
fseek (ifp, 0, SEEK_SET);
for (i=0; i < 1024; i++) {
fread (t, 1, 12, ifp);
if (((t[2] & t[4] & t[7] & t[9]) >> 4
& t[1] & t[6] & t[8] & t[11] & 3) != 3)
return 0;
}
return 1;
}
 
/*
Separates a Minolta DiMAGE Z2 from a Nikon E4300.
*/
int CLASS minolta_z2()
{
int i;
char tail[424];
 
fseek (ifp, -sizeof tail, SEEK_END);
fread (tail, 1, sizeof tail, ifp);
for (i=0; i < sizeof tail; i++)
if (tail[i]) return 1;
return 0;
}
 
void CLASS nikon_e2100_load_raw()
{
uchar data[3432], *dp;
ushort pixel[2288], *pix;
int row, col;
 
for (row=0; row <= height; row+=2) {
if (row == height) {
fseek (ifp, width==1616 ? 8792:424, SEEK_CUR);
row = 1;
}
fread (data, 1, width*3/2, ifp);
for (dp=data, pix=pixel; pix < pixel+width; dp+=12, pix+=8) {
pix[0] = (dp[2] >> 4) + (dp[ 3] << 4);
pix[1] = (dp[2] << 8) + dp[ 1];
pix[2] = (dp[7] >> 4) + (dp[ 0] << 4);
pix[3] = (dp[7] << 8) + dp[ 6];
pix[4] = (dp[4] >> 4) + (dp[ 5] << 4);
pix[5] = (dp[4] << 8) + dp[11];
pix[6] = (dp[9] >> 4) + (dp[10] << 4);
pix[7] = (dp[9] << 8) + dp[ 8];
}
for (col=0; col < width; col++)
BAYER(row,col) = (pixel[col] & 0xfff) << 2;
}
}
 
void CLASS nikon_e950_load_raw()
{
int irow, row, col;
 
getbits(-1);
for (irow=0; irow < height; irow++) {
row = irow * 2 % height;
for (col=0; col < width; col++)
BAYER(row,col) = getbits(10) << 4;
for (col=28; col--; )
getbits(8);
}
}
 
/*
The Fuji Super CCD is just a Bayer grid rotated 45 degrees.
*/
void CLASS fuji_s2_load_raw()
{
ushort pixel[2944];
int row, col, r, c;
 
fseek (ifp, (2944*24+32)*2, SEEK_CUR);
for (row=0; row < 2144; row++) {
fread (pixel, 2, 2944, ifp);
for (col=0; col < 2880; col++) {
r = row + ((col+1) >> 1);
c = 2143 - row + (col >> 1);
BAYER(r,c) = ntohs(pixel[col]) << 2;
}
}
}
 
void CLASS fuji_common_load_raw (int ncol, int icol, int nrow)
{
ushort pixel[2048];
int row, col, r, c;
 
for (row=0; row < nrow; row++) {
fread (pixel, 2, ncol, ifp);
if (ntohs(0xaa55) == 0xaa55) /* data is little-endian */
swab (pixel, pixel, ncol*2);
for (col=0; col <= icol; col++) {
r = icol - col + (row >> 1);
c = col + ((row+1) >> 1);
BAYER(r,c) = pixel[col] << 2;
}
}
}
 
void CLASS fuji_s5000_load_raw()
{
fseek (ifp, (1472*4+24)*2, SEEK_CUR);
fuji_common_load_raw (1472, 1423, 2152);
}
 
void CLASS fuji_s7000_load_raw()
{
fuji_common_load_raw (2048, 2047, 3080);
}
 
/*
The Fuji Super CCD SR has two photodiodes for each pixel.
The secondary has about 1/16 the sensitivity of the primary,
but this ratio may vary.
*/
void CLASS fuji_f700_load_raw()
{
ushort pixel[2944];
int row, col, r, c, val;
 
for (row=0; row < 2168; row++) {
fread (pixel, 2, 2944, ifp);
if (ntohs(0xaa55) == 0xaa55) /* data is little-endian */
swab (pixel, pixel, 2944*2);
for (col=0; col < 1440; col++) {
r = 1439 - col + (row >> 1);
c = col + ((row+1) >> 1);
val = pixel[col+16 + use_secondary*1472];
BAYER(r,c) = val;
}
}
}
 
void CLASS rollei_load_raw()
{
uchar pixel[10];
unsigned iten=0, isix, i, buffer=0, row, col, todo[16];
 
isix = raw_width * raw_height * 5 / 8;
while (fread (pixel, 1, 10, ifp) == 10) {
for (i=0; i < 10; i+=2) {
todo[i] = iten++;
todo[i+1] = pixel[i] << 8 | pixel[i+1];
buffer = pixel[i] >> 2 | buffer << 6;
}
for ( ; i < 16; i+=2) {
todo[i] = isix++;
todo[i+1] = buffer >> (14-i)*5;
}
for (i=0; i < 16; i+=2) {
row = todo[i] / raw_width - top_margin;
col = todo[i] % raw_width - left_margin;
if (row < height && col < width)
BAYER(row,col) = (todo[i+1] & 0x3ff) << 4;
}
}
}
 
void CLASS phase_one_load_raw()
{
int row, col, a, b;
ushort pixel[4134], akey, bkey;
 
fseek (ifp, 8, SEEK_CUR);
fseek (ifp, fget4(ifp) + 296, SEEK_CUR);
akey = fget2(ifp);
bkey = fget2(ifp);
fseek (ifp, data_offset + 12 + top_margin*raw_width*2, SEEK_SET);
for (row=0; row < height; row++) {
fread (pixel, 2, raw_width, ifp);
for (col=0; col < raw_width; col+=2) {
a = ntohs(pixel[col+0]) ^ akey;
b = ntohs(pixel[col+1]) ^ bkey;
pixel[col+0] = (b & 0xaaaa) | (a & 0x5555);
pixel[col+1] = (a & 0xaaaa) | (b & 0x5555);
}
for (col=0; col < width; col++)
BAYER(row,col) = pixel[col+left_margin];
}
}
 
void CLASS ixpress_load_raw()
{
ushort pixel[4090];
int row, col;
 
fseek (ifp, 304 + 6*2*4090, SEEK_SET);
for (row=height; --row >= 0; ) {
fread (pixel, 2, 4090, ifp);
if (ntohs(0xaa55) == 0xaa55) /* data is little-endian */
swab (pixel, pixel, 4090*2);
for (col=0; col < width; col++)
BAYER(row,col) = pixel[width-1-col];
}
}
 
/* For this function only, raw_width is in bytes, not pixels! */
void CLASS packed_12_load_raw()
{
int row, col;
 
getbits(-1);
for (row=0; row < height; row++) {
for (col=0; col < width; col++)
BAYER(row,col) = getbits(12) << 2;
for (col = width*3/2; col < raw_width; col++)
getbits(8);
}
}
 
void CLASS unpacked_load_raw (int order, int rsh)
{
ushort *pixel;
int row, col;
 
pixel = calloc (raw_width, sizeof *pixel);
merror (pixel, "unpacked_load_raw()");
for (row=0; row < height; row++) {
fread (pixel, 2, raw_width, ifp);
if (order != ntohs(0x55aa))
swab (pixel, pixel, width*2);
for (col=0; col < width; col++)
BAYER(row,col) = pixel[col] << 8 >> (8+rsh);
}
free(pixel);
}
 
void CLASS be_16_load_raw() /* "be" = "big-endian" */
{
unpacked_load_raw (0x55aa, 0);
}
 
void CLASS be_high_12_load_raw()
{
unpacked_load_raw (0x55aa, 2);
}
 
void CLASS be_low_12_load_raw()
{
unpacked_load_raw (0x55aa,-2);
}
 
void CLASS be_low_10_load_raw()
{
unpacked_load_raw (0x55aa,-4);
}
 
void CLASS le_high_12_load_raw() /* "le" = "little-endian" */
{
unpacked_load_raw (0xaa55, 2);
}
 
void CLASS olympus_cseries_load_raw()
{
int irow, row, col;
 
for (irow=0; irow < height; irow++) {
row = irow * 2 % height + irow / (height/2);
if (row < 2) {
fseek (ifp, data_offset - row*(-width*height*3/4 & -2048), SEEK_SET);
getbits(-1);
}
for (col=0; col < width; col++)
BAYER(row,col) = getbits(12) << 2;
}
}
 
void CLASS eight_bit_load_raw()
{
uchar *pixel;
int row, col;
 
pixel = calloc (raw_width, sizeof *pixel);
merror (pixel, "eight_bit_load_raw()");
for (row=0; row < height; row++) {
fread (pixel, 1, raw_width, ifp);
for (col=0; col < width; col++)
BAYER(row,col) = pixel[col] << 6;
}
free (pixel);
}
 
void CLASS casio_qv5700_load_raw()
{
uchar data[3232], *dp;
ushort pixel[2576], *pix;
int row, col;
 
for (row=0; row < height; row++) {
fread (data, 1, 3232, ifp);
for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) {
pix[0] = (dp[0] << 2) + (dp[1] >> 6);
pix[1] = (dp[1] << 4) + (dp[2] >> 4);
pix[2] = (dp[2] << 6) + (dp[3] >> 2);
pix[3] = (dp[3] << 8) + (dp[4] );
}
for (col=0; col < width; col++)
BAYER(row,col) = (pixel[col] & 0x3ff) << 4;
}
}
 
void CLASS nucore_load_raw()
{
uchar *data, *dp;
int irow, row, col;
 
data = calloc (width, 2);
merror (data, "nucore_load_raw()");
for (irow=0; irow < height; irow++) {
fread (data, 2, width, ifp);
if (model[0] == 'B' && width == 2598)
row = height - 1 - irow/2 - height/2 * (irow & 1);
else
row = irow;
for (dp=data, col=0; col < width; col++, dp+=2)
BAYER(row,col) = (dp[0] << 2) + (dp[1] << 10);
}
free(data);
}
 
const int * CLASS make_decoder_int (const int *source, int level)
{
struct decode *cur;
 
cur = free_decode++;
if (level < source[0]) {
cur->branch[0] = free_decode;
source = make_decoder_int (source, level+1);
cur->branch[1] = free_decode;
source = make_decoder_int (source, level+1);
} else {
cur->leaf = source[1];
source += 2;
}
return source;
}
 
int CLASS radc_token (int tree)
{
int t;
static struct decode *dstart[18], *dindex;
static const int *s, source[] = {
1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8,
1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8,
2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8,
2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8,
2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8,
2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8,
2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8,
2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8,
2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4,
2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8,
1,0, 2,2, 2,-2,
1,-3, 1,3,
2,-17, 2,-5, 2,5, 2,17,
2,-7, 2,2, 2,9, 2,18,
2,-18, 2,-9, 2,-2, 2,7,
2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79,
2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76,
2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37
};
 
if (free_decode == first_decode)
for (s=source, t=0; t < 18; t++) {
dstart[t] = free_decode;
s = make_decoder_int (s, 0);
}
if (tree == 18) {
if (model[2] == '4')
return (getbits(5) << 3) + 4; /* DC40 */
else
return (getbits(6) << 2) + 2; /* DC50 */
}
for (dindex = dstart[tree]; dindex->branch[0]; )
dindex = dindex->branch[getbits(1)];
return dindex->leaf;
}
 
#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
 
#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
 
void CLASS kodak_radc_load_raw()
{
int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val;
short last[3] = { 16,16,16 }, mul[3], buf[3][3][386];
 
init_decoder();
getbits(-1);
for (i=0; i < sizeof(buf)/sizeof(short); i++)
buf[0][0][i] = 2048;
for (row=0; row < height; row+=4) {
for (i=0; i < 3; i++)
mul[i] = getbits(6);
for (c=0; c < 3; c++) {
val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
s = val > 65564 ? 10:12;
x = ~(-1 << (s-1));
val <<= 12-s;
for (i=0; i < sizeof(buf[0])/sizeof(short); i++)
buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
last[c] = mul[c];
for (r=0; r <= !c; r++) {
buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7;
for (tree=1, col=width/2; col > 0; ) {
if ((tree = radc_token(tree))) {
col -= 2;
if (tree == 8)
FORYX buf[c][y][x] = radc_token(tree+10) * mul[c];
else
FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
} else
do {
nreps = (col > 2) ? radc_token(9) + 1 : 1;
for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) {
col -= 2;
FORYX buf[c][y][x] = PREDICTOR;
if (rep & 1) {
step = radc_token(10) << 4;
FORYX buf[c][y][x] += step;
}
}
} while (nreps == 9);
}
for (y=0; y < 2; y++)
for (x=0; x < width/2; x++) {
val = (buf[c][y+1][x] << 4) / mul[c];
if (val < 0) val = 0;
if (c)
BAYER(row+y*2+c-1,x*2+2-c) = val;
else
BAYER(row+r*2+y,x*2+y) = val;
}
memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
}
}
for (y=row; y < row+4; y++)
for (x=0; x < width; x++)
if ((x+y) & 1) {
val = (BAYER(y,x)-2048)*2 + (BAYER(y,x-1)+BAYER(y,x+1))/2;
if (val < 0) val = 0;
BAYER(y,x) = val;
}
}
}
 
#undef FORYX
#undef PREDICTOR
 
#ifdef NO_JPEG
void CLASS kodak_jpeg_load_raw() {}
#else
 
METHODDEF(boolean)
fill_input_buffer (j_decompress_ptr cinfo)
{
static char jpeg_buffer[4096];
size_t nbytes;
 
nbytes = fread (jpeg_buffer, 1, 4096, ifp);
swab (jpeg_buffer, jpeg_buffer, nbytes);
cinfo->src->next_input_byte = jpeg_buffer;
cinfo->src->bytes_in_buffer = nbytes;
return TRUE;
}
 
void CLASS kodak_jpeg_load_raw()
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPARRAY buf;
JSAMPLE (*pixel)[3];
int row, col;
 
cinfo.err = jpeg_std_error (&jerr);
jpeg_create_decompress (&cinfo);
jpeg_stdio_src (&cinfo, ifp);
cinfo.src->fill_input_buffer = fill_input_buffer;
jpeg_read_header (&cinfo, TRUE);
jpeg_start_decompress (&cinfo);
if ((cinfo.output_width != width ) ||
(cinfo.output_height*2 != height ) ||
(cinfo.output_components != 3 )) {
fprintf (stderr, "%s: incorrect JPEG dimensions\n", ifname);
jpeg_destroy_decompress (&cinfo);
longjmp (failure, 3);
}
buf = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1);
 
while (cinfo.output_scanline < cinfo.output_height) {
row = cinfo.output_scanline * 2;
jpeg_read_scanlines (&cinfo, buf, 1);
pixel = (void *) buf[0];
for (col=0; col < width; col+=2) {
BAYER(row+0,col+0) = pixel[col+0][1] << 6;
BAYER(row+1,col+1) = pixel[col+1][1] << 6;
BAYER(row+0,col+1) = (pixel[col][0] + pixel[col+1][0]) << 5;
BAYER(row+1,col+0) = (pixel[col][2] + pixel[col+1][2]) << 5;
}
}
jpeg_finish_decompress (&cinfo);
jpeg_destroy_decompress (&cinfo);
}
 
#endif
 
void CLASS kodak_dc120_load_raw()
{
static const int mul[4] = { 162, 192, 187, 92 };
static const int add[4] = { 0, 636, 424, 212 };
uchar pixel[848];
int row, shift, col;
 
for (row=0; row < height; row++)
{
fread (pixel, 848, 1, ifp);
shift = row * mul[row & 3] + add[row & 3];
for (col=0; col < width; col++)
BAYER(row,col) = (ushort) pixel[(col + shift) % 848] << 6;
}
}
 
void CLASS kodak_dc20_coeff (float juice)
{
static const float my_coeff[3][4] =
{ { 2.25, 0.75, -1.75, -0.25 },
{ -0.25, 0.75, 0.75, -0.25 },
{ -0.25, -1.75, 0.75, 2.25 } };
static const float flat[3][4] =
{ { 1, 0, 0, 0 },
{ 0, 0.5, 0.5, 0 },
{ 0, 0, 0, 1 } };
int r, g;
 
if (juice != 0) {
for (r=0; r < 3; r++)
for (g=0; g < 4; g++)
coeff[r][g] = my_coeff[r][g] * juice + flat[r][g] * (1-juice);
use_coeff = 1;
}
}
 
void CLASS kodak_easy_load_raw()
{
uchar *pixel;
ushort curve[0x1000];
unsigned row, col, icol;
 
kodak_curve (curve);
if (raw_width > width)
black = 0;
pixel = calloc (raw_width, sizeof *pixel);
merror (pixel, "kodak_easy_load_raw()");
for (row=0; row < height; row++) {
fread (pixel, 1, raw_width, ifp);
for (col=0; col < raw_width; col++) {
icol = col - left_margin;
if (icol < width)
BAYER(row,icol) = (ushort) curve[pixel[col]] << 2;
else
black += curve[pixel[col]];
}
}
if (raw_width > width)
black = ((INT64) black << 2) / ((raw_width - width) * height);
if (!strncmp(model,"DC2",3))
black = 0;
free(pixel);
}
 
void CLASS kodak_compressed_load_raw()
{
uchar c, blen[256];
ushort raw[6], curve[0x1000];
unsigned row, col, len, save, i, israw=0, bits=0, pred[2];
INT64 bitbuf=0;
int diff;
 
kodak_curve (curve);
for (row=0; row < height; row++)
for (col=0; col < width; col++)
{
if ((col & 255) == 0) { /* Get the bit-lengths of the */
len = width - col; /* next 256 pixel values */
if (len > 256) len = 256;
save = ftell(ifp);
for (israw=i=0; i < len; i+=2) {
c = fgetc(ifp);
if ((blen[i+0] = c & 15) > 12 ||
(blen[i+1] = c >> 4) > 12 )
israw = 1;
}
bitbuf = bits = pred[0] = pred[1] = 0;
if (len % 8 == 4) {
bitbuf = fgetc(ifp) << 8;
bitbuf += fgetc(ifp);
bits = 16;
}
if (israw)
fseek (ifp, save, SEEK_SET);
}
if (israw) { /* If the data is not compressed */
switch (col & 7) {
case 0:
fread (raw, 2, 6, ifp);
for (i=0; i < 6; i++)
raw[i] = ntohs(raw[i]);
diff = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
break;
case 1:
diff = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
break;
default:
diff = raw[(col & 7) - 2] & 0xfff;
}
} else { /* If the data is compressed */
len = blen[col & 255]; /* Number of bits for this pixel */
if (bits < len) { /* Got enough bits in the buffer? */
for (i=0; i < 32; i+=8)
bitbuf += (INT64) fgetc(ifp) << (bits+(i^8));
bits += 32;
}
diff = bitbuf & (0xffff >> (16-len)); /* Pull bits from buffer */
bitbuf >>= len;
bits -= len;
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
pred[col & 1] += diff;
diff = pred[col & 1];
}
BAYER(row,col) = curve[diff] << 2;
}
}
 
void CLASS kodak_yuv_load_raw()
{
uchar c, blen[384];
unsigned row, col, len, bits=0;
INT64 bitbuf=0;
int i, li=0, si, diff, six[6], y[4], cb=0, cr=0, rgb[3];
ushort *ip, curve[0x1000];
 
kodak_curve (curve);
for (row=0; row < height; row+=2)
for (col=0; col < width; col+=2) {
if ((col & 127) == 0) {
len = (width - col + 1) * 3 & -4;
if (len > 384) len = 384;
for (i=0; i < len; ) {
c = fgetc(ifp);
blen[i++] = c & 15;
blen[i++] = c >> 4;
}
li = bitbuf = bits = y[1] = y[3] = cb = cr = 0;
if (len % 8 == 4) {
bitbuf = fgetc(ifp) << 8;
bitbuf += fgetc(ifp);
bits = 16;
}
}
for (si=0; si < 6; si++) {
len = blen[li++];
if (bits < len) {
for (i=0; i < 32; i+=8)
bitbuf += (INT64) fgetc(ifp) << (bits+(i^8));
bits += 32;
}
diff = bitbuf & (0xffff >> (16-len));
bitbuf >>= len;
bits -= len;
if ((diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
six[si] = diff;
}
y[0] = six[0] + y[1];
y[1] = six[1] + y[0];
y[2] = six[2] + y[3];
y[3] = six[3] + y[2];
cb += six[4];
cr += six[5];
for (i=0; i < 4; i++) {
ip = image[(row+(i >> 1))*width + col+(i & 1)];
rgb[0] = y[i] + cr;
rgb[1] = y[i];
rgb[2] = y[i] + cb;
for (c=0; c < 3; c++)
if (rgb[c] > 0) ip[c] = curve[rgb[c]] << 2;
}
}
}
 
void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
{
static unsigned pad[128], p;
 
if (start) {
for (p=0; p < 4; p++)
pad[p] = key = key * 48828125 + 1;
pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
for (p=4; p < 127; p++)
pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
for (p=0; p < 127; p++)
pad[p] = htonl(pad[p]);
}
while (len--)
*data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
}
 
void CLASS sony_load_raw()
{
uchar head[40];
ushort pixel[3360];
unsigned i, key, row, col, icol;
INT64 bblack=0;
 
fseek (ifp, 200896, SEEK_SET);
fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR);
order = 0x4d4d;
key = fget4(ifp);
fseek (ifp, 164600, SEEK_SET);
fread (head, 1, 40, ifp);
sony_decrypt ((void *) head, 10, 1, key);
for (i=26; i-- > 22; )
key = key << 8 | head[i];
fseek (ifp, 862144, SEEK_SET);
for (row=0; row < height; row++) {
fread (pixel, 2, raw_width, ifp);
sony_decrypt ((void *) pixel, raw_width/2, !row, key);
for (col=0; col < 3343; col++)
if ((icol = col-left_margin) < width)
BAYER(row,icol) = ntohs(pixel[col]);
else
bblack += ntohs(pixel[col]);
}
black = bblack / ((3343 - width) * height);
}
 
void CLASS sony_rgbe_coeff()
{
int r, g;
static const float my_coeff[3][4] =
{ { 1.321918, 0.000000, 0.149829, -0.471747 },
{ -0.288764, 1.129213, -0.486517, 0.646067 },
{ 0.061336, -0.199343, 1.138007, 0.000000 } };
 
for (r=0; r < 3; r++)
for (g=0; g < 4; g++)
coeff[r][g] = my_coeff[r][g];
use_coeff = 1;
}
 
void CLASS foveon_decoder (unsigned huff[1024], unsigned code)
{
struct decode *cur;
int i, len;
 
cur = free_decode++;
if (free_decode > first_decode+2048) {
fprintf (stderr, "%s: decoder table overflow\n", ifname);
longjmp (failure, 2);
}
if (code) {
for (i=0; i < 1024; i++)
if (huff[i] == code) {
cur->leaf = i;
return;
}
}
if ((len = code >> 27) > 26) return;
code = (len+1) << 27 | (code & 0x3ffffff) << 1;
 
cur->branch[0] = free_decode;
foveon_decoder (huff, code);
cur->branch[1] = free_decode;
foveon_decoder (huff, code+1);
}
 
void CLASS foveon_load_raw()
{
struct decode *dindex;
short diff[1024], pred[3];
unsigned huff[1024], bitbuf=0;
int row, col, bit=-1, c, i;
 
fseek (ifp, 260, SEEK_SET);
for (i=0; i < 1024; i++)
diff[i] = fget2(ifp);
for (i=0; i < 1024; i++)
huff[i] = fget4(ifp);
 
init_decoder();
foveon_decoder (huff, 0);
 
for (row=0; row < raw_height; row++) {
memset (pred, 0, sizeof pred);
if (!bit) fget4(ifp);
for (col=bit=0; col < raw_width; col++) {
for (c=0; c < 3; c++) {
for (dindex=first_decode; dindex->branch[0]; ) {
if ((bit = (bit-1) & 31) == 31)
for (i=0; i < 4; i++)
bitbuf = (bitbuf << 8) + fgetc(ifp);
dindex = dindex->branch[bitbuf >> bit & 1];
}
pred[c] += diff[dindex->leaf];
}
if ((unsigned) (row-top_margin) >= height ||
(unsigned) (col-left_margin) >= width ) continue;
for (c=0; c < 3; c++)
if (pred[c] > 0)
image[(row-top_margin)*width+(col-left_margin)][c] = pred[c];
}
}
}
 
int CLASS apply_curve (int i, const int *curve)
{
if (i <= -curve[0])
return -curve[curve[0]]-1;
else if (i < 0)
return -curve[1-i];
else if (i < curve[0])
return curve[1+i];
else
return curve[curve[0]]+1;
}
 
void CLASS foveon_interpolate()
{
float mul[3] =
{ 1.0321, 1.0, 1.1124 };
static const int weight[3][3][3] =
{ { { 4141, 37726, 11265 },
{ -30437, 16066, -41102 },
{ 326, -413, 362 } },
{ { 1770, -1316, 3480 },
{ -2139, 213, -4998 },
{ -2381, 3496, -2008 } },
{ { -3838, -24025, -12968 },
{ 20144, -12195, 30272 },
{ -631, -2025, 822 } } },
curve1[73] = { 72,
0,1,2,2,3,4,5,6,6,7,8,9,9,10,11,11,12,13,13,14,14,
15,16,16,17,17,18,18,18,19,19,20,20,20,21,21,21,22,
22,22,23,23,23,23,23,24,24,24,24,24,25,25,25,25,25,
25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26 },
curve2[21] = { 20,
0,1,1,2,3,3,4,4,5,5,6,6,6,7,7,7,7,7,7,7 },
curve3[73] = { 72,
0,1,1,2,2,3,4,4,5,5,6,6,7,7,8,8,8,9,9,10,10,10,10,
11,11,11,12,12,12,12,12,12,13,13,13,13,13,13,13,13,
14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
14,14,14,14,14,14,14,14,14,14,14,14,14,14,14 },
curve4[37] = { 36,
0,1,1,2,3,3,4,4,5,6,6,7,7,7,8,8,9,9,9,10,10,10,
11,11,11,11,11,12,12,12,12,12,12,12,12,12 },
curve5[111] = { 110,
0,1,1,2,3,3,4,5,6,6,7,7,8,9,9,10,11,11,12,12,13,13,
14,14,15,15,16,16,17,17,18,18,18,19,19,19,20,20,20,
21,21,21,21,22,22,22,22,22,23,23,23,23,23,24,24,24,24,
24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,26,26,
26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,
26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26 },
*curves[3] = { curve3, curve4, curve5 },
trans[3][3] =
{ { 7576, -2933, 1279 },
{ -11594, 29911, -12394 },
{ 4000, -18850, 20772 } };
ushort *pix, prev[3], (*shrink)[3];
int row, col, c, i, j, diff, sum, ipix[3], work[3][3], total[4];
int (*smrow[7])[3], smlast, smred, smred_p=0, hood[7], min, max;
 
/* Sharpen all colors */
for (row=0; row < height; row++) {
pix = image[row*width];
memcpy (prev, pix, sizeof prev);
for (col=0; col < width; col++) {
for (c=0; c < 3; c++) {
diff = pix[c] - prev[c];
prev[c] = pix[c];
ipix[c] = pix[c] + ((diff + (diff*diff >> 14)) * 0x3333 >> 14);
}
for (c=0; c < 3; c++) {
work[0][c] = ipix[c]*ipix[c] >> 14;
work[2][c] = ipix[c]*work[0][c] >> 14;
work[1][2-c] = ipix[(c+1) % 3] * ipix[(c+2) % 3] >> 14;
}
for (c=0; c < 3; c++) {
for (sum=i=0; i < 3; i++)
for ( j=0; j < 3; j++)
sum += weight[c][i][j] * work[i][j];
ipix[c] = (ipix[c] + (sum >> 14)) * mul[c];
if (ipix[c] < 0) ipix[c] = 0;
if (ipix[c] > 32000) ipix[c] = 32000;
pix[c] = ipix[c];
}
pix += 4;
}
}
/* Array for 5x5 Gaussian averaging of red values */
smrow[6] = calloc (width*5, sizeof **smrow);
merror (smrow[6], "foveon_interpolate()");
for (i=0; i < 5; i++)
smrow[i] = smrow[6] + i*width;
 
/* Sharpen the reds against these Gaussian averages */
for (smlast=-1, row=2; row < height-2; row++) {
while (smlast < row+2) {
for (i=0; i < 6; i++)
smrow[(i+5) % 6] = smrow[i];
pix = image[++smlast*width+2];
for (col=2; col < width-2; col++) {
smrow[4][col][0] =
(pix[0]*6 + (pix[-4]+pix[4])*4 + pix[-8]+pix[8] + 8) >> 4;
pix += 4;
}
}
pix = image[row*width+2];
for (col=2; col < width-2; col++) {
smred = (smrow[2][col][0]*6 + (smrow[1][col][0]+smrow[3][col][0])*4
+ smrow[0][col][0]+smrow[4][col][0] + 8) >> 4;
if (col == 2)
smred_p = smred;
i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 2);
if (i < 0) i = 0;
if (i > 10000) i = 10000;
pix[0] = i;
smred_p = smred;
pix += 4;
}
}
/* Limit each color value to the range of its neighbors */
hood[0] = 4;
for (i=0; i < 3; i++) {
hood[i+1] = (i-width-1)*4;
hood[i+4] = (i+width-1)*4;
}
for (row=1; row < height-1; row++) {
pix = image[row*width+1];
memcpy (prev, pix-4, sizeof prev);
for (col=1; col < width-1; col++) {
for (c=0; c < 3; c++) {
for (min=max=prev[c], i=0; i < 7; i++) {
j = pix[hood[i]];
if (min > j) min = j;
if (max < j) max = j;
}
prev[c] = *pix;
if (*pix < min) *pix = min;
if (*pix > max) *pix = max;
pix++;
}
pix++;
}
}
/*
Because photons that miss one detector often hit another,
the sum R+G+B is much less noisy than the individual colors.
So smooth the hues without smoothing the total.
*/
for (smlast=-1, row=2; row < height-2; row++) {
while (smlast < row+2) {
for (i=0; i < 6; i++)
smrow[(i+5) % 6] = smrow[i];
pix = image[++smlast*width+2];
for (col=2; col < width-2; col++) {
for (c=0; c < 3; c++)
smrow[4][col][c] = pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8];
pix += 4;
}
}
pix = image[row*width+2];
for (col=2; col < width-2; col++) {
for (total[3]=1500, sum=60, c=0; c < 3; c++) {
for (total[c]=i=0; i < 5; i++)
total[c] += smrow[i][col][c];
total[3] += total[c];
sum += pix[c];
}
j = (sum << 16) / total[3];
for (c=0; c < 3; c++) {
i = apply_curve ((total[c] * j >> 16) - pix[c], curve1);
i += pix[c] - 13 - (c==1);
ipix[c] = i - apply_curve (i, curve2);
}
sum = (ipix[0]+ipix[1]+ipix[1]+ipix[2]) >> 2;
for (c=0; c < 3; c++) {
i = ipix[c] - apply_curve (ipix[c] - sum, curve2);
if (i < 0) i = 0;
pix[c] = i;
}
pix += 4;
}
}
/* Translate the image to a different colorspace */
for (pix=image[0]; pix < image[height*width]; pix+=4) {
for (c=0; c < 3; c++) {
for (i=j=0; j < 3; j++)
i += trans[c][j] * pix[j];
i = (i+0x1000) >> 13;
if (i < 0) i = 0;
if (i > 24000) i = 24000;
ipix[c] = i;
}
for (c=0; c < 3; c++)
pix[c] = ipix[c];
}
/* Smooth the image bottom-to-top and save at 1/4 scale */
shrink = calloc ((width/4) * (height/4), sizeof *shrink);
merror (shrink, "foveon_interpolate()");
for (row = height/4; row--; )
for (col=0; col < width/4; col++) {
ipix[0] = ipix[1] = ipix[2] = 0;
for (i=0; i < 4; i++)
for (j=0; j < 4; j++)
for (c=0; c < 3; c++)
ipix[c] += image[(row*4+i)*width+col*4+j][c];
for (c=0; c < 3; c++)
if (row+2 > height/4)
shrink[row*(width/4)+col][c] = ipix[c] >> 4;
else
shrink[row*(width/4)+col][c] =
(shrink[(row+1)*(width/4)+col][c]*1840 + ipix[c]*141) >> 12;
}
 
/* From the 1/4-scale image, smooth right-to-left */
for (row=0; row < (height & ~3); row++) {
ipix[0] = ipix[1] = ipix[2] = 0;
if ((row & 3) == 0)
for (col = width & ~3 ; col--; )
for (c=0; c < 3; c++)
smrow[0][col][c] = ipix[c] =
(shrink[(row/4)*(width/4)+col/4][c]*1485 + ipix[c]*6707) >> 13;
 
/* Then smooth left-to-right */
ipix[0] = ipix[1] = ipix[2] = 0;
for (col=0; col < (width & ~3); col++)
for (c=0; c < 3; c++)
smrow[1][col][c] = ipix[c] =
(smrow[0][col][c]*1485 + ipix[c]*6707) >> 13;
 
/* Smooth top-to-bottom */
if (row == 0)
memcpy (smrow[2], smrow[1], sizeof **smrow * width);
else
for (col=0; col < (width & ~3); col++)
for (c=0; c < 3; c++)
smrow[2][col][c] =
(smrow[2][col][c]*6707 + smrow[1][col][c]*1485) >> 13;
 
/* Adjust the chroma toward the smooth values */
for (col=0; col < (width & ~3); col++) {
for (i=j=60, c=0; c < 3; c++) {
i += smrow[2][col][c];
j += image[row*width+col][c];
}
j = (j << 16) / i;
for (sum=c=0; c < 3; c++) {
i = (smrow[2][col][c] * j >> 16) - image[row*width+col][c];
ipix[c] = apply_curve (i, curves[c]);
sum += ipix[c];
}
sum >>= 3;
for (c=0; c < 3; c++) {
i = image[row*width+col][c] + ipix[c] - sum;
if (i < 0) i = 0;
image[row*width+col][c] = i;
}
}
}
free(shrink);
free(smrow[6]);
}
 
/*
Seach from the current directory up to the root looking for
a ".badpixels" file, and fix those pixels now.
*/
void CLASS bad_pixels()
{
FILE *fp=NULL;
char *fname, *cp, line[128];
int len, time, row, col, r, c, rad, tot, n, fixed=0;
 
if (!filters) return;
for (len=16 ; ; len *= 2) {
fname = malloc (len);
if (!fname) return;
if (getcwd (fname, len-12)) break;
free (fname);
if (errno != ERANGE) return;
}
#ifdef WIN32
if (fname[1] == ':')
memmove (fname, fname+2, len-2);
for (cp=fname; *cp; cp++)
if (*cp == '\\') *cp = '/';
#endif
cp = fname + strlen(fname);
if (cp[-1] == '/') cp--;
while (*fname == '/') {
strcpy (cp, "/.badpixels");
if ((fp = fopen (fname, "r"))) break;
if (cp == fname) break;
while (*--cp != '/');
}
free (fname);
if (!fp) return;
while (fgets (line, 128, fp)) {
cp = strchr (line, '#');
if (cp) *cp = 0;
if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue;
if ((unsigned) col >= width || (unsigned) row >= height) continue;
if (time > timestamp) continue;
for (tot=n=0, rad=1; rad < 3 && n==0; rad++)
for (r = row-rad; r <= row+rad; r++)
for (c = col-rad; c <= col+rad; c++)
if ((unsigned) r < height && (unsigned) c < width &&
(r != row || c != col) && FC(r,c) == FC(row,col)) {
tot += BAYER(r,c);
n++;
}
BAYER(row,col) = tot/n;
if (verbose) {
if (!fixed++)
fprintf (stderr, "Fixed bad pixels at:");
fprintf (stderr, " %d,%d", col, row);
}
}
if (fixed) fputc ('\n', stderr);
fclose (fp);
}
 
int CLASS get_generic_parameter(FILE *fp, const char *name, const char *line,
const char *sequence, void *where, int *flag)
{
if (strcmp(line, name) == 0) {
int status;
char data[128];
if (!fgets(data, 127, fp))
return -1;
if (feof(fp))
return -1;
status = sscanf (data, sequence, where);
if (status != 1)
return -1;
if (flag)
*flag = 1;
return 1;
} else
return 0;
}
 
int CLASS get_float_parameter(FILE *fp, const char *name, const char *line,
float *where, int *flag)
{
return get_generic_parameter(fp, name, line, "%f", where, flag);
}
 
int CLASS get_int_parameter(FILE *fp, const char *name, const char *line,
int *where, int *flag)
{
return get_generic_parameter(fp, name, line, "%d", where, flag);
}
 
/*
Get value of parameters from file.
*/
int get_parameter_value(FILE *fp)
{
char *cp, line[128], data[128];
float my_coeff[3][4];
int i, j;
int got_coeff=0;
 
while (1) {
fgets (line, 128, fp);
if (feof(fp)) break;
cp = strchr (line, '#');
if (cp) *cp = 0;
 
if (get_float_parameter(fp, "gamma:\n", line,
&gamma_val, NULL) == -1)
break;
 
if (get_float_parameter(fp, "brightness:\n", line,
&bright, NULL) == -1)
break;
 
if (get_float_parameter(fp, "red scale:\n", line,
&red_scale, NULL) == -1)
break;
 
if (get_float_parameter(fp, "blue scale:\n", line,
&blue_scale, NULL) == -1)
break;
 
if (get_float_parameter(fp, "green scale:\n", line,
&green_scale, NULL) == -1)
break;
 
if (get_float_parameter(fp, "juice:\n", line,
&juice, NULL) == -1)
break;
 
if (get_float_parameter(fp, "white point fraction:\n", line,
&white_point_fraction, NULL) == -1)
break;
 
if (get_float_parameter(fp, "pivot value:\n", line,
&pivot_value, NULL) == -1)
break;
 
if (get_float_parameter(fp, "exposure compensation:\n", line,
&exposure_compensation, NULL) == -1)
break;
 
if (get_float_parameter(fp, "saturation:\n", line,
&saturation, NULL) == -1)
break;
 
if (get_float_parameter(fp, "contrast:\n", line,
&contrast, NULL) == -1)
break;
 
if (get_int_parameter(fp, "flip:\n", line,
&flip, NULL) == -1)
break;
 
if (!strcmp(line, "color matrix:\n")) {
int status = 0;
for (i=0; i < 3; i++) {
fgets (data, 128, fp);
if (feof(fp)) {
got_coeff = 0;
break;
}
status= sscanf (data, "%f %f %f %f",
&my_coeff[i][0], &my_coeff[i][1],
&my_coeff[i][2], &my_coeff[i][3]);
if (status < 3 || status > 4 ||
(got_coeff > 0 && got_coeff != status)) {
got_coeff = 0;
break;
}
if (got_coeff == 0)
got_coeff = status;
}
}
}
 
if (juice != 0.0) {
if (got_coeff > 0) {
if (verbose) {
fprintf (stderr, "Color matrix with juice = %f:\n", juice);
for (i=0; i < 3; i++)
fprintf (stderr, " [%f %f %f %f]\n",
my_coeff[i][0], my_coeff[i][1], my_coeff[i][2], my_coeff[i][3]);
for (i=0; i < 3; i++)
for (j=0; j < got_coeff; j++) {
if (i == j || i == 1 && j == 3)
coeff[i][j] = my_coeff[i][j] * juice + (1-juice);
else
coeff[i][j] = my_coeff[i][j] * juice;
}
use_coeff = 1;
}
}
}
}
 
void get_parameters()
{
FILE *fp=NULL;
char *fname, *cp;
const char *default_file="default.prm", *prm_ext = ".prm";
int len;
 
fp = fopen (default_file, "r");
if (fp) {
get_parameter_value (fp);
fclose (fp);
}
 
fname = malloc (strlen(ifname) + 16);
merror (fname, "get_parameters()");
strcpy (fname, ifname);
if ((cp = strrchr (fname, '.'))) *cp = 0;
strcat (fname, prm_ext);
fp = fopen (fname, "r");
free (fname);
if (!fp) return;
 
get_parameter_value (fp);
fclose (fp);
}
 
void CLASS scale_colors()
{
int row, col, c, val;
int min[4], max[4], count[4];
double sum[4], dmin, dmax;
double *x_weights, *y_weights;
 
int i;
ushort *lut[4];
ushort abs_max = 0;
ushort abs_min = ABS_MAX;
int clipped_pixels[4];
int total_clipped_pixels = 0;
int total_pixels = 0;
int weighted_total_pixels = 0;
double pixels[4];
double white_fraction = 1.0 - white_point_fraction;
double total = 0.0;
double totals[4];
double means[4];
int mean;
float compensation = exp2(exposure_compensation);
double post_mul = 1.0;
double auto_compensation = 1.0;
int original_rgb_max;
 
if (user_black >= 0)
black = user_black;
if (white_fraction > 1)
white_fraction = 1;
else if (white_fraction < 0)
white_fraction = 0;
if (use_neutral_wb) {
for (c=0; c < 4; c++) {
pre_mul[c] = 1.0;
}
}
for (c = 0; c < 4; c++) {
pixels[c] = 0;
totals[c] = 0;
clipped_pixels[c] = 0;
}
memset (histogram, 0, sizeof histogram);
for (c=0; c < 4; c++) {
min[c] = INT_MAX;
max[c] = count[c] = sum[c] = 0;
}
if (center_weight) {
x_weights = malloc(sizeof(double) * width);
y_weights = malloc(sizeof(double) * height);
for (row = 0; row < height; row++)
y_weights[row]= exp(-pow(abs((row - (height / 2)) / (height / 4)), 3.0));
for (col = 0; col < width; col++)
x_weights[col] = exp(-pow(abs((col - (width / 2)) / (width / 4)), 3.0));
}
for (row=0; row < height; row++) {
for (col=0; col < width; col++) {
for (c=0; c < colors; c++) {
double weight = 1;
val = image[row*width+col][c];
if (!val) continue;
if (use_camera_black && val < black)
val = black;
histogram[val >> 3]++;
if (val >= rgb_max - 100) {
clipped_pixels[c]++;
total_clipped_pixels++;
}
total += val;
total_pixels++;
if (center_weight) {
double x_weight = x_weights[col];
double y_weight = y_weights[row];
weight = x_weight * y_weight;
}
totals[c] += val * weight;
pixels[c] += weight;
weighted_total_pixels += weight;
if (min[c] > val) min[c] = val;
if (max[c] < val) max[c] = val;
if (val < abs_min)
abs_min = val;
if (val > abs_max)
abs_max = val;
}
}
}
if (center_weight) {
free(x_weights);
free(y_weights);
}
if (rgb_max < abs_max)
rgb_max = abs_max;
if (black > abs_min)
black = abs_min;
abs_max -= black;
abs_min -= black;
mean = (total / total_pixels) - black;
for (c = 0; c < 4; c++) {
means[c] = 0;
max[c] -= black;
min[c] -= black;
}
for (c = 0; c < colors; c++)
if (pixels[c])
means[c] = (totals[c] / pixels[c]) - black;
 
rgb_max -= black;
if (use_auto_wb || (use_camera_wb && camera_red == -1)) {
for (c=0; c < 4; c++) {
min[c] = INT_MAX;
max[c] = count[c] = sum[c] = 0;
}
for (row=0; row < height; row++)
for (col=0; col < width; col++)
for (c=0; c < colors; c++) {
val = image[row*width+col][c];
if (!val) continue;
if (use_camera_black && val < black)
val = black;
if (min[c] > val) min[c] = val;
if (max[c] < val) max[c] = val;
val -= black;
if (val > rgb_max-100) continue;
if (val < 0) val = 0;
sum[c] += val;
count[c]++;
}
for (dmax=c=0; c < colors; c++) {
sum[c] /= count[c];
if (dmax < sum[c]) dmax = sum[c];
}
for (c=0; c < colors; c++)
pre_mul[c] = dmax / sum[c];
}
if (use_camera_wb && camera_red != -1) {
for (c=0; c < 4; c++)
count[c] = sum[c] = 0;
for (row=0; row < 8; row++)
for (col=0; col < 8; col++) {
c = FC(row,col);
if ((val = white[row][col] - black) > 0)
sum[c] += val;
count[c]++;
}
for (dmin=DBL_MAX, dmax=c=0; c < colors; c++) {
sum[c] /= count[c];
if (dmin > sum[c]) dmin = sum[c];
if (dmax < sum[c]) dmax = sum[c];
}
if (dmin > 0)
for (c=0; c < colors; c++)
pre_mul[c] = dmax / sum[c];
else if (camera_red && camera_blue) {
pre_mul[0] = camera_red;
pre_mul[2] = camera_blue;
pre_mul[1] = pre_mul[3] = 1.0;
} else
fprintf (stderr, "%s: Cannot use camera white balance.\n", ifname);
}
 
total = 0;
for (c = 0; c < colors; c++) {
if (pixels[c] > 0)
total += means[c] * pixels[c] / pre_mul[c];
}
total /= weighted_total_pixels;
 
if (!use_coeff) {
pre_mul[0] *= red_scale;
pre_mul[2] *= blue_scale;
pre_mul[1] *= green_scale;
pre_mul[3] *= green_scale;
}
for (c = 0; c < 4; c++)
pre_mul[c] *= compensation;
 
if (autoexposure) {
auto_compensation = .3 / ((double) total / (double) rgb_max);
if (auto_compensation > 4.0) /* Don't overcompensate dark images */
auto_compensation = 4.0 * sqrt(auto_compensation / 4.0);
for (c = 0; c < 4; c++)
pre_mul[c] *= auto_compensation;
if ((auto_compensation * compensation) > 1 && !use_pivot)
pivot_value /= (auto_compensation * compensation);
use_pivot = 1;
}
if (pivot_value > 1)
use_pivot = 0;
 
for (c=0; c < 4; c++) {
if (pre_mul[c] < post_mul) {
post_mul = pre_mul[c];
}
}
for (c=0; c < 4; c++) {
pre_mul[c] /= post_mul;
}
 
for (c = 0; c < 4; c++)
lut[c] = NULL;
if (use_pivot) {
for (c=0; c < c; c++) {
if (pre_mul[c] > 1.0) {
double k = pre_mul[c];
double rescale = 1.0 - (clipped_pixels[c] / pixels[c]);
double start = pivot_value * rescale * rescale;
double start_1 = 1 - start;
double x_start = start / k;
double x_start_1 = 1 - x_start;
double end_slope = alternate_scale ? 1.0 / (3 * k) : 0;
double end_intercept = 1.0 - end_slope;
double end_start = end_intercept + x_start * end_slope;
double end_start_1 = 1.0 - end_start;
double diff = start_1 - end_start_1;
double scale = 1 / x_start_1;
/*
* Choose the exponent so that at 1.0 the first derivative
* of the curve is pre_mul[c].
*/
double expt = ((k - end_slope) * x_start_1 / diff);
if (verbose) {
fprintf(stderr, "Pivot channel %d: k %f start %f x_start %f x_start_1 %f expt %f scale %f end_slope %f end_intercept %f end_start %f end_start_1 %f diff %f\n",
c, k, start, x_start, x_start_1, expt, scale,
end_slope, end_intercept, end_start, end_start_1, diff);
}
lut[c] = malloc (sizeof(ushort) * 65536);
k = k * RGB_MAX / rgb_max;
for (i = 0; i <= rgb_max; i++) {
double base = i / (double) rgb_max;
if (base <= x_start) {
lut[c][i] = k * i;
} else if (base > rgb_max) {
lut[c][i] = RGB_MAX;
} else {
/*
* Roundoff error may result in this going slightly negative.
* That's bad juju.
*/
double x_base = 1 - ((base - x_start) * scale);
if (x_base < 0)
x_base = 0;
lut[c][i] =
(RGB_MAX *
(end_intercept + (base * end_slope) -
(diff * pow(x_base, expt))));
}
}
}
}
}
for (c = 0; c < colors; c++)
pre_mul[c] = pre_mul[c] * RGB_MAX / rgb_max;
original_rgb_max = rgb_max;
rgb_max = RGB_MAX;
if (verbose) {
fprintf (stderr, "Scaling with black=%d, pre_mul[] =", black);
for (c=0; c < colors; c++)
fprintf (stderr, " %f", pre_mul[c]);
fputc ('\n', stderr);
fprintf (stderr, "Maximum level %d (%d, %.2f%%)\n", abs_max,
abs_max * 65536 / original_rgb_max,
100.0 * abs_max / original_rgb_max);
fprintf (stderr, "Minimum level %d (%d, %.2f%%)\n", abs_min,
abs_min * 65536 / original_rgb_max,
100.0 * abs_min / original_rgb_max);
fprintf (stderr, "Mean level %d (%d, %.2f%%)\n", mean,
mean * 65536 / original_rgb_max,
100.0 * mean / original_rgb_max);
fprintf (stderr, "Weighted mean level %f (%f, %.2f%%)\n", total,
total * 65536 / original_rgb_max,
100.0 * total / original_rgb_max);
for (c = 0; c < colors; c++)
if (pixels[c] > 0)
fprintf (stderr, "Mean[%d] level %f (%f, %.2f%%) %.2f pixels\n",
c, means[c], means[c] * 65536 / original_rgb_max,
100.0 * means[c] / original_rgb_max, pixels[c]);
for (c = 0; c < colors; c++)
if (pixels[c] > 0)
fprintf (stderr, "Max[%d] level %d (%d, %.2f%%) %.2f pixels\n",
c, max[c], max[c] * 65536 / original_rgb_max,
100.0 * (double) max[c] / original_rgb_max, pixels[c]);
fprintf (stderr, "Auto exposure compensation %f (%f stops)\n",
auto_compensation,
log(auto_compensation) / log(2));
fprintf (stderr, "Manual exposure compensation %f (%f stops)\n",
compensation, exposure_compensation);
fprintf (stderr, "Total exposure compensation %f (%f stops)\n",
auto_compensation * compensation,
log(auto_compensation * compensation) / log(2));
fprintf (stderr, "Post multiplier %f (%f stops)\n",
post_mul, log(post_mul) / log(2));
fprintf (stderr, "Clipped pixels: %d/%d, %.2f%%\n",
total_clipped_pixels, total_pixels,
(double) total_clipped_pixels / total_pixels * 100);
for (c = 0; c < colors; c++)
if (pixels[c] > 0)
fprintf(stderr, "Clipped[%d] %d (%.2f%%)\n", c, clipped_pixels[c],
100.0 * clipped_pixels[c] / pixels[c]);
}
for (row=0; row < height; row++)
for (col=0; col < width; col++)
for (c=0; c < colors; c++) {
val = image[row*width+col][c];
if (!val) continue;
if (use_camera_black && val < black)
val = black;
val -= black;
if (lut[c])
val = lut[c][val];
else
val *= pre_mul[c];
if (val < 0) val = 0;
if (val > rgb_max) val = rgb_max;
val *= post_mul;
image[row*width+col][c] = val;
}
for (c = 0; c < colors; c++) {
if (lut[c])
free(lut[c]);
}
}
 
/*
This algorithm is officially called:
 
"Interpolation using a Threshold-based variable number of gradients"
 
described in http://www-ise.stanford.edu/~tingchen/algodep/vargra.html
 
I've extended the basic idea to work with non-Bayer filter arrays.
Gradients are numbered clockwise from NW=0 to W=7.
*/
void CLASS vng_interpolate()
{
static const signed char *cp, terms[] = {
-2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
-2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
-2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
-2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
-2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
-1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
-1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
-1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
-1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
-1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
-1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
-1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
-1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
+0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
+0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
+0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
+0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
+0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
+0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
+0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
+1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
+1,+0,+2,+1,0,0x10
}, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
ushort (*brow[5])[4], *pix;
int code[8][2][320], *ip, gval[8], gmin, gmax, sum[4];
int row, col, shift, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
int g, diff, thold, num, c;
 
for (row=0; row < 8; row++) { /* Precalculate for bilinear */
for (col=1; col < 3; col++) {
ip = code[row][col & 1];
memset (sum, 0, sizeof sum);
for (y=-1; y <= 1; y++)
for (x=-1; x <= 1; x++) {
shift = (y==0) + (x==0);
if (shift == 2) continue;
color = FC(row+y,col+x);
*ip++ = (width*y + x)*4 + color;
*ip++ = shift;
*ip++ = color;
sum[color] += 1 << shift;
}
for (c=0; c < colors; c++)
if (c != FC(row,col)) {
*ip++ = c;
*ip++ = sum[c];
}
}
}
 
 
 
 
for (row=1; row < height-1; row++)
{ /* Do bilinear interpolation */
for (col=1; col < width-1; col++)
{
pix = image[row*width+col];
ip = code[row & 7][col & 1];
memset (sum, 0, sizeof sum);
 
for (g=8; g--; )
{
diff = pix[*ip++];
diff <<= *ip++;
sum[*ip++] += diff;
}
 
for (g=colors; --g; )
{
c = *ip++;
pix[c] = sum[c] / *ip++;
}
 
 
}
}
 
 
if (quick_interpolate)
return;
 
 
 
for (row=0; row < 8; row++)
{ /* Precalculate for VNG */
for (col=0; col < 2; col++)
{
ip = code[row][col];
for (cp=terms, t=0; t < 64; t++)
{
y1 = *cp++; x1 = *cp++;
y2 = *cp++; x2 = *cp++;
weight = *cp++;
grads = *cp++;
color = FC(row+y1,col+x1);
if (FC(row+y2,col+x2) != color) continue;
diag = (FC(row,col+1) == color && FC(row+1,col) == color) ? 2:1;
if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
*ip++ = (y1*width + x1)*4 + color;
*ip++ = (y2*width + x2)*4 + color;
*ip++ = weight;
for (g=0; g < 8; g++)
if (grads & 1<<g) *ip++ = g;
*ip++ = -1;
}
*ip++ = INT_MAX;
for (cp=chood, g=0; g < 8; g++) {
y = *cp++; x = *cp++;
*ip++ = (y*width + x) * 4;
color = FC(row,col);
if (FC(row+y,col+x) != color && FC(row+y*2,col+x*2) == color)
*ip++ = (y*width + x) * 8 + color;
else
*ip++ = 0;
}
}
}
 
 
 
 
brow[4] = calloc (width*3, sizeof **brow);
merror (brow[4], "vng_interpolate()");
for (row=0; row < 3; row++)
brow[row] = brow[4] + row*width;
 
/* Do VNG interpolation */
for (row=2; row < height-2; row++)
{
 
 
 
 
 
for (col=2; col < width-2; col++)
{
 
 
pix = image[row*width+col];
ip = code[row & 7][col & 1];
memset (gval, 0, sizeof gval);
 
 
/* Calculate gradients */
while ((g = ip[0]) != INT_MAX)
{
num = (diff = pix[g] - pix[ip[1]]) >> 31;
gval[ip[3]] += (diff = ((diff ^ num) - num) << ip[2]);
ip += 5;
if ((g = ip[-1]) == -1) continue;
gval[g] += diff;
while ((g = *ip++) != -1)
gval[g] += diff;
}
ip++;
 
 
 
gmin = gmax = gval[0]; /* Choose a threshold */
for (g=1; g < 8; g++)
{
if (gmin > gval[g]) gmin = gval[g];
if (gmax < gval[g]) gmax = gval[g];
}
 
 
 
 
if (gmax == 0)
{
memcpy (brow[2][col], pix, sizeof *image);
continue;
}
 
 
 
 
 
thold = (k1-k2)*gmin + k2*gmax;
memset (sum, 0, sizeof sum);
color = FC(row,col);
 
 
 
for (num=g=0; g < 8; g++,ip+=2)
{ /* Average the neighbors */
if (gval[g] <= thold)
{
for (c=0; c < colors; c++)
if (c == color && ip[1])
sum[c] += (pix[c] + pix[ip[1]]) >> 1;
else
sum[c] += pix[ip[0] + c];
num++;
}
}
 
 
 
 
 
 
 
for (c=0; c < colors; c++)
{ /* Save to buffer */
t = pix[color];
if (c != color)
{
t += (sum[c] - sum[color])/num;
if (t < 0) t = 0;
if (t > rgb_max) t = rgb_max;
}
brow[2][col][c] = t;
}
 
 
 
 
 
}
 
 
 
 
 
 
 
if (row > 3) /* Write buffer to image */
memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
for (g=0; g < 4; g++)
brow[(g-1) & 3] = brow[g];
}
 
 
 
 
 
 
 
 
memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image);
free(brow[4]);
}
 
/*
Interpolation for 1/16 thumbnail file. Just take an average of the
unit pixels.
*/
void thm_interpolate()
{
int row, col, x, y, c;
int sum[4];
 
for (row=0; row < height; row += 4) {
for (col=0; col < width; col += 4) {
memset (sum, 0, sizeof sum);
for (y=0; y < 4; y++){
for (x=0; x< 4; x++){
sum[0] += (image[(row+y)*width+(col+x)][0] >> 2);
sum[1] += (image[(row+y)*width+(col+x)][1] >> 3);
sum[2] += (image[(row+y)*width+(col+x)][2] >> 2);
}
}
for (c=0; c < 3; c++)
image[row*width+col][c] = sum[c];
}
}
}
 
 
void CLASS tiff_parse_subifd (int base)
{
int entries, tag, type, len, val, save;
 
entries = fget2(ifp);
while (entries--) {
tag = fget2(ifp);
type = fget2(ifp);
len = fget4(ifp);
if (type == 3 && len < 3) {
val = fget2(ifp); fget2(ifp);
} else
val = fget4(ifp);
switch (tag) {
case 0x100: /* ImageWidth */
raw_width = val;
break;
case 0x101: /* ImageHeight */
raw_height = val;
break;
case 0x102: /* Bits per sample */
break;
case 0x103: /* Compression */
tiff_data_compression = val;
break;
case 0x106: /* Kodak color format */
kodak_data_compression = val;
break;
case 0x111: /* StripOffset */
if (len == 1)
data_offset = val;
else {
save = ftell(ifp);
fseek (ifp, val+base, SEEK_SET);
data_offset = fget4(ifp);
fseek (ifp, save, SEEK_SET);
}
break;
case 0x115: /* SamplesPerRow */
break;
case 0x116: /* RowsPerStrip */
break;
case 0x117: /* StripByteCounts */
break;
case 0x123:
curve_offset = val;
curve_length = len;
}
}
}
 
void CLASS nef_parse_makernote()
{
int base=0, offset=0, entries, tag, type, len, val, save;
short sorder;
char buf[10];
 
/*
The MakerNote might have its own TIFF header (possibly with
its own byte-order!), or it might just be a table.
*/
sorder = order;
fread (buf, 1, 10, ifp);
if (!strcmp (buf,"Nikon")) { /* starts with "Nikon\0\2\0\0\0" ? */
base = ftell(ifp);
order = fget2(ifp); /* might differ from file-wide byteorder */
val = fget2(ifp); /* should be 42 decimal */
offset = fget4(ifp);
fseek (ifp, offset-8, SEEK_CUR);
} else if (!strcmp (buf,"OLYMP"))
fseek (ifp, -2, SEEK_CUR);
else
fseek (ifp, -10, SEEK_CUR);
 
entries = fget2(ifp);
while (entries--) {
tag = fget2(ifp);
type = fget2(ifp);
len = fget4(ifp);
if (type == 3) { /* short int */
val = fget2(ifp); fget2(ifp);
} else
val = fget4(ifp);
save = ftell(ifp);
if (tag == 0xc) {
fseek (ifp, base+val, SEEK_SET);
camera_red = fget4(ifp);
camera_red /= fget4(ifp);
camera_blue = fget4(ifp);
camera_blue/= fget4(ifp);
}
if (tag == 0x8c)
curve_offset = base+val + 2112;
if (tag == 0x96)
curve_offset = base+val + 2;
if (tag == 0x97) {
if (!strcmp(model,"NIKON D100 ")) {
fseek (ifp, base+val + 72, SEEK_SET);
camera_red = fget2(ifp) / 256.0;
camera_blue = fget2(ifp) / 256.0;
} else if (!strcmp(model,"NIKON D2H")) {
fseek (ifp, base+val + 10, SEEK_SET);
camera_red = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue = fget2(ifp);
camera_blue = fget2(ifp) / camera_blue;
} else if (!strcmp(model,"NIKON D70")) {
fseek (ifp, base+val + 20, SEEK_SET);
camera_red = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue = fget2(ifp);
camera_blue/= fget2(ifp);
}
}
if (tag == 0x1017) /* Olympus */
camera_red = val / 256.0;
if (tag == 0x1018)
camera_blue = val / 256.0;
fseek (ifp, save, SEEK_SET);
}
order = sorder;
}
 
/*
Since the TIFF DateTime string has no timezone information,
assume that the camera's clock was set to Universal Time.
*/
void CLASS get_timestamp()
{
struct tm t;
time_t ts;
 
if (fscanf (ifp, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
&t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
return;
t.tm_year -= 1900;
t.tm_mon -= 1;
putenv ("TZ=UTC"); /* Remove this to assume local time */
if ((ts = mktime(&t)) > 0)
timestamp = ts;
}
 
void CLASS nef_parse_exif (int base)
{
int entries, tag, type, len, val, save;
 
entries = fget2(ifp);
while (entries--) {
tag = fget2(ifp);
type = fget2(ifp);
len = fget4(ifp);
val = fget4(ifp);
save = ftell(ifp);
fseek (ifp, val+base, SEEK_SET);
if (tag == 0x9003 || tag == 0x9004)
get_timestamp();
if (tag == 0x927c &&
(!strncmp(make,"NIKON",5) || !strncmp(make,"OLYMPUS",7)))
nef_parse_makernote();
fseek (ifp, save, SEEK_SET);
}
}
 
/*
Parse a TIFF file looking for camera model and decompress offsets.
*/
void CLASS parse_tiff (int base)
{
int doff, entries, tag, type, len, val, save;
char software[64];
int wide=0, high=0, cr2_offset=0, offset=0;
static const int flip_map[] = { 0,1,3,2,4,6,7,5 };
 
fseek (ifp, base, SEEK_SET);
order = fget2(ifp);
val = fget2(ifp); /* Should be 42 for standard TIFF */
while ((doff = fget4(ifp))) {
fseek (ifp, doff+base, SEEK_SET);
entries = fget2(ifp);
while (entries--) {
tag = fget2(ifp);
type = fget2(ifp);
len = fget4(ifp);
if (type == 3 && len < 3) {
val = fget2(ifp); fget2(ifp);
} else
val = fget4(ifp);
save = ftell(ifp);
fseek (ifp, val+base, SEEK_SET);
 
 
//printf("%d %x\n", ftell(ifp), tag);
 
switch (tag) {
case 0x11:
camera_red = val / 256.0;
break;
case 0x12:
camera_blue = val / 256.0;
break;
case 0x100: /* ImageWidth */
wide = val;
break;
case 0x101: /* ImageHeight */
high = val;
break;
case 0x10f: /* Make tag */
fgets (make, 64, ifp);
break;
case 0x110: /* Model tag */
fgets (model, 64, ifp);
break;
case 0x111: /* StripOffset */
cr2_offset = val;
offset = fget4(ifp);
break;
case 0x112: /* Rotation */
flip = flip_map[(val-1) & 7];
break;
case 0x123:
curve_offset = val;
curve_length = len;
break;
case 0x827d: /* Model2 tag */
fgets (model2, 64, ifp);
break;
case 0x131: /* Software tag */
fgets (software, 64, ifp);
if (!strncmp(software,"Adobe",5))
make[0] = 0;
break;
case 0x132: /* DateTime tag */
get_timestamp();
break;
case 0x144:
strcpy (make, "Leaf");
raw_width = wide;
raw_height = high;
if (len > 1)
data_offset = fget4(ifp);
else
data_offset = val;
break;
case 0x14a: /* SubIFD tag */
if (len > 2 && !strcmp(make,"Kodak"))
len = 2;
if (len > 1)
while (len--) {
fseek (ifp, val+base, SEEK_SET);
fseek (ifp, fget4(ifp)+base, SEEK_SET);
tiff_parse_subifd(base);
val += 4;
}
else
tiff_parse_subifd(base);
break;
case 0x8769: /* Nikon EXIF tag */
nef_parse_exif(base);
break;
}
 
fseek (ifp, save, SEEK_SET);
}
}
 
if (!strncmp(make,"OLYMPUS",7)) {
make[7] = 0;
raw_width = wide;
raw_height = - (-high & -2);
data_offset = offset;
}
if (!strcmp(make,"Canon") && strcmp(model,"EOS D2000C"))
data_offset = cr2_offset;
 
if (make[0] == 0 && wide == 680 && high == 680) {
strcpy (make, "Imacon");
strcpy (model, "Ixpress");
}
}
 
/*
CIFF block 0x1030 contains an 8x8 white sample.
Load this into white[][] for use in scale_colors().
*/
void CLASS ciff_block_1030()
{
static const ushort key[] = { 0x410, 0x45f3 };
int i, bpp, row, col, vbits=0;
unsigned long bitbuf=0;
 
fget2(ifp);
if (fget4(ifp) != 0x80008) return;
if (fget4(ifp) == 0) return;
bpp = fget2(ifp);
if (bpp != 10 && bpp != 12) return;
for (i=row=0; row < 8; row++)
for (col=0; col < 8; col++) {
if (vbits < bpp) {
bitbuf = bitbuf << 16 | (fget2(ifp) ^ key[i++ & 1]);
vbits += 16;
}
white[row][col] =
bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp) << (14-bpp);
vbits -= bpp;
}
}
 
/*
Parse the CIFF structure looking for two pieces of information:
The camera model, and the decode table number.
*/
void CLASS parse_ciff (int offset, int length)
{
int tboff, nrecs, i, type, len, roff, aoff, save, wbi=-1;
static const int remap[] = { 1,2,3,4,5,1 };
static const int remap_10d[] = { 0,1,3,4,5,6,0,0,2,8 };
 
fseek (ifp, offset+length-4, SEEK_SET);
tboff = fget4(ifp) + offset;
fseek (ifp, tboff, SEEK_SET);
nrecs = fget2(ifp);
for (i = 0; i < nrecs; i++) {
type = fget2(ifp);
len = fget4(ifp);
roff = fget4(ifp);
aoff = offset + roff;
save = ftell(ifp);
if (type == 0x080a) { /* Get the camera make and model */
fseek (ifp, aoff, SEEK_SET);
fread (make, 64, 1, ifp);
fseek (ifp, aoff+strlen(make)+1, SEEK_SET);
fread (model, 64, 1, ifp);
}
if (type == 0x102a) { /* Find the White Balance index */
fseek (ifp, aoff+14, SEEK_SET); /* 0=auto, 1=daylight, 2=cloudy ... */
wbi = fget2(ifp);
if (((!strcmp(model,"Canon EOS DIGITAL REBEL") ||
!strcmp(model,"Canon EOS 300D DIGITAL"))) && wbi == 6)
wbi++;
}
if (type == 0x102c) { /* Get white balance (G2) */
if (!strcmp(model,"Canon PowerShot G1") ||
!strcmp(model,"Canon PowerShot Pro90 IS")) {
fseek (ifp, aoff+120, SEEK_SET);
white[0][1] = fget2(ifp) << 4;
white[0][0] = fget2(ifp) << 4;
white[1][0] = fget2(ifp) << 4;
white[1][1] = fget2(ifp) << 4;
} else {
fseek (ifp, aoff+100, SEEK_SET);
if (wbi == 6 && fget4(ifp) == 0)
wbi = 15;
else {
fseek (ifp, aoff+100, SEEK_SET);
goto common;
}
}
}
if (type == 0x0032) { /* Get white balance (D30 & G3) */
if (!strcmp(model,"Canon EOS D30")) {
fseek (ifp, aoff+72, SEEK_SET);
common:
camera_red = fget2(ifp);
camera_red = fget2(ifp) / camera_red;
camera_blue = fget2(ifp);
camera_blue /= fget2(ifp);
} else {
fseek (ifp, aoff+80 + (wbi < 6 ? remap[wbi]*8 : 0), SEEK_SET);
if (!camera_red)
goto common;
}
}
if (type == 0x10a9) { /* Get white balance (D60) */
if (!strcmp(model,"Canon EOS 10D"))
wbi = remap_10d[wbi];
fseek (ifp, aoff+2 + wbi*8, SEEK_SET);
camera_red = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue = fget2(ifp);
camera_blue = fget2(ifp) / camera_blue;
}
if (type == 0x1030 && wbi > 14) { /* Get white sample */
fseek (ifp, aoff, SEEK_SET);
ciff_block_1030();
}
if (type == 0x1031) { /* Get the raw width and height */
fseek (ifp, aoff+2, SEEK_SET);
raw_width = fget2(ifp);
raw_height = fget2(ifp);
}
if (type == 0x180e) { /* Get the timestamp */
fseek (ifp, aoff, SEEK_SET);
timestamp = fget4(ifp);
}
if (type == 0x580e)
timestamp = len;
if (type == 0x1810) { /* Get the rotation */
fseek (ifp, aoff+12, SEEK_SET);
switch (fget4(ifp)) {
case 270: flip = 5; break;
case 180: flip = 3; break;
case 90: flip = 6;
}
}
if (type == 0x1835) { /* Get the decoder table */
fseek (ifp, aoff, SEEK_SET);
crw_init_tables (fget4(ifp));
}
if (type >> 8 == 0x28 || type >> 8 == 0x30) /* Get sub-tables */
parse_ciff(aoff, len);
fseek (ifp, save, SEEK_SET);
}
if (wbi == 0 && !strcmp(model,"Canon EOS D30"))
camera_red = -1; /* Use my auto WB for this photo */
}
 
void CLASS parse_rollei()
{
char line[128], *val;
int tx=0, ty=0;
struct tm t;
time_t ts;
 
fseek (ifp, 0, SEEK_SET);
do {
fgets (line, 128, ifp);
if ((val = strchr(line,'=')))
*val++ = 0;
else
val = line + strlen(line);
if (!strcmp(line,"DAT"))
sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
if (!strcmp(line,"TIM"))
sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
if (!strcmp(line,"HDR"))
data_offset = atoi(val);
if (!strcmp(line,"X "))
raw_width = atoi(val);
if (!strcmp(line,"Y "))
raw_height = atoi(val);
if (!strcmp(line,"TX "))
tx = atoi(val);
if (!strcmp(line,"TY "))
ty = atoi(val);
} while (strncmp(line,"EOHD",4));
t.tm_year -= 1900;
t.tm_mon -= 1;
putenv ("TZ=");
if ((ts = mktime(&t)) > 0)
timestamp = ts;
data_offset += tx * ty * 2;
strcpy (make, "Rollei");
strcpy (model, "d530flex");
}
 
void CLASS parse_foveon()
{
char *buf, *bp, *np;
int off1, off2, len, i;
 
order = 0x4949; /* Little-endian */
fseek (ifp, -4, SEEK_END);
off2 = fget4(ifp);
fseek (ifp, off2, SEEK_SET);
while (fget4(ifp) != 0x464d4143) /* Search for "CAMF" */
if (feof(ifp)) return;
off1 = fget4(ifp);
fseek (ifp, off1+8, SEEK_SET);
off1 += (fget4(ifp)+3) * 8;
len = (off2 - off1)/2;
fseek (ifp, off1, SEEK_SET);
buf = malloc (len);
merror (buf, "parse_foveon()");
for (i=0; i < len; i++) /* Convert Unicode to ASCII */
buf[i] = fget2(ifp);
for (bp=buf; bp < buf+len; bp=np) {
np = bp + strlen(bp) + 1;
if (!strcmp(bp,"CAMMANUF"))
strcpy (make, np);
if (!strcmp(bp,"CAMMODEL"))
strcpy (model, np);
if (!strcmp(bp,"TIME"))
timestamp = atoi(np);
}
fseek (ifp, 248, SEEK_SET);
raw_width = fget4(ifp);
raw_height = fget4(ifp);
free(buf);
}
 
void CLASS foveon_coeff()
{
static const float foveon[3][3] = {
{ 2.0343955, -0.727533, -0.3067457 },
{ -0.2287194, 1.231793, -0.0028293 },
{ -0.0086152, -0.153336, 1.1617814 }
};
int i, j;
 
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
coeff[i][j] = foveon[i][j] * pre_mul[i];
use_coeff = 1;
}
 
/*
The grass is always greener in my PowerShot G2 when this
function is called. Use at your own risk!
*/
void CLASS canon_rgb_coeff (float juice)
{
static const float my_coeff[3][3] =
{ { 1.116187, -0.107427, -0.008760 },
{ -1.551374, 4.157144, -1.605770 },
{ 0.090939, -0.399727, 1.308788 } };
int i, j;
 
if (juice != 0) {
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
coeff[i][j] = my_coeff[i][j] * juice + (i==j) * (1-juice);
use_coeff = 1;
}
}
 
void CLASS nikon_e950_coeff()
{
int r, g;
static const float my_coeff[3][4] =
{ { -1.936280, 1.800443, -1.448486, 2.584324 },
{ 1.405365, -0.524955, -0.289090, 0.408680 },
{ -1.204965, 1.082304, 2.941367, -1.818705 } };
 
for (r=0; r < 3; r++)
for (g=0; g < 4; g++)
coeff[r][g] = my_coeff[r][g];
use_coeff = 1;
}
 
/*
Given a matrix that converts RGB to GMCY, create a matrix to do
the opposite. Only square matrices can be inverted, so I create
four 3x3 matrices by omitting a different GMCY color in each one.
The final coeff[][] matrix is the sum of these four.
*/
void CLASS gmcy_coeff()
{
static const float gmcy[4][3] = {
/* red green blue */
{ 0.11, 0.86, 0.08 }, /* green */
{ 0.50, 0.29, 0.51 }, /* magenta */
{ 0.11, 0.92, 0.75 }, /* cyan */
{ 0.81, 0.98, 0.08 } /* yellow */
};
double invert[3][6], num;
int ignore, i, j, k, r, g;
 
memset (coeff, 0, sizeof coeff);
for (ignore=0; ignore < 4; ignore++) {
for (j=0; j < 3; j++) {
g = (j < ignore) ? j : j+1;
for (r=0; r < 3; r++) {
invert[j][r] = gmcy[g][r]; /* 3x3 matrix to invert */
invert[j][r+3] = (r == j); /* Identity matrix */
}
}
for (j=0; j < 3; j++) {
num = invert[j][j]; /* Normalize this row */
for (i=0; i < 6; i++)
invert[j][i] /= num;
for (k=0; k < 3; k++) { /* Subtract it from the other rows */
if (k==j) continue;
num = invert[k][j];
for (i=0; i < 6; i++)
invert[k][i] -= invert[j][i] * num;
}
}
for (j=0; j < 3; j++) { /* Add the result to coeff[][] */
g = (j < ignore) ? j : j+1;
for (r=0; r < 3; r++)
coeff[r][g] += invert[r][j+3];
}
}
for (r=0; r < 3; r++) { /* Normalize such that: */
for (num=g=0; g < 4; g++) /* (1,1,1,1) x coeff = (1,1,1) */
num += coeff[r][g];
for (g=0; g < 4; g++)
coeff[r][g] /= num;
}
use_coeff = 1;
}
 
/*
Identify which camera created this file, and set global variables
accordingly. Return nonzero if the file cannot be decoded.
*/
int CLASS identify()
{
char head[32], *c;
unsigned hlen, fsize, i;
static const struct {
int fsize;
char make[12], model[16];
} table[] = {
{ 62464, "Kodak", "DC20" },
{ 124928, "Kodak", "DC20" },
{ 2465792, "NIKON", "E950" },
{ 2940928, "NIKON", "E2100" },
{ 4771840, "NIKON", "E990" },
{ 5865472, "NIKON", "E4500" },
{ 5869568, "NIKON", "E4300" },
{ 787456, "Creative", "PC-CAM 600" },
{ 1976352, "Casio", "QV-2000UX" },
{ 3217760, "Casio", "QV-3*00EX" },
{ 6218368, "Casio", "QV-5700" },
{ 7684000, "Casio", "QV-4000" },
{ 9313536, "Casio", "EX-P600" },
{ 4841984, "Pentax", "Optio S" },
{ 6114240, "Pentax", "Optio S4" },
{ 12582980, "Sinar", "" } };
static const char *corp[] =
{ "Canon", "NIKON", "Kodak", "PENTAX", "MINOLTA", "Minolta", "Konica" };
 
/* What format is this file? Set make[] if we recognize it. */
 
raw_height = raw_width = flip = 0;
make[0] = model[0] = model2[0] = 0;
memset (white, 0, sizeof white);
camera_red = camera_blue = timestamp = 0;
data_offset = curve_offset = tiff_data_compression = 0;
zero_after_ff = 0;
 
order = fget2(ifp);
hlen = fget4(ifp);
fseek (ifp, 0, SEEK_SET);
fread (head, 1, 32, ifp);
fseek (ifp, 0, SEEK_END);
fsize = ftell(ifp);
if ((c = memmem (head, 32, "MMMMRawT", 8))) {
strcpy (make, "Phase One");
data_offset = c - head;
fseek (ifp, data_offset + 8, SEEK_SET);
fseek (ifp, fget4(ifp) + 136, SEEK_CUR);
raw_width = fget4(ifp);
fseek (ifp, 12, SEEK_CUR);
raw_height = fget4(ifp);
} else if (order == 0x4949 || order == 0x4d4d) {
if (!memcmp (head+6, "HEAPCCDR", 8)) {
data_offset = hlen;
parse_ciff (hlen, fsize - hlen);
} else {
parse_tiff(0);
if (!strncmp(make,"NIKON",5) && raw_width == 0)
make[0] = 0;
}
} else if (!memcmp (head, "\0MRM", 4)) {
parse_tiff(48);
fseek (ifp, 4, SEEK_SET);
data_offset = fget4(ifp) + 8;
fseek (ifp, 24, SEEK_SET);
raw_height = fget2(ifp);
raw_width = fget2(ifp);
fseek (ifp, 12, SEEK_SET); /* PRD */
fseek (ifp, fget4(ifp) + 4, SEEK_CUR); /* TTW */
fseek (ifp, fget4(ifp) + 12, SEEK_CUR); /* WBG */
camera_red = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue = fget2(ifp);
camera_blue = fget2(ifp) / camera_blue;
} else if (!memcmp (head, "\xff\xd8\xff\xe1", 4) &&
!memcmp (head+6, "Exif", 4)) {
fseek (ifp, 4, SEEK_SET);
fseek (ifp, 4 + fget2(ifp), SEEK_SET);
if (fgetc(ifp) != 0xff)
parse_tiff(12);
} else if (!memcmp (head, "BM", 2)) {
data_offset = 0x1000;
order = 0x4949;
fseek (ifp, 38, SEEK_SET);
if (fget4(ifp) == 2834 && fget4(ifp) == 2834) {
strcpy (model, "BMQ");
goto nucore;
}
} else if (!memcmp (head, "BR", 2)) {
strcpy (model, "RAW");
nucore:
strcpy (make, "Nucore");
order = 0x4949;
fseek (ifp, 10, SEEK_SET);
data_offset += fget4(ifp);
fget4(ifp);
raw_width = fget4(ifp);
raw_height = fget4(ifp);
if (model[0] == 'B' && raw_width == 2597) {
raw_width++;
data_offset -= 0x1000;
}
} else if (!memcmp (head+25, "ARECOYK", 7)) {
strcpy (make, "CONTAX");
strcpy (model, "N DIGITAL");
} else if (!memcmp (head, "FUJIFILM", 8)) {
fseek (ifp, 84, SEEK_SET);
parse_tiff (fget4(ifp)+12);
order = 0x4d4d;
fseek (ifp, 100, SEEK_SET);
data_offset = fget4(ifp);
} else if (!memcmp (head, "DSC-Image", 9))
parse_rollei();
else if (!memcmp (head, "FOVb", 4))
parse_foveon();
else
for (i=0; i < sizeof table / sizeof *table; i++)
if (fsize == table[i].fsize) {
strcpy (make, table[i].make );
strcpy (model, table[i].model);
}
 
for (i=0; i < sizeof corp / sizeof *corp; i++)
if (strstr (make, corp[i])) /* Simplify company names */
strcpy (make, corp[i]);
if (!strncmp (make, "KODAK", 5))
make[16] = model[16] = 0;
c = make + strlen(make); /* Remove trailing spaces */
while (*--c == ' ') *c = 0;
c = model + strlen(model);
while (*--c == ' ') *c = 0;
i = strlen(make); /* Remove make from model */
if (!strncmp (model, make, i++))
memmove (model, model+i, 64-i);
 
 
if (make[0] == 0) {
// Cinelerra
// fprintf (stderr, "%s: unsupported file format.\n", ifname);
return 1;
}
 
/* File format is OK. Do we support this camera? */
/* Start with some useful defaults: */
 
load_raw = NULL;
height = raw_height;
width = raw_width;
top_margin = left_margin = 0;
colors = 3;
filters = 0x94949494;
black = is_cmy = is_foveon = use_coeff = 0;
pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = 1;
xmag = ymag = 1;
rgb_max = 0x4000;
 
/* We'll try to decode anything from Canon or Nikon. */
 
if ((is_canon = !strcmp(make,"Canon"))) {
canon_rgb_coeff (juice);
if (memcmp (head+6, "HEAPCCDR", 8)) {
filters = 0x61616161;
load_raw = lossless_jpeg_load_raw;
}
else
if (raw_width)
{
load_raw = canon_compressed_load_raw;
}
}
if (!strcmp(make,"NIKON"))
load_raw = nikon_is_compressed() ?
nikon_compressed_load_raw : nikon_load_raw;
 
if (!strcmp(model,"PowerShot 600")) {
height = 613;
width = 854;
colors = 4;
filters = 0xe1e4e1e4;
load_raw = canon_600_load_raw;
pre_mul[0] = 1.137;
pre_mul[1] = 1.257;
} else if (!strcmp(model,"PowerShot A5") ||
!strcmp(model,"PowerShot A5 Zoom")) {
height = 776;
width = 960;
raw_width = 992;
colors = 4;
filters = 0x1e4e1e4e;
load_raw = canon_a5_load_raw;
pre_mul[0] = 1.5842;
pre_mul[1] = 1.2966;
pre_mul[2] = 1.0419;
} else if (!strcmp(model,"PowerShot A50")) {
height = 968;
width = 1290;
raw_width = 1320;
colors = 4;
filters = 0x1b4e4b1e;
load_raw = canon_a5_load_raw;
pre_mul[0] = 1.750;
pre_mul[1] = 1.381;
pre_mul[3] = 1.182;
} else if (!strcmp(model,"PowerShot Pro70")) {
height = 1024;
width = 1552;
colors = 4;
filters = 0x1e4b4e1b;
load_raw = canon_a5_load_raw;
pre_mul[0] = 1.389;
pre_mul[1] = 1.343;
pre_mul[3] = 1.034;
} else if (!strcmp(model,"PowerShot Pro90 IS")) {
width = 1896;
colors = 4;
filters = 0xb4b4b4b4;
pre_mul[0] = 1.496;
pre_mul[1] = 1.509;
pre_mul[3] = 1.009;
} else if (is_canon && raw_width == 2144) {
height = 1550;
width = 2088;
top_margin = 8;
left_margin = 4;
if (!strcmp(model,"PowerShot G1")) {
colors = 4;
filters = 0xb4b4b4b4;
pre_mul[0] = 1.446;
pre_mul[1] = 1.405;
pre_mul[2] = 1.016;
} else {
pre_mul[0] = 1.785;
pre_mul[2] = 1.266;
}
} else if (is_canon && raw_width == 2224) {
height = 1448;
width = 2176;
top_margin = 6;
left_margin = 48;
pre_mul[0] = 1.592;
pre_mul[2] = 1.261;
} else if (is_canon && raw_width == 2376) {
height = 1720;
width = 2312;
top_margin = 6;
left_margin = 12;
#ifdef CUSTOM
if (write_fun == write_ppm) /* Pro users may not want my matrix */
canon_rgb_coeff (0.1);
#endif
if (!strcmp(model,"PowerShot G2") ||
!strcmp(model,"PowerShot S40")) {
pre_mul[0] = 1.965;
pre_mul[2] = 1.208;
} else { /* G3 and S45 */
pre_mul[0] = 1.855;
pre_mul[2] = 1.339;
}
} else if (is_canon && raw_width == 2672) {
height = 1960;
width = 2616;
top_margin = 6;
left_margin = 12;
pre_mul[0] = 1.895;
pre_mul[2] = 1.403;
} else if (is_canon && raw_width == 3152) {
height = 2056;
width = 3088;
top_margin = 12;
left_margin = 64;
pre_mul[0] = 2.242;
pre_mul[2] = 1.245;
if (!strcmp(model,"EOS Kiss Digital")) {
pre_mul[0] = 1.882;
pre_mul[2] = 1.094;
}
rgb_max = 16000;
} else if (is_canon && raw_width == 3160) {
height = 2328;
width = 3112;
top_margin = 12;
left_margin = 44;
pre_mul[0] = 1.85;
pre_mul[2] = 1.53;
} else if (is_canon && raw_width == 3344) {
height = 2472;
width = 3288;
top_margin = 6;
left_margin = 4;
pre_mul[0] = 1.621;
pre_mul[2] = 1.528;
} else if (!strcmp(model,"EOS-1D")) {
height = 1662;
width = 2496;
data_offset = 288912;
pre_mul[0] = 1.976;
pre_mul[2] = 1.282;
} else if (!strcmp(model,"EOS-1DS")) {
height = 2718;
width = 4082;
data_offset = 289168;
pre_mul[0] = 1.66;
pre_mul[2] = 1.13;
rgb_max = 14464;
} else if (!strcmp(model,"EOS-1D Mark II") ||
!strcmp(model,"EOS 20D")) {
raw_height = 2360;
raw_width = 3596;
top_margin = 12;
left_margin = 74;
height = raw_height - top_margin;
width = raw_width - left_margin;
filters = 0x94949494;
pre_mul[0] = 1.95;
pre_mul[2] = 1.36;
} else if (!strcmp(model,"EOS-1Ds Mark II")) {
raw_height = 3349;
raw_width = 5108;
top_margin = 13;
left_margin = 98;
height = raw_height - top_margin;
width = raw_width - left_margin;
filters = 0x94949494;
pre_mul[0] = 1.609;
pre_mul[2] = 1.848;
rgb_max = 0x3a00;
} else if (!strcmp(model,"EOS D2000C")) {
black = 800;
pre_mul[2] = 1.25;
} else if (!strcmp(model,"D1")) {
filters = 0x16161616;
pre_mul[0] = 0.838;
pre_mul[2] = 1.095;
} else if (!strcmp(model,"D1H")) {
filters = 0x16161616;
pre_mul[0] = 2.301;
pre_mul[2] = 1.129;
} else if (!strcmp(model,"D1X")) {
width = 4024;
filters = 0x16161616;
ymag = 2;
pre_mul[0] = 1.910;
pre_mul[2] = 1.220;
} else if (!strcmp(model,"D100")) {
if (tiff_data_compression == 34713 && load_raw == nikon_load_raw)
raw_width = (width += 3) + 3;
filters = 0x61616161;
pre_mul[0] = 2.374;
pre_mul[2] = 1.677;
rgb_max = 15632;
} else if (!strcmp(model,"D2H")) {
width = 2482;
left_margin = 6;
filters = 0x49494949;
pre_mul[0] = 2.8;
pre_mul[2] = 1.2;
} else if (!strcmp(model,"D70")) {
filters = 0x16161616;
pre_mul[0] = 2.043;
pre_mul[2] = 1.625;
} else if (!strcmp(model,"E950")) {
height = 1203;
width = 1616;
filters = 0x4b4b4b4b;
colors = 4;
load_raw = nikon_e950_load_raw;
nikon_e950_coeff();
pre_mul[0] = 1.18193;
pre_mul[2] = 1.16452;
pre_mul[3] = 1.17250;
} else if (!strcmp(model,"E990")) {
height = 1540;
width = 2064;
colors = 4;
if (nikon_e990()) {
filters = 0xb4b4b4b4;
nikon_e950_coeff();
pre_mul[0] = 1.196;
pre_mul[1] = 1.246;
pre_mul[2] = 1.018;
} else {
strcpy (model, "E995");
filters = 0xe1e1e1e1;
pre_mul[0] = 1.253;
pre_mul[1] = 1.178;
pre_mul[3] = 1.035;
}
} else if (!strcmp(model,"E2100")) {
width = 1616;
if (nikon_e2100()) {
height = 1206;
load_raw = nikon_e2100_load_raw;
pre_mul[0] = 1.945;
pre_mul[2] = 1.040;
} else {
strcpy (model, "E2500");
height = 1204;
filters = 0x4b4b4b4b;
goto coolpix;
}
} else if (!strcmp(model,"E4300")) {
height = 1710;
width = 2288;
filters = 0x16161616;
if (minolta_z2()) {
strcpy (make, "Minolta");
strcpy (model, "DiMAGE Z2");
load_raw = nikon_e2100_load_raw;
}
} else if (!strcmp(model,"E4500")) {
height = 1708;
width = 2288;
filters = 0xb4b4b4b4;
goto coolpix;
} else if (!strcmp(model,"E5000") || !strcmp(model,"E5700")) {
filters = 0xb4b4b4b4;
coolpix:
colors = 4;
pre_mul[0] = 1.300;
pre_mul[1] = 1.300;
pre_mul[3] = 1.148;
} else if (!strcmp(model,"E5400")) {
filters = 0x16161616;
pre_mul[0] = 1.700;
pre_mul[2] = 1.344;
} else if (!strcmp(model,"E8700") ||
!strcmp(model,"E8800")) {
filters = 0x16161616;
pre_mul[0] = 2.131;
pre_mul[2] = 1.300;
} else if (!strcmp(model,"FinePixS2Pro")) {
height = 3584;
width = 3583;
filters = 0x61616161;
load_raw = fuji_s2_load_raw;
black = 512;
pre_mul[0] = 1.424;
pre_mul[2] = 1.718;
} else if (!strcmp(model,"FinePix S5000")) {
height = 2499;
width = 2500;
filters = 0x49494949;
load_raw = fuji_s5000_load_raw;
pre_mul[0] = 1.639;
pre_mul[2] = 1.438;
rgb_max = 0xf800;
} else if (!strcmp(model,"FinePix S7000")) {
pre_mul[0] = 1.62;
pre_mul[2] = 1.38;
goto fuji_s7000;
} else if (!strcmp(model,"FinePix E550")) {
pre_mul[0] = 1.45;
pre_mul[2] = 1.25;
fuji_s7000:
height = 3587;
width = 3588;
filters = 0x49494949;
load_raw = fuji_s7000_load_raw;
rgb_max = 0xf800;
} else if (!strcmp(model,"FinePix F700") ||
!strcmp(model,"FinePix S20Pro")) {
height = 2523;
width = 2524;
filters = 0x49494949;
load_raw = fuji_f700_load_raw;
pre_mul[0] = 1.639;
pre_mul[2] = 1.438;
rgb_max = 0x3e00;
} else if (!strcmp(model,"Digital Camera KD-400Z")) {
height = 1712;
width = 2312;
raw_width = 2336;
data_offset = 4034;
fseek (ifp, 2032, SEEK_SET);
goto konica_400z;
} else if (!strcmp(model,"Digital Camera KD-510Z")) {
data_offset = 4032;
fseek (ifp, 2032, SEEK_SET);
goto konica_510z;
} else if (!strcasecmp(make,"MINOLTA")) {
load_raw = be_low_12_load_raw;
rgb_max = 15860;
if (!strncmp(model,"DiMAGE A",8)) {
load_raw = packed_12_load_raw;
rgb_max = model[8] == '1' ? 15916:16380;
} else if (!strncmp(model,"DiMAGE G",8)) {
if (model[8] == '4') {
data_offset = 5056;
fseek (ifp, 2078, SEEK_SET);
height = 1716;
width = 2304;
} else if (model[8] == '5') {
data_offset = 4016;
fseek (ifp, 1936, SEEK_SET);
konica_510z:
height = 1956;
width = 2607;
raw_width = 2624;
} else if (model[8] == '6') {
data_offset = 4032;
fseek (ifp, 2030, SEEK_SET);
height = 2136;
width = 2848;
}
filters = 0x61616161;
konica_400z:
load_raw = be_low_10_load_raw;
rgb_max = 15856;
order = 0x4d4d;
camera_red = fget2(ifp);
camera_blue = fget2(ifp);
camera_red /= fget2(ifp);
camera_blue /= fget2(ifp);
}
pre_mul[0] = 1.42;
pre_mul[2] = 1.25;
} else if (!strcmp(model,"*ist D")) {
height = 2024;
width = 3040;
data_offset = 0x10000;
load_raw = be_low_12_load_raw;
pre_mul[0] = 1.76;
pre_mul[1] = 1.07;
} else if (!strcmp(model,"Optio S")) {
height = 1544;
width = 2068;
raw_width = 3136;
load_raw = packed_12_load_raw;
pre_mul[0] = 1.506;
pre_mul[2] = 1.152;
} else if (!strcmp(model,"Optio S4")) {
height = 1737;
width = 2324;
raw_width = 3520;
load_raw = packed_12_load_raw;
pre_mul[0] = 1.308;
pre_mul[2] = 1.275;
} else if (!strcmp(make,"Phase One")) {
switch (raw_height) {
case 2060:
strcpy (model, "LightPhase");
height = 2048;
width = 3080;
top_margin = 5;
left_margin = 22;
pre_mul[0] = 1.331;
pre_mul[2] = 1.154;
break;
case 2682:
strcpy (model, "H10");
height = 2672;
width = 4012;
top_margin = 5;
left_margin = 26;
break;
case 4128:
strcpy (model, "H20");
height = 4098;
width = 4098;
top_margin = 20;
left_margin = 26;
pre_mul[0] = 1.963;
pre_mul[2] = 1.430;
break;
case 5488:
strcpy (model, "H25");
height = 5458;
width = 4098;
top_margin = 20;
left_margin = 26;
pre_mul[0] = 2.80;
pre_mul[2] = 1.20;
}
filters = top_margin & 1 ? 0x94949494 : 0x49494949;
load_raw = phase_one_load_raw;
rgb_max = 0xffff;
} else if (!strcmp(model,"Ixpress")) {
height = 4084;
width = 4080;
filters = 0x49494949;
load_raw = ixpress_load_raw;
pre_mul[0] = 1.963;
pre_mul[2] = 1.430;
rgb_max = 0xffff;
} else if (!strcmp(make,"Sinar") && !memcmp(head,"8BPS",4)) {
fseek (ifp, 14, SEEK_SET);
height = fget4(ifp);
width = fget4(ifp);
filters = 0x61616161;
data_offset = 68;
load_raw = be_16_load_raw;
rgb_max = 0xffff;
} else if (!strcmp(make,"Leaf")) {
if (height > width)
filters = 0x16161616;
load_raw = be_16_load_raw;
pre_mul[0] = 1.1629;
pre_mul[2] = 1.3556;
rgb_max = 0xffff;
} else if (!strcmp(model,"DIGILUX 2") || !strcmp(model,"DMC-LC1")) {
height = 1928;
width = 2568;
data_offset = 1024;
load_raw = le_high_12_load_raw;
pre_mul[0] = 1.883;
pre_mul[2] = 1.367;
} else if (!strcmp(model,"E-1")) {
filters = 0x61616161;
load_raw = le_high_12_load_raw;
pre_mul[0] = 1.57;
pre_mul[2] = 1.48;
} else if (!strcmp(model,"E-10")) {
load_raw = be_high_12_load_raw;
pre_mul[0] = 1.43;
pre_mul[2] = 1.77;
} else if (!strncmp(model,"E-20",4)) {
load_raw = be_high_12_load_raw;
black = 640;
pre_mul[0] = 1.43;
pre_mul[2] = 1.77;
} else if (!strcmp(model,"C5050Z")) {
filters = 0x16161616;
load_raw = olympus_cseries_load_raw;
pre_mul[0] = 1.533;
pre_mul[2] = 1.880;
} else if (!strcmp(model,"C5060WZ")) {
load_raw = olympus_cseries_load_raw;
pre_mul[0] = 2.285;
pre_mul[2] = 1.023;
} else if (!strcmp(model,"C8080WZ")) {
filters = 0x16161616;
load_raw = olympus_cseries_load_raw;
pre_mul[0] = 2.335;
pre_mul[2] = 1.323;
} else if (!strcmp(model,"N DIGITAL")) {
height = 2047;
width = 3072;
filters = 0x61616161;
data_offset = 0x1a00;
load_raw = packed_12_load_raw;
pre_mul[0] = 1.366;
pre_mul[2] = 1.251;
} else if (!strcmp(model,"DSC-F828")) {
height = 2460;
width = 3288;
raw_width = 3360;
left_margin = 5;
load_raw = sony_load_raw;
sony_rgbe_coeff();
filters = 0xb4b4b4b4;
colors = 4;
pre_mul[0] = 1.512;
pre_mul[1] = 1.020;
pre_mul[2] = 1.405;
} else if (!strcasecmp(make,"KODAK")) {
filters = 0x61616161;
if (!strcmp(model,"NC2000F")) {
width -= 4;
left_margin = 1;
curve_length = 176;
pre_mul[0] = 1.509;
pre_mul[2] = 2.686;
} else if (!strcmp(model,"EOSDCS3B")) {
width -= 4;
left_margin = 2;
pre_mul[0] = 1.629;
pre_mul[2] = 2.767;
} else if (!strcmp(model,"EOSDCS1")) {
width -= 4;
left_margin = 2;
pre_mul[0] = 1.386;
pre_mul[2] = 2.405;
} else if (!strcmp(model,"DCS315C")) {
black = 32;
pre_mul[1] = 1.068;
pre_mul[2] = 1.036;
} else if (!strcmp(model,"DCS330C")) {
black = 32;
pre_mul[1] = 1.012;
pre_mul[2] = 1.804;
} else if (!strcmp(model,"DCS420")) {
width -= 4;
left_margin = 2;
pre_mul[0] = 1.327;
pre_mul[2] = 2.074;
} else if (!strcmp(model,"DCS460")) {
width -= 4;
left_margin = 2;
pre_mul[0] = 1.724;
pre_mul[2] = 2.411;
} else if (!strcmp(model,"DCS460A")) {
width -= 4;
left_margin = 2;
colors = 1;
filters = 0;
} else if (!strcmp(model,"DCS520C")) {
black = 720;
pre_mul[0] = 1.006;
pre_mul[2] = 1.858;
} else if (!strcmp(model,"DCS560C")) {
black = 750;
pre_mul[1] = 1.053;
pre_mul[2] = 1.703;
} else if (!strcmp(model,"DCS620C")) {
black = 720;
pre_mul[1] = 1.002;
pre_mul[2] = 1.818;
} else if (!strcmp(model,"DCS620X")) {
black = 740;
pre_mul[0] = 1.486;
pre_mul[2] = 1.280;
is_cmy = 1;
} else if (!strcmp(model,"DCS660C")) {
black = 855;
pre_mul[0] = 1.156;
pre_mul[2] = 1.626;
} else if (!strcmp(model,"DCS660M")) {
black = 855;
colors = 1;
filters = 0;
} else if (!strcmp(model,"DCS720X")) {
pre_mul[0] = 1.35;
pre_mul[2] = 1.18;
is_cmy = 1;
} else if (!strcmp(model,"DCS760C")) {
pre_mul[0] = 1.06;
pre_mul[2] = 1.72;
} else if (!strcmp(model,"DCS760M")) {
colors = 1;
filters = 0;
} else if (!strcmp(model,"ProBack")) {
pre_mul[0] = 1.06;
pre_mul[2] = 1.385;
} else if (!strncmp(model2,"PB645C",6)) {
pre_mul[0] = 1.0497;
pre_mul[2] = 1.3306;
} else if (!strncmp(model2,"PB645H",6)) {
pre_mul[0] = 1.2010;
pre_mul[2] = 1.5061;
} else if (!strncmp(model2,"PB645M",6)) {
pre_mul[0] = 1.01755;
pre_mul[2] = 1.5424;
} else if (!strcasecmp(model,"DCS Pro 14n")) {
pre_mul[1] = 1.0323;
pre_mul[2] = 1.258;
} else if (!strcasecmp(model,"DCS Pro 14nx")) {
pre_mul[0] = 1.336;
pre_mul[2] = 1.3155;
} else if (!strcasecmp(model,"DCS Pro SLR/c")) {
pre_mul[0] = 1.425;
pre_mul[2] = 1.293;
} else if (!strcasecmp(model,"DCS Pro SLR/n")) {
pre_mul[0] = 1.324;
pre_mul[2] = 1.483;
}
switch (tiff_data_compression) {
case 0: /* No compression */
case 1:
load_raw = kodak_easy_load_raw;
break;
case 7: /* Lossless JPEG */
load_raw = lossless_jpeg_load_raw;
case 32867:
break;
case 65000: /* Kodak DCR compression */
if (kodak_data_compression == 32803)
load_raw = kodak_compressed_load_raw;
else {
load_raw = kodak_yuv_load_raw;
height = (height+1) & -2;
width = (width +1) & -2;
filters = 0;
}
break;
default:
fprintf (stderr, "%s: %s %s uses unsupported compression method %d.\n",
ifname, make, model, tiff_data_compression);
return 1;
}
if (!strcmp(model,"DC20")) {
height = 242;
if (fsize < 100000) {
width = 249;
raw_width = 256;
} else {
width = 501;
raw_width = 512;
}
data_offset = raw_width + 1;
colors = 4;
filters = 0x8d8d8d8d;
kodak_dc20_coeff (0.5);
pre_mul[1] = 1.179;
pre_mul[2] = 1.209;
pre_mul[3] = 1.036;
load_raw = kodak_easy_load_raw;
} else if (strstr(model,"DC25")) {
strcpy (model, "DC25");
height = 242;
if (fsize < 100000) {
width = 249;
raw_width = 256;
data_offset = 15681;
} else {
width = 501;
raw_width = 512;
data_offset = 15937;
}
colors = 4;
filters = 0xb4b4b4b4;
load_raw = kodak_easy_load_raw;
} else if (!strcmp(model,"Digital Camera 40")) {
strcpy (model, "DC40");
height = 512;
width = 768;
data_offset = 1152;
load_raw = kodak_radc_load_raw;
} else if (strstr(model,"DC50")) {
strcpy (model, "DC50");
height = 512;
width = 768;
data_offset = 19712;
load_raw = kodak_radc_load_raw;
} else if (strstr(model,"DC120")) {
strcpy (model, "DC120");
height = 976;
width = 848;
if (tiff_data_compression == 7)
load_raw = kodak_jpeg_load_raw;
else
load_raw = kodak_dc120_load_raw;
}
} else if (!strcmp(make,"Rollei")) {
switch (raw_width) {
case 1316:
height = 1030;
width = 1300;
top_margin = 1;
left_margin = 6;
break;
case 2568:
height = 1960;
width = 2560;
top_margin = 2;
left_margin = 8;
}
filters = 0x16161616;
load_raw = rollei_load_raw;
pre_mul[0] = 1.8;
pre_mul[2] = 1.3;
} else if (!strcmp(make,"SIGMA")) {
switch (raw_height) {
case 763: height = 756; top_margin = 2; break;
case 1531: height = 1514; top_margin = 7; break;
}
switch (raw_width) {
case 1152: width = 1136; left_margin = 8; break;
case 2304: width = 2271; left_margin = 17; break;
}
if (height*2 < width) ymag = 2;
filters = 0;
load_raw = foveon_load_raw;
is_foveon = 1;
pre_mul[0] = 1.179;
pre_mul[2] = 0.713;
if (!strcmp(model,"SD10")) {
pre_mul[0] *= 2.07;
pre_mul[2] *= 2.30;
}
foveon_coeff();
rgb_max = 5600;
} else if (!strcmp(model,"PC-CAM 600")) {
height = 768;
data_offset = width = 1024;
filters = 0x49494949;
load_raw = eight_bit_load_raw;
pre_mul[0] = 1.14;
pre_mul[2] = 2.73;
} else if (!strcmp(model,"QV-2000UX")) {
height = 1208;
width = 1632;
data_offset = width * 2;
load_raw = eight_bit_load_raw;
} else if (!strcmp(model,"QV-3*00EX")) {
height = 1546;
width = 2070;
raw_width = 2080;
load_raw = eight_bit_load_raw;
} else if (!strcmp(model,"QV-4000")) {
height = 1700;
width = 2260;
load_raw = be_high_12_load_raw;
} else if (!strcmp(model,"QV-5700")) {
height = 1924;
width = 2576;
load_raw = casio_qv5700_load_raw;
} else if (!strcmp(model,"EX-P600")) {
height = 2142;
width = 2844;
raw_width = 4288;
load_raw = packed_12_load_raw;
pre_mul[0] = 2.356;
pre_mul[1] = 1.069;
} else if (!strcmp(make,"Nucore")) {
filters = 0x61616161;
load_raw = nucore_load_raw;
}
if (!load_raw || !height) {
fprintf (stderr, "%s: %s %s is not yet supported.\n",
ifname, make, model);
return 1;
}
#ifdef NO_JPEG
if (load_raw == kodak_jpeg_load_raw) {
fprintf (stderr, "%s: decoder was not linked with libjpeg.\n", ifname);
return 1;
}
#endif
if (!raw_height) raw_height = height;
if (!raw_width ) raw_width = width;
if (colors == 4 && !use_coeff)
gmcy_coeff();
if (use_coeff) /* Apply user-selected color balance */
for (i=0; i < colors; i++) {
coeff[0][i] *= red_scale;
coeff[2][i] *= blue_scale;
coeff[1][i] *= green_scale;
}
if (four_color_rgb && filters && colors == 3) {
for (i=0; i < 32; i+=4) {
if ((filters >> i & 15) == 9)
filters |= 2 << i;
if ((filters >> i & 15) == 6)
filters |= 8 << i;
}
colors++;
pre_mul[3] = pre_mul[1];
if (use_coeff)
for (i=0; i < 3; i++)
coeff[i][3] = coeff[i][1] /= 2;
}
fseek (ifp, data_offset, SEEK_SET);
 
 
// Cinelerra
if (flip & 4)
sprintf(dcraw_info, "%d %d", height, width);
else
sprintf(dcraw_info, "%d %d", width, height);
 
 
 
 
 
return 0;
}
 
/*
Convert the entire image to RGB colorspace and build a histogram.
*/
void CLASS convert_to_rgb()
{
int row, col, r, g, c=0;
ushort *img;
float rgb[3], mag;
 
if (document_mode)
colors = 1;
memset (histogram, 0, sizeof histogram);
for (row = trim; row < height-trim; row++)
for (col = trim; col < width-trim; col++) {
img = image[row*width+col];
if (document_mode)
c = FC(row,col);
if (colors == 4 && !use_coeff) /* Recombine the greens */
img[1] = (img[1] + img[3]) >> 1;
if (colors == 1) /* RGB from grayscale */
for (r=0; r < 3; r++)
rgb[r] = img[c];
else if (use_coeff) { /* RGB from GMCY or Foveon */
for (r=0; r < 3; r++)
for (rgb[r]=g=0; g < colors; g++)
rgb[r] += img[g] * coeff[r][g];
} else if (is_cmy) { /* RGB from CMY */
rgb[0] = img[0] + img[1] - img[2];
rgb[1] = img[1] + img[2] - img[0];
rgb[2] = img[2] + img[0] - img[1];
} else /* RGB from RGB (easy) */
goto norgb;
for (r=0; r < 3; r++) {
if (rgb[r] < 0)
rgb[r] = 0;
if (rgb[r] > rgb_max)
rgb[r] = rgb_max;
img[r] = rgb[r];
}
norgb:
// Cinelerra
// if (1 || write_fun == write_ppm) {
if (write_fun == write_ppm) {
for (mag=r=0; r < 3; r++)
mag += (unsigned) img[r]*img[r];
mag = sqrt(mag)/2;
if (mag > 0xffff)
mag = 0xffff;
img[3] = mag;
histogram[img[3] >> 3]++;
}
}
}
 
#define FMIN(a, b) ((a) < (b) ? (a) : (b))
 
static inline void calc_rgb_to_hsl(ushort *rgb, double *hue, double *sat,
double *lightness)
{
double red, green, blue;
double h, s, l;
double min, max;
double delta;
int maxval;
 
red = rgb[0] / (double) rgb_max;
green = rgb[1] / (double) rgb_max;
blue = rgb[2] / (double) rgb_max;
 
if (red > green) {
if (red > blue) {
max = red;
maxval = 0;
} else {
max = blue;
maxval = 2;
}
min = FMIN(green, blue);
} else {
if (green > blue) {
max = green;
maxval = 1;
} else {
max = blue;
maxval = 2;
}
min = FMIN(red, blue);
}
 
l = (max + min) / 2.0;
delta = max - min;
 
if (delta < .000001) { /* Suggested by Eugene Anikin <eugene@anikin.com> */
s = 0.0;
h = 0.0;
} else {
if (l <= .5)
s = delta / (max + min);
else
s = delta / (2 - max - min);
 
if (maxval == 0)
h = (green - blue) / delta;
else if (maxval == 1)
h = 2 + (blue - red) / delta;
else
h = 4 + (red - green) / delta;
 
if (h < 0.0)
h += 6.0;
else if (h > 6.0)
h -= 6.0;
}
 
*hue = h;
*sat = s;
*lightness = l;
}
 
static inline double hsl_value(double n1, double n2, double hue)
{
if (hue < 0)
hue += 6.0;
else if (hue > 6)
hue -= 6.0;
if (hue < 1.0)
return (n1 + (n2 - n1) * hue);
else if (hue < 3.0)
return (n2);
else if (hue < 4.0)
return (n1 + (n2 - n1) * (4.0 - hue));
else
return (n1);
}
 
static inline void calc_hsl_to_rgb(ushort *rgb, double h, double s, double l)
{
if (s < .0000001) {
if (l > 1)
l = 1;
else if (l < 0)
l = 0;
rgb[0] = l * (double) rgb_max;
rgb[1] = l * (double) rgb_max;
rgb[2] = l * (double) rgb_max;
} else {
double m1, m2;
double h1, h2;
h1 = h + 2;
h2 = h - 2;
 
if (l < .5)
m2 = l * (1 + s);
else
m2 = l + s - (l * s);
m1 = (l * 2) - m2;
rgb[0] = (double) rgb_max * hsl_value(m1, m2, h1);
rgb[1] = (double) rgb_max * hsl_value(m1, m2, h);
rgb[2] = (double) rgb_max * hsl_value(m1, m2, h2);
}
}
 
static inline double update_saturation(double sat, double adjust)
{
if (adjust < 1)
sat *= adjust;
else if (adjust > 1) {
double s1 = sat * adjust;
double s2 = 1.0 - ((1.0 - sat) * (1.0 / adjust));
sat = FMIN(s1, s2);
}
if (sat > 1)
sat = 1.0;
return sat;
}
 
static inline double update_contrast(double lum, double adjust)
{
double retval = lum;
if (lum >= .5)
retval = 1.0 - lum;
if (retval < .00001 && adjust < .0001)
retval = .5;
else
retval = .5 - ((.5 - .5 * pow(2 * retval, adjust)));
if (lum > .5)
retval = 1 - retval;
return retval;
}
 
static inline void do_hsl_adjust(ushort *rgb)
{
double h, s, l;
if (saturation != 1.0 || contrast != 1.0) {
calc_rgb_to_hsl(rgb, &h, &s, &l);
if (saturation != 1.0)
s = update_saturation(s, saturation);
if (contrast != 1.0)
l = update_contrast(l, contrast);
calc_hsl_to_rgb(rgb, h, s, l);
}
}
 
void CLASS flip_image()
{
unsigned *flag;
int size, base, dest, next, row, col, temp;
INT64 *img, hold;
 
img = (INT64 *) image;
size = height * width;
flag = calloc ((size+31) >> 5, sizeof *flag);
merror (flag, "flip_image()");
for (base = 0; base < size; base++) {
if (flag[base >> 5] & (1 << (base & 31)))
continue;
dest = base;
hold = img[base];
while (1) {
if (flip & 4) {
row = dest % height;
col = dest / height;
} else {
row = dest / width;
col = dest % width;
}
if (flip & 2)
row = height - 1 - row;
if (flip & 1)
col = width - 1 - col;
next = row * width + col;
if (next == base) break;
flag[next >> 5] |= 1 << (next & 31);
img[dest] = img[next];
dest = next;
}
img[dest] = hold;
}
free (flag);
if (flip & 4) {
temp = height;
height = width;
width = temp;
temp = ymag;
ymag = xmag;
xmag = temp;
}
}
 
/*
Write the image to a 24-bpp PPM file.
*/
void CLASS write_ppm (FILE *ofp)
{
int row, col, i, c, val, total;
float max, mul, scale[0x10000];
ushort *rgb;
uchar (*ppm)[3];
 
double white_fraction = 1.0 - white_point_fraction;
 
if (white_fraction > 1)
white_fraction = 1;
else if (white_fraction < 0)
white_fraction = 0;
 
if (strcmp(make, "FUJIFILM") == 0)
white_fraction /= 2;
/*
Set the white point to the 99th percentile
*/
i = width * height * white_fraction;
for (val=0x2000, total=0; --val; )
if ((total += histogram[val]) > i) break;
max = val << 4;
 
fprintf (ofp, "P6\n%d %d\n255\n",
xmag*(width-trim*2), ymag*(height-trim*2));
 
ppm = calloc (width-trim*2, 3*xmag);
merror (ppm, "write_ppm()");
mul = bright * 442 / max;
scale[0] = 0;
for (i=1; i < 0x10000; i++)
scale[i] = mul * pow (i*2/max, gamma_val-1);
 
for (row=trim; row < height-trim; row++) {
for (col=trim; col < width-trim; col++) {
rgb = image[row*width+col];
do_hsl_adjust(rgb);
for (c=0; c < 3; c++) {
val = rgb[c] * scale[rgb[3]];
if (val > 255) val=255;
for (i=0; i < xmag; i++)
ppm[xmag*(col-trim)+i][c] = val;
}
}
for (i=0; i < ymag; i++)
fwrite (ppm, width-trim*2, 3*xmag, ofp);
}
free(ppm);
}
 
/*
Write the image to a 48-bpp Photoshop file.
*/
void CLASS write_psd16 (FILE *ofp)
{
char head[] = {
'8','B','P','S', /* signature */
0,1,0,0,0,0,0,0, /* version and reserved */
0,3, /* number of channels */
0,0,0,0, /* height, big-endian */
0,0,0,0, /* width, big-endian */
0,16, /* 16-bit color */
0,3, /* mode (1=grey, 3=rgb) */
0,0,0,0, /* color mode data */
0,0,0,0, /* image resources */
0,0,0,0, /* layer/mask info */
0,0 /* no compression */
};
int hw[2], psize, row, col, c, val;
ushort *buffer, *pred, *rgb;
 
hw[0] = htonl(height-trim*2); /* write the header */
hw[1] = htonl(width-trim*2);
memcpy (head+14, hw, sizeof hw);
fwrite (head, 40, 1, ofp);
 
psize = (height-trim*2) * (width-trim*2);
buffer = calloc (6, psize);
merror (buffer, "write_psd()");
pred = buffer;
 
for (row = trim; row < height-trim; row++) {
for (col = trim; col < width-trim; col++) {
rgb = image[row*width+col];
do_hsl_adjust(rgb);
for (c=0; c < 3; c++) {
val = rgb[c] * bright;
if (val > 0xffff)
val = 0xffff;
pred[c*psize] = htons(val);
}
pred++;
}
}
fwrite(buffer, psize, 6, ofp);
free(buffer);
}
/*
Write the image to a 48-bpp PPM file.
*/
void CLASS write_ppm16 (FILE *ofp)
{
int row, col, c, val;
ushort *rgb, (*ppm)[3];
 
val = rgb_max * bright;
if (val < 256)
val = 256;
if (val > 0xffff)
val = 0xffff;
fprintf (ofp, "P6\n%d %d\n%d\n",
width-trim*2, height-trim*2, val);
 
ppm = calloc (width-trim*2, 6);
merror (ppm, "write_ppm16()");
 
for (row = trim; row < height-trim; row++) {
 
for (col = trim; col < width-trim; col++) {
 
 
rgb = image[row*width+col];
do_hsl_adjust(rgb);
for (c=0; c < 3; c++) {
val = rgb[c] * bright;
if (val > 0xffff)
val = 0xffff;
ppm[col-trim][c] = htons(val);
 
 
 
}
}
fwrite (ppm, width-trim*2, 6, ofp);
}
free(ppm);
}
 
 
 
 
 
 
 
// Cinelerra
void CLASS write_cinelerra (FILE *ofp)
{
int row, col, c, val;
float *output;
 
for (row = 0; row < height; row++)
{
output = dcraw_data[row];
for (col = 0; col < width; col++)
{
ushort *pixel = image[row * width + col];
for(c = 0; c < 3; c++)
*output++ = (float)pixel[c] / 0xffff;
if(dcraw_alpha) *output++ = 1.0;
}
}
 
 
 
 
 
 
#if 0
int row, col, i, c, total, j;
float val;
float max, mul, scale[0x10000];
ushort *rgb;
 
double white_fraction = 1.0 - white_point_fraction;
 
if (white_fraction > 1)
white_fraction = 1;
else if (white_fraction < 0)
white_fraction = 0;
 
if (strcmp(make, "FUJIFILM") == 0)
white_fraction /= 2;
 
/*
* Set the white point to the 99th percentile
*/
i = width * height * white_fraction;
for (j=0x2000, total=0; --j; )
{
if ((total += histogram[j]) > i) break;
}
max = j << 4;
 
mul = bright * 442 / max;
scale[0] = 0;
for (i=1; i < 0x10000; i++)
{
scale[i] = mul * pow (i*2/max, gamma_val-1);
}
 
for (row=trim; row < height-trim; row++)
{
float *output = dcraw_data[row];
for (col=trim; col < width-trim; col++)
{
rgb = image[row*width+col];
do_hsl_adjust(rgb);
for (c=0; c < 3; c++)
{
val = rgb[c] * scale[rgb[3]];
*output++ = val / 255;
}
if(dcraw_alpha) *output++ = 1.0;
}
}
 
#endif
 
 
}
 
 
 
 
 
 
 
 
void CLASS write_ppm_16_8(FILE *ofp)
{
int row, col, c, i;
float divisor;
ushort *rgb;
uchar (*ppm)[3];
unsigned val;
unsigned max = 0;
 
val = (double) rgb_max * bright;
if (val < 256)
val = 256;
if (val > 0xffff)
val = 0xffff;
divisor = 256 * ((double) val / 65536.0);
fprintf (ofp, "P6\n%d %d\n255\n",
width-trim*2, ymag*(height-trim*2));
 
ppm = calloc (width-trim*2, 3);
merror (ppm, "write_ppm16_8()");
 
for (row = trim; row < height-trim; row++) {
for (col = trim; col < width-trim; col++) {
rgb = image[row*width+col];
do_hsl_adjust(rgb);
for (c=0; c < 3; c++) {
if (rgb[c] > max)
max = rgb[c];
val = rgb[c] * bright / divisor;
if (val > 0xff)
val = 0xff;
ppm[col-trim][c] = val;
}
}
for (i=0; i < ymag; i++)
fwrite (ppm, width-trim*2, 3, ofp);
}
free(ppm);
}
 
// Cinelerra
int CLASS dcraw_main (int argc, char **argv)
{
int arg, status=0, user_flip=-1;
int identify_only=0, write_to_stdout=0, half_size=0;
char opt, *ofname, *cp;
const char *write_ext = ".ppm";
FILE *ofp = stdout;
 
 
if (argc == 1)
{
fprintf (stderr,
"\nRaw Photo Decoder \"dcraw\" v6.10"
"\nby Dave Coffin, dcoffin a cybercom o net"
"\n\nUsage: %s [options] file1 file2 ...\n"
"\nValid options:"
"\n-i Identify files but don't decode them"
"\n-c Write to standard output"
"\n-v Print verbose messages while decoding"
"\n-f Interpolate RGBG as four colors"
"\n-d Document Mode (no color, no interpolation)"
"\n-q Quick, low-quality color interpolation"
"\n-h Half-size color image (3x faster than -q)"
"\n-s Use secondary pixels (Fuji Super CCD SR only)"
"\n-g <num> Set gamma (0.6 by default, only for 24-bpp output)"
"\n-b <num> Set brightness (1.0 by default)"
"\n-a Use automatic white balance"
"\n-w Use camera white balance, if possible"
"\n-B <num> Use specified black level"
"\n-L Use floating black level"
"\n-n Use neutral (no correction) white balance"
"\n-u Use auto exposure compensation"
"\n-W Use center-weighted metering for exposure compensation"
"\n-T Use alternate scaling to improve contrast in highlights"
"\n-r <num> Set red multiplier (daylight = 1.0)"
"\n-l <num> Set blue multiplier (daylight = 1.0)"
"\n-t [0-7] Flip image (0 = none, 3 = 180, 5 = 90CCW, 6 = 90CW)"
"\n-e <num> Set green multiplier (daylight = 1.0)"
"\n-m <num> Set white point fraction (default 0.99)"
"\n-p <num> Set white point correction start (default none)"
"\n-P <num> Set relative white point correction start (default 0.75)"
"\n-x <num> Set exposure compensation in stops (default 0.00)"
"\n-S <num> Adjust saturation"
"\n-C <num> Adjust contrast"
"\n-k <num> Set interpolation threshold paramater k1\n\t for T = k1*Min + k2 * (Max - Min) (default = 1.5)"
"\n-K <num> Set interpolation threshold paramater k2\n\t for T = k1*Min + k2 * (Max - Min) (default = 0.5)"
"\n-j <num> Set parameter for color matrix"
"\n-1 Write 24-bpp PPM using 16 bit calculation"
"\n-2 Write 24-bpp PPM (default)"
"\n-3 Write 48-bpp PSD (Adobe Photoshop)"
"\n-4 Write 48-bpp PPM"
"\n\n", argv[0]);
return 1;
}
 
argv[argc] = "";
for (arg=1; argv[arg][0] == '-'; ) {
opt = argv[arg++][1];
if (strchr ("gbrlempPxSCB", opt) &&
(!isdigit(argv[arg][0]) && argv[arg][0] != '.' &&
(argv[arg][0] != '-' || (!isdigit(argv[arg][1]) &&
argv[arg][1] != '.')))) {
fprintf (stderr, "\"-%c\" requires a numeric argument.\n", opt);
return 1;
}
switch (opt)
{
case 'g': gamma_val = atof(argv[arg++]); break;
case 'b': bright = atof(argv[arg++]); break;
case 'r': red_scale = atof(argv[arg++]); break;
case 'l': blue_scale = atof(argv[arg++]); break;
case 't': user_flip = atoi(argv[arg++]); break;
case 'k': k1 = atof(argv[arg++]); break;
case 'K': k2 = atof(argv[arg++]); break;
case 'j': juice = atof(argv[arg++]); break;
 
case 'e': green_scale = atof(argv[arg++]); break;
case 'm': white_point_fraction = atof(argv[arg++]); break;
case 'P': pivot_value = atof(argv[arg++]); white_point_fraction = 1; break;
case 'p': pivot_value = atof(argv[arg++]); white_point_fraction = 1; use_pivot = 1; break;
case 'x': exposure_compensation = atof(argv[arg++]); break;
case 'S': saturation = atof(argv[arg++]); break;
case 'C': contrast = atof(argv[arg++]); break;
case 'n': use_neutral_wb = 1; break;
case 'u': autoexposure = 1; break;
case 'B': user_black = atoi(argv[arg++]); use_camera_black = 1; break;
case 'L': use_camera_black = 0; break;
case 'T': alternate_scale = 1; white_point_fraction = 1; break;
 
case 'W': center_weight = 1; break;
 
case 'i': identify_only = 1; break;
case 'c': write_to_stdout = 1; break;
case 'v': verbose = 1; break;
case 'h': half_size = 1; /* "-h" implies "-f" */
case 'f': four_color_rgb = 1; break;
case 'd': document_mode = 1; break;
case 'q': quick_interpolate = 1; break;
case 'a': use_auto_wb = 1; break;
case 'w': use_camera_wb = 1; break;
case 's': use_secondary = 1; break;
 
case '1': write_fun = write_ppm_16_8; write_ext = ".ppm"; break;
case '2': write_fun = write_ppm; write_ext = ".ppm"; break;
case '3': write_fun = write_psd16; write_ext = ".psd"; break;
case '4': write_fun = write_ppm16; write_ext = ".ppm"; break;
 
default:
fprintf (stderr, "Unknown option \"-%c\".\n", opt);
return 1;
}
}
 
 
// Cinelerra
write_fun = write_cinelerra;
 
if (arg == argc) {
fprintf (stderr, "No files to process.\n");
return 1;
}
if (write_to_stdout) {
 
 
 
// Cinelerra
if (0 /* isatty(1) */) {
fprintf (stderr, "Will not write an image to the terminal!\n");
return 1;
}
 
 
 
 
#if defined(WIN32) || defined(DJGPP)
if (setmode(1,O_BINARY) < 0) {
perror("setmode()");
return 1;
}
#endif
}
 
for ( ; arg < argc; arg++)
{
status = 1;
image = NULL;
if (setjmp (failure)) {
if (fileno(ifp) > 2) fclose(ifp);
if (fileno(ofp) > 2) fclose(ofp);
if (image) free(image);
status = 1;
continue;
}
ifname = argv[arg];
if (!(ifp = fopen (ifname, "rb"))) {
perror (ifname);
continue;
}
if ((status = identify())) {
fclose(ifp);
continue;
}
 
 
 
if (identify_only) {
// Cinelerra
// fprintf (stderr, "%s is a %s %s image.\n", ifname, make, model);
fclose(ifp);
continue;
}
shrink = half_size && filters;
iheight = (height + shrink) >> shrink;
iwidth = (width + shrink) >> shrink;
image = calloc (iheight * iwidth, sizeof *image);
merror (image, "main()");
if (verbose)
fprintf (stderr,
"Loading %s %s image from %s...\n", make, model, ifname);
(*load_raw)();
fclose(ifp);
bad_pixels();
height = iheight;
width = iwidth;
if (is_foveon) {
if (verbose)
fprintf (stderr, "Foveon interpolation...\n");
foveon_interpolate();
} else {
scale_colors();
}
 
 
if (shrink) filters = 0;
trim = 0;
if (filters && !document_mode) {
trim = 1;
if (verbose)
fprintf (stderr, "%s interpolation...\n",
quick_interpolate ? "Bilinear":"VNG");
// Cinelerra
// This blends the RGB pattern in the sensor but is too damn slow.
vng_interpolate();
}
if (verbose)
fprintf (stderr, "Converting to RGB colorspace...\n");
 
 
convert_to_rgb();
 
 
if (user_flip >= 0)
flip = user_flip;
if (flip) {
if (verbose)
fprintf (stderr, "Flipping image %c:%c:%c...\n",
flip & 1 ? 'H':'0', flip & 2 ? 'V':'0', flip & 4 ? 'T':'0');
flip_image();
}
 
 
ofname = malloc (strlen(ifname) + 16);
merror (ofname, "main()");
if (write_to_stdout)
strcpy (ofname, "standard output");
else {
strcpy (ofname, ifname);
if ((cp = strrchr (ofname, '.'))) *cp = 0;
strcat (ofname, write_ext);
ofp = fopen (ofname, "wb");
if (!ofp) {
status = 1;
perror(ofname);
goto cleanup;
}
}
 
 
if (verbose)
fprintf (stderr, "Writing data to %s...\n", ofname);
(*write_fun)(ofp);
if (ofp != stdout)
fclose(ofp);
cleanup:
free(ofname);
free(image);
}
return status;
}
/branches/automake-1_1_5/hvirtual/cinelerra/gwindow.inc
New file
0,0 → 1,10
#ifndef GWINDOW_INC
#define GWINDOW_INC
 
 
 
class GWindow;
 
 
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/gwindow.C
New file
0,0 → 1,28
#include "gwindow.h"
#include "gwindowgui.h"
#include "mwindow.h"
#include "mwindowgui.h"
 
GWindow::GWindow(MWindow *mwindow)
: Thread(1, 0, 0)
{
this->mwindow = mwindow;
}
 
void GWindow::run()
{
gui->run_window();
}
 
void GWindow::create_objects()
{
int w, h;
 
 
GWindowGUI::calculate_extents(mwindow->gui, &w, &h);
gui = new GWindowGUI(mwindow, w, h);
gui->create_objects();
}
 
 
 
/branches/automake-1_1_5/hvirtual/cinelerra/iec61883input.inc
New file
0,0 → 1,7
#ifndef IEC61883INPUT_INC
#define IEC61883INPUT_INC
 
 
class IEC61883Input;
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/gwindowgui.h
New file
0,0 → 1,54
#ifndef GWINDOWGUI_H
#define GWINDOWGUI_H
 
#include "automation.inc"
#include "guicast.h"
#include "mwindow.inc"
 
class GWindowToggle;
 
#define ASSETS 0
#define TITLES 1
#define TRANSITIONS 2
#define PLUGIN_AUTOS 3
#define OTHER_TOGGLES 4
 
class GWindowGUI : public BC_Window
{
public:
GWindowGUI(MWindow *mwindow, int w, int h);
static void calculate_extents(BC_WindowBase *gui, int *w, int *h);
void create_objects();
int translation_event();
int close_event();
int keypress_event();
void update_toggles(int use_lock);
void update_mwindow();
 
MWindow *mwindow;
GWindowToggle *other[OTHER_TOGGLES];
GWindowToggle *auto_toggle[AUTOMATION_TOTAL];
};
 
class GWindowToggle : public BC_CheckBox
{
public:
GWindowToggle(MWindow *mwindow,
GWindowGUI *gui,
int x,
int y,
int subscript,
int other,
char *text);
int handle_event();
void update();
 
static int* get_main_value(MWindow *mwindow, int subscript, int other);
 
MWindow *mwindow;
GWindowGUI *gui;
int subscript;
int other;
};
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/iec61883input.C
New file
0,0 → 1,330
#include "condition.h"
#include "iec61883input.h"
#include "mutex.h"
#include "vframe.h"
 
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
 
#define INPUT_SAMPLES 131072
#define BUFFER_TIMEOUT 500000
 
 
IEC61883Input::IEC61883Input()
: Thread(1, 1, 0)
{
frame = 0;
handle = 0;
fd = 0;
buffer = 0;
buffer_valid = 0;
input_buffer = 0;
done = 0;
total_buffers = 0;
current_inbuffer = 0;
current_outbuffer = 0;
buffer_size = 0;
audio_buffer = 0;
audio_samples = 0;
video_lock = 0;
audio_lock = 0;
buffer_lock = 0;
decoder = 0;
}
 
IEC61883Input::~IEC61883Input()
{
// Driver crashes if it isn't stopped before cancelling the thread.
// May still crash during the cancel though.
 
if(Thread::running())
{
done = 1;
Thread::join();
}
 
if(buffer)
{
for(int i = 0; i < total_buffers; i++)
delete [] buffer[i];
delete [] buffer;
delete [] buffer_valid;
}
 
if(input_buffer)
munmap(input_buffer, total_buffers * buffer_size);
 
if(audio_buffer)
{
delete [] audio_buffer;
}
 
if(decoder)
{
dv_delete(decoder);
}
 
if(video_lock) delete video_lock;
if(audio_lock) delete audio_lock;
if(buffer_lock) delete buffer_lock;
if(frame) iec61883_dv_fb_close(frame);
if(handle) raw1394_destroy_handle(handle);
}
 
static int write_frame_static(unsigned char *data, int len, int complete, void *ptr)
{
IEC61883Input *input = (IEC61883Input*)ptr;
return input->write_frame(data, len, complete);
}
 
 
 
int IEC61883Input::open(int port,
int channel,
int length,
int channels,
int samplerate,
int bits,
int w,
int h)
{
this->port = port;
this->channel = channel;
this->length = length;
this->channels = channels;
this->samplerate = samplerate;
this->bits = bits;
this->w = w;
this->h = h;
is_pal = (h == 576);
buffer_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
total_buffers = length;
 
 
// Initialize grabbing
if(!handle)
{
handle = raw1394_new_handle_on_port(port);
if(handle)
{
frame = iec61883_dv_fb_init(handle, write_frame_static, (void *)this);
if(frame)
{
if(!iec61883_dv_fb_start(frame, channel))
{
fd = raw1394_get_fd(handle);
}
}
}
 
buffer = new char*[total_buffers];
buffer_valid = new int[total_buffers];
bzero(buffer_valid, sizeof(int) * total_buffers);
for(int i = 0; i < total_buffers; i++)
{
buffer[i] = new char[DV_PAL_SIZE];
}
 
 
audio_buffer = new char[INPUT_SAMPLES * 2 * channels];
 
audio_lock = new Condition(0, "IEC61883Input::audio_lock");
video_lock = new Condition(0, "IEC61883Input::video_lock");
buffer_lock = new Mutex("IEC61883Input::buffer_lock");
 
decoder = dv_new();
 
Thread::start();
}
 
if(!handle || !frame || !fd) return 1;
 
return 0;
}
 
 
void IEC61883Input::run()
{
while(!done && handle)
{
struct timeval tv;
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 20000;
if(select(fd + 1, &rfds, 0, 0, &tv) > 0)
{
raw1394_loop_iterate(handle);
}
}
 
}
 
 
 
 
 
 
 
 
int IEC61883Input::write_frame(unsigned char *data, int len, int complete)
{
if(!complete) printf("write_frame: incomplete frame received.\n");
 
buffer_lock->lock("IEC61883Input write_frame 1");
 
// Get a buffer to transfer to
char *dst = 0;
int is_overflow = 0;
if(!buffer_valid[current_inbuffer])
dst = buffer[current_inbuffer];
else
is_overflow = 1;
 
char *src = (char*)(data);
// static FILE *test = 0;
// if(!test) test = fopen("/tmp/test", "w");
// fwrite(src, buffer_size, 1, test);
 
// Export the video
if(dst)
{
memcpy(dst, src, len);
buffer_valid[current_inbuffer] = 1;
video_lock->unlock();
}
 
 
// Extract the audio
if(audio_samples < INPUT_SAMPLES - 2048)
{
int audio_result = dv_read_audio(decoder,
(unsigned char*)audio_buffer +
audio_samples * 2 * 2,
(unsigned char*)src,
len,
channels,
bits);
int real_freq = decoder->decoder->audio->frequency;
if (real_freq == 32000)
{
// do in-place _FAST_ && _SIMPLE_ upsampling to 48khz
// i also think user should get a warning that his material is effectively 32khz
// we take 16bit samples for both channels in one 32bit int
int *twosample = (int*) (audio_buffer + audio_samples * 2 * 2);
int from = audio_result - 1;
int new_result = audio_result * 48000 / real_freq;
for (int to = new_result - 1; to >=0; to--)
{
if ((to % 3) == 0 || (to % 3) == 1) from --;
twosample[to] = twosample[from];
}
audio_result = new_result;
}
 
 
audio_samples += audio_result;
 
// Export the audio
audio_lock->unlock();
}
 
// Advance buffer
if(!is_overflow)
increment_counter(&current_inbuffer);
 
 
buffer_lock->unlock();
return 0;
}
 
 
 
 
 
 
 
void IEC61883Input::increment_counter(int *counter)
{
(*counter)++;
if(*counter >= total_buffers) *counter = 0;
}
 
void IEC61883Input::decrement_counter(int *counter)
{
(*counter)--;
if(*counter < 0) *counter = total_buffers - 1;
}
 
 
 
int IEC61883Input::read_video(VFrame *data)
{
int result = 0;
 
// Take over buffer table
buffer_lock->lock("IEC61883Input::read_video 1");
// Wait for buffer with timeout
while(!buffer_valid[current_outbuffer] && !result)
{
buffer_lock->unlock();
result = video_lock->timed_lock(BUFFER_TIMEOUT, "IEC61883Input::read_video 2");
buffer_lock->lock("IEC61883Input::read_video 3");
}
 
// Copy frame
if(buffer_valid[current_outbuffer])
{
data->allocate_compressed_data(buffer_size);
data->set_compressed_size(buffer_size);
memcpy(data->get_data(), buffer[current_outbuffer], buffer_size);
buffer_valid[current_outbuffer] = 0;
increment_counter(&current_outbuffer);
}
 
buffer_lock->unlock();
return result;
}
 
 
 
 
int IEC61883Input::read_audio(char *data, int samples)
{
int result = 0;
int timeout = (int64_t)samples * (int64_t)1000000 * (int64_t)2 / (int64_t)samplerate;
if(timeout < 500000) timeout = 500000;
 
// Take over buffer table
buffer_lock->lock("IEC61883Input::read_audio 1");
// Wait for buffer with timeout
while(audio_samples < samples && !result)
{
buffer_lock->unlock();
result = audio_lock->timed_lock(timeout, "IEC61883Input::read_audio 2");
buffer_lock->lock("IEC61883Input::read_audio 3");
}
 
if(audio_samples >= samples)
{
memcpy(data, audio_buffer, samples * bits * channels / 8);
memcpy(audio_buffer,
audio_buffer + samples * bits * channels / 8,
(audio_samples - samples) * bits * channels / 8);
audio_samples -= samples;
}
 
buffer_lock->unlock();
return result;
}
 
 
 
 
 
/branches/automake-1_1_5/hvirtual/cinelerra/filecr2.h
New file
0,0 → 1,48
#ifndef FILECR2_H
#define FILECR2_H
 
 
#include "filebase.h"
 
 
// This uses a program from a guy called Coffin to do the decoding.
// Changes to the dcraw.c file were commented with // Cinelerra
 
// The expected behavior for the dcraw function:
// -i <path>
// When the file is recognized, return 0.
// When the file is unknown, return 1.
 
// <path>
// Decode the file.
extern "C"
{
extern char dcraw_info[1024];
extern float **dcraw_data;
extern int dcraw_alpha;
int dcraw_main (int argc, char **argv);
}
 
class FileCR2 : public FileBase
{
public:
FileCR2(Asset *asset, File *file);
~FileCR2();
 
void reset();
static int check_sig(Asset *asset);
 
// Open file and set asset properties but don't decode.
int open_file(int rd, int wr);
int close_file();
// Open file and decode.
int read_frame(VFrame *frame);
// Get best colormodel for decoding.
int colormodel_supported(int colormodel);
 
private:
void format_to_asset();
};
 
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/iec61883output.h
New file
0,0 → 1,131
#ifndef IEC61883OUTPUT_H
#define IEC61883OUTPUT_H
 
 
 
#ifdef HAVE_FIREWIRE
 
#include "audiodevice.inc"
#include "condition.inc"
#include "iec61883.h"
#include "libdv.h"
#include "mutex.inc"
#include "thread.h"
#include "vframe.inc"
#include "videodevice.inc"
 
// Common 1394 output for audio and video
 
// This runs continuously to keep the VTR warm.
// Takes encoded DV frames and PCM audio.
class IEC61883Output : public Thread
{
public:
IEC61883Output(VideoDevice *vdevice);
IEC61883Output(AudioDevice *adevice);
~IEC61883Output();
 
void reset();
int open(int port,
int channel,
int length,
int channels,
int bits,
int samplerate,
int syt);
void start();
void run();
 
 
// Write frame with timed blocking.
 
void write_frame(VFrame *input);
 
 
// Write audio with timed blocking.
 
void write_samples(char *data, int samples);
long get_audio_position();
void interrupt();
void flush();
 
 
 
void increment_counter(int *counter);
void decrement_counter(int *counter);
int read_frame(unsigned char *data, int n, unsigned int dropped);
 
 
char **buffer;
int *buffer_size;
int *buffer_valid;
 
int total_buffers;
int current_inbuffer;
int current_outbuffer;
 
char *audio_buffer;
int audio_samples;
// Encoder for audio frames
dv_t *encoder;
 
Mutex *buffer_lock;
// Block while waiting for the first buffer to be allocated
Condition *start_lock;
Mutex *position_lock;
 
// Provide timed blocking for writing routines.
 
Condition *video_lock;
Condition *audio_lock;
int done;
 
 
// Output
int fd;
raw1394handle_t handle;
iec61883_dv_t frame;
// Must break up each frame into 480 byte chunks again.
char *out_buffer;
int out_size;
int out_position;
 
 
VFrame *temp_frame, *temp_frame2;
// Encoder for making DV frames
dv_t *audio_encoder;
dv_t *video_encoder;
unsigned char *output_buffer;
int output_number;
unsigned int packet_sizes[321];
unsigned char continuity_counter;
int unused_buffers;
int avc_id;
int channels;
int samplerate;
int bits;
int syt;
long audio_position;
int interrupted;
int have_video;
int is_pal;
VideoDevice *vdevice;
AudioDevice *adevice;
 
 
 
};
 
 
 
 
#endif
 
 
 
 
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/gwindowgui.inc
New file
0,0 → 1,8
#ifndef GWINDOWGUI_INC
#define GWINDOWGUI_INC
 
 
class GWindowGUI;
 
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/tests/diffkey.xml
New file
0,0 → 1,229
<?xml version="1.0"?>
<EDL VERSION=1.2.2 PROJECT_PATH=/root/hvirtual/cinelerra/tests/diffkey.xml>
<LOCALSESSION IN_POINT=-1.0000000000000000e+00 LOOP_PLAYBACK=0 LOOP_START=0.0000000000000000e+00 LOOP_END=1.2445766666666668e+01 OUT_POINT=-1.0000000000000000e+00 SELECTION_START=0.0000000000000000e+00 SELECTION_END=0.0000000000000000e+00 CLIP_TITLE= CLIP_NOTES="Hello world" FOLDER=Clips TRACK_START=0 VIEW_START=0 ZOOM_SAMPLE=1 ZOOMY=64 ZOOM_TRACK=64 PREVIEW_START=0.0000000000000000e+00 PREVIEW_END=3.3366666666666669e-02 RED=6.199329e-01 GREEN=7.370215e-01 BLUE=8.561220e-01>
 
<SESSION ASSETLIST_FORMAT=1 ASSET_COLUMN0=295 ASSET_COLUMN1=82 SHOW_FADE=0 SHOW_PAN=1 SHOW_MUTE=0 SHOW_TRANSITIONS=1 SHOW_PLUGINS=1 SHOW_CAMERA=1 SHOW_PROJECTOR=1 SHOW_MODE=1 SHOW_MASK=1 SHOW_CZOOM=0 SHOW_PZOOM=0 AUTO_KEYFRAMES=0 AUTOS_FOLLOW_EDITS=1 BRENDER_START=3.1990291666666664e+01 CROP_X1=0 CROP_Y1=0 CROP_X2=1820 CROP_Y2=924 CURRENT_FOLDER="Video Effects" CURSOR_ON_FRAMES=1 CWINDOW_DEST=0 CWINDOW_MASK=0 CWINDOW_METER=0 CWINDOW_OPERATION=8 CWINDOW_SCROLLBARS=1 CWINDOW_XSCROLL=29 CWINDOW_YSCROLL=4294967282 CWINDOW_ZOOM=1.000000e+00 DEFAULT_ATRANSITION=Crossfade DEFAULT_VTRANSITION=Dissolve DEFAULT_TRANSITION_LENGTH=5.0000000000000000e-01 EDITING_MODE=1 FOLDERLIST_FORMAT=1 HIGHLIGHTED_TRACK=3 LABELS_FOLLOW_EDITS=0 MPEG4_DEBLOCK=0 PLUGINS_FOLLOW_EDITS=0 PLAYBACK_PRELOAD=0 SAFE_REGIONS=0 SHOW_ASSETS=1 SHOW_TITLES=1 TEST_PLAYBACK_EDITS=1 TIME_FORMAT=0 NUDGE_SECONDS=1 TOOL_WINDOW=1 VWINDOW_METER=1 VWINDOW_FOLDER=VWINDOW_SOURCE=4294967295 VWINDOW_SOURCE=4294967295 VWINDOW_ZOOM=1.000000e+00>
 
<VIDEO INTERPOLATION_TYPE=0 COLORMODEL=RGBA-FLOAT CHANNELS=1 VCHANNEL_X_0=0 VCHANNEL_Y_0=0 FRAMERATE=2.9970029970029969e+01 FRAMES_PER_FOOT=1.600000e+01 OUTPUTW=1820 OUTPUTH=924 ASPECTW=1.960000e+02 ASPECTH=1.000000e+02>
 
<AUDIO SAMPLERATE=48000 CHANNELS=2 ACHANNEL_ANGLE_0=544 ACHANNEL_ANGLE_1=0>
 
<FOLDER>Clips</FOLDER>
<FOLDER>Media</FOLDER>
<ASSETS>
<ASSET SRC=/home/jpeg/mane/diffkey5.cr2>
<FOLDER>Media</FOLDER>
<FORMAT TYPE=Unknown USE_HEADER=1>
<AUDIO_OMIT CHANNELS=0 RATE=0 BITS=0 BYTE_ORDER=0 SIGNED=0 HEADER=0 DITHER=0 ACODEC=twos AUDIO_LENGTH=0 AMPEG_BITRATE=256 AMPEG_DERIVATIVE=3 VORBIS_VBR=0 VORBIS_MIN_BITRATE=4294967295 VORBIS_BITRATE=128000 VORBIS_MAX_BITRATE=4294967295 MP3_BITRATE=256000>
<VIDEO HEIGHT=2348 WIDTH=3522 LAYERS=1 FRAMERATE=1.0000000000000000e+00 VCODEC=yuv2 VIDEO_LENGTH=-1 JPEG_QUALITY=100 ASPECT_RATIO=-1.0000000000000000e+00 VMPEG_IFRAME_DISTANCE=45 VMPEG_BFRAME_DISTANCE=0 VMPEG_PROGRESSIVE=0 VMPEG_DENOISE=1 VMPEG_BITRATE=1000000 VMPEG_DERIVATIVE=1 VMPEG_QUANTIZATION=15 VMPEG_CMODEL=0 VMPEG_FIX_BITRATE=0 VMPEG_SEQ_CODES=0 DIVX_BITRATE=2000000 DIVX_RC_PERIOD=50 DIVX_RC_REACTION_RATIO=45 DIVX_RC_REACTION_PERIOD=10 DIVX_MAX_KEY_INTERVAL=250 DIVX_MAX_QUANTIZER=31 DIVX_MIN_QUANTIZER=1 DIVX_QUANTIZER=15 DIVX_QUALITY=5 DIVX_FIX_BITRATE=1 DIVX_USE_DEBLOCKING=1 MS_BITRATE=1000000 MS_BITRATE_TOLERANCE=500000 MS_INTERLACED=0 MS_QUANTIZATION=10 MS_GOP_SIZE=45 MS_FIX_BITRATE=1 AC3_BITRATE=128 PNG_USE_ALPHA=0 EXR_USE_ALPHA=0 EXR_COMPRESSION=0 TIFF_CMODEL=0 TIFF_COMPRESSION=0>
</ASSET>
<ASSET SRC=/home/jpeg/mane/diffkey6.cr2>
<FOLDER>Media</FOLDER>
<FORMAT TYPE=Unknown USE_HEADER=1>
<AUDIO_OMIT CHANNELS=0 RATE=0 BITS=0 BYTE_ORDER=0 SIGNED=0 HEADER=0 DITHER=0 ACODEC=twos AUDIO_LENGTH=0 AMPEG_BITRATE=256 AMPEG_DERIVATIVE=3 VORBIS_VBR=0 VORBIS_MIN_BITRATE=4294967295 VORBIS_BITRATE=128000 VORBIS_MAX_BITRATE=4294967295 MP3_BITRATE=256000>
<VIDEO HEIGHT=2348 WIDTH=3522 LAYERS=1 FRAMERATE=1.0000000000000000e+00 VCODEC=yuv2 VIDEO_LENGTH=-1 JPEG_QUALITY=100 ASPECT_RATIO=-1.0000000000000000e+00 VMPEG_IFRAME_DISTANCE=45 VMPEG_BFRAME_DISTANCE=0 VMPEG_PROGRESSIVE=0 VMPEG_DENOISE=1 VMPEG_BITRATE=1000000 VMPEG_DERIVATIVE=1 VMPEG_QUANTIZATION=15 VMPEG_CMODEL=0 VMPEG_FIX_BITRATE=0 VMPEG_SEQ_CODES=0 DIVX_BITRATE=2000000 DIVX_RC_PERIOD=50 DIVX_RC_REACTION_RATIO=45 DIVX_RC_REACTION_PERIOD=10 DIVX_MAX_KEY_INTERVAL=250 DIVX_MAX_QUANTIZER=31 DIVX_MIN_QUANTIZER=1 DIVX_QUANTIZER=15 DIVX_QUALITY=5 DIVX_FIX_BITRATE=1 DIVX_USE_DEBLOCKING=1 MS_BITRATE=1000000 MS_BITRATE_TOLERANCE=500000 MS_INTERLACED=0 MS_QUANTIZATION=10 MS_GOP_SIZE=45 MS_FIX_BITRATE=1 AC3_BITRATE=128 PNG_USE_ALPHA=0 EXR_USE_ALPHA=0 EXR_COMPRESSION=0 TIFF_CMODEL=0 TIFF_COMPRESSION=0>
</ASSET>
<ASSET SRC=/tmp/background.exr>
<FOLDER>Media</FOLDER>
<FORMAT TYPE=EXR USE_HEADER=1>
<AUDIO_OMIT CHANNELS=0 RATE=0 BITS=0 BYTE_ORDER=0 SIGNED=0 HEADER=0 DITHER=0 ACODEC=twos AUDIO_LENGTH=0 AMPEG_BITRATE=256 AMPEG_DERIVATIVE=3 VORBIS_VBR=0 VORBIS_MIN_BITRATE=4294967295 VORBIS_BITRATE=128000 VORBIS_MAX_BITRATE=4294967295 MP3_BITRATE=256000>
<VIDEO HEIGHT=2348 WIDTH=3522 LAYERS=1 FRAMERATE=1.0000000000000000e+00 VCODEC=yuv2 VIDEO_LENGTH=-1 JPEG_QUALITY=100 ASPECT_RATIO=-1.0000000000000000e+00 VMPEG_IFRAME_DISTANCE=45 VMPEG_BFRAME_DISTANCE=0 VMPEG_PROGRESSIVE=0 VMPEG_DENOISE=1 VMPEG_BITRATE=1000000 VMPEG_DERIVATIVE=1 VMPEG_QUANTIZATION=15 VMPEG_CMODEL=0 VMPEG_FIX_BITRATE=0 VMPEG_SEQ_CODES=0 DIVX_BITRATE=2000000 DIVX_RC_PERIOD=50 DIVX_RC_REACTION_RATIO=45 DIVX_RC_REACTION_PERIOD=10 DIVX_MAX_KEY_INTERVAL=250 DIVX_MAX_QUANTIZER=31 DIVX_MIN_QUANTIZER=1 DIVX_QUANTIZER=15 DIVX_QUALITY=5 DIVX_FIX_BITRATE=1 DIVX_USE_DEBLOCKING=1 MS_BITRATE=1000000 MS_BITRATE_TOLERANCE=500000 MS_INTERLACED=0 MS_QUANTIZATION=10 MS_GOP_SIZE=45 MS_FIX_BITRATE=1 AC3_BITRATE=128 PNG_USE_ALPHA=0 EXR_USE_ALPHA=0 EXR_COMPRESSION=0 TIFF_CMODEL=0 TIFF_COMPRESSION=0>
</ASSET>
<ASSET SRC=/tmp/top.exr>
<FOLDER>Media</FOLDER>
<FORMAT TYPE=EXR USE_HEADER=1>
<AUDIO_OMIT CHANNELS=0 RATE=0 BITS=0 BYTE_ORDER=0 SIGNED=0 HEADER=0 DITHER=0 ACODEC=twos AUDIO_LENGTH=0 AMPEG_BITRATE=256 AMPEG_DERIVATIVE=3 VORBIS_VBR=0 VORBIS_MIN_BITRATE=4294967295 VORBIS_BITRATE=128000 VORBIS_MAX_BITRATE=4294967295 MP3_BITRATE=256000>
<VIDEO HEIGHT=925 WIDTH=1821 LAYERS=1 FRAMERATE=1.0000000000000000e+00 VCODEC=yuv2 VIDEO_LENGTH=-1 JPEG_QUALITY=100 ASPECT_RATIO=-1.0000000000000000e+00 VMPEG_IFRAME_DISTANCE=45 VMPEG_BFRAME_DISTANCE=0 VMPEG_PROGRESSIVE=0 VMPEG_DENOISE=1 VMPEG_BITRATE=1000000 VMPEG_DERIVATIVE=1 VMPEG_QUANTIZATION=15 VMPEG_CMODEL=0 VMPEG_FIX_BITRATE=0 VMPEG_SEQ_CODES=0 DIVX_BITRATE=2000000 DIVX_RC_PERIOD=50 DIVX_RC_REACTION_RATIO=45 DIVX_RC_REACTION_PERIOD=10 DIVX_MAX_KEY_INTERVAL=250 DIVX_MAX_QUANTIZER=31 DIVX_MIN_QUANTIZER=1 DIVX_QUANTIZER=15 DIVX_QUALITY=5 DIVX_FIX_BITRATE=1 DIVX_USE_DEBLOCKING=1 MS_BITRATE=1000000 MS_BITRATE_TOLERANCE=500000 MS_INTERLACED=0 MS_QUANTIZATION=10 MS_GOP_SIZE=45 MS_FIX_BITRATE=1 AC3_BITRATE=128 PNG_USE_ALPHA=0 EXR_USE_ALPHA=0 EXR_COMPRESSION=0 TIFF_CMODEL=0 TIFF_COMPRESSION=0>
</ASSET>
<ASSET SRC=/tmp/bottom.exr>
<FOLDER>Media</FOLDER>
<FORMAT TYPE=EXR USE_HEADER=1>
<AUDIO_OMIT CHANNELS=0 RATE=0 BITS=0 BYTE_ORDER=0 SIGNED=0 HEADER=0 DITHER=0 ACODEC=twos AUDIO_LENGTH=0 AMPEG_BITRATE=256 AMPEG_DERIVATIVE=3 VORBIS_VBR=0 VORBIS_MIN_BITRATE=4294967295 VORBIS_BITRATE=128000 VORBIS_MAX_BITRATE=4294967295 MP3_BITRATE=256000>
<VIDEO HEIGHT=925 WIDTH=1821 LAYERS=1 FRAMERATE=1.0000000000000000e+00 VCODEC=yuv2 VIDEO_LENGTH=-1 JPEG_QUALITY=100 ASPECT_RATIO=-1.0000000000000000e+00 VMPEG_IFRAME_DISTANCE=45 VMPEG_BFRAME_DISTANCE=0 VMPEG_PROGRESSIVE=0 VMPEG_DENOISE=1 VMPEG_BITRATE=1000000 VMPEG_DERIVATIVE=1 VMPEG_QUANTIZATION=15 VMPEG_CMODEL=0 VMPEG_FIX_BITRATE=0 VMPEG_SEQ_CODES=0 DIVX_BITRATE=2000000 DIVX_RC_PERIOD=50 DIVX_RC_REACTION_RATIO=45 DIVX_RC_REACTION_PERIOD=10 DIVX_MAX_KEY_INTERVAL=250 DIVX_MAX_QUANTIZER=31 DIVX_MIN_QUANTIZER=1 DIVX_QUANTIZER=15 DIVX_QUALITY=5 DIVX_FIX_BITRATE=1 DIVX_USE_DEBLOCKING=1 MS_BITRATE=1000000 MS_BITRATE_TOLERANCE=500000 MS_INTERLACED=0 MS_QUANTIZATION=10 MS_GOP_SIZE=45 MS_FIX_BITRATE=1 AC3_BITRATE=128 PNG_USE_ALPHA=0 EXR_USE_ALPHA=0 EXR_COMPRESSION=0 TIFF_CMODEL=0 TIFF_COMPRESSION=0>
</ASSET>
</ASSETS>
 
 
 
<LABELS>
</LABELS>
 
<TRACK RECORD=1 NUDGE=0 PLAY=1 GANG=1 DRAW=0 EXPAND=0 TRACK_W=1820 TRACK_H=924 TYPE=VIDEO>
<TITLE>Video 4</TITLE>
<EDITS>
<EDIT STARTSOURCE=0 CHANNEL=0 LENGTH=1><FILE SRC=/tmp/top.exr></EDIT>
</EDITS>
<MUTEAUTOS>
<AUTO POSITION=0 VALUE=0>
</MUTEAUTOS>
<FADEAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+02 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</FADEAUTOS>
<CAMERAAUTOS>
<AUTO POSITION=0 CENTER_X=0.000000e+00 CENTER_Y=0.000000e+00 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</CAMERAAUTOS>
<PROJECTORAUTOS>
<AUTO POSITION=0 CENTER_X=0.000000e+00 CENTER_Y=0.000000e+00 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</PROJECTORAUTOS>
<MODEAUTOS>
<AUTO POSITION=0 VALUE=0>
</MODEAUTOS>
<MASKAUTOS>
<AUTO MODE=0 VALUE=100 FEATHER=0.000000e+00 POSITION=0>
<MASK NUMBER=0>
 
<POINT>1.841000e+03, 9.315348e+02, 0.000000e+00, 0.000000e+00, 0.000000e+00, 0.000000e+00</POINT>
<POINT>1.623000e+03, 9.444708e+02, 3.000000e+01, 1.194092e+01, 1.000000e+00, -2.686707e+01</POINT>
<POINT>1.685000e+03, 5.902234e+02, -5.900000e+01, 8.060126e+01, 4.000000e+00, -9.154709e+01</POINT>
<POINT>1.826000e+03, 4.419569e+02, -1.900000e+01, -6.965546e+00, 0.000000e+00, 0.000000e+00</POINT>
</MASK>
 
</AUTO>
</MASKAUTOS>
<CZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</CZOOMAUTOS>
<PZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</PZOOMAUTOS>
</TRACK>
 
 
 
<TRACK RECORD=0 NUDGE=0 PLAY=1 GANG=1 DRAW=0 EXPAND=1 TRACK_W=1820 TRACK_H=924 TYPE=VIDEO>
<TITLE>Video 2</TITLE>
<EDITS>
<EDIT STARTSOURCE=0 CHANNEL=0 LENGTH=1><FILE SRC=/tmp/top.exr></EDIT>
</EDITS>
<MUTEAUTOS>
<AUTO POSITION=0 VALUE=0>
</MUTEAUTOS>
<FADEAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+02 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</FADEAUTOS>
<CAMERAAUTOS>
<AUTO POSITION=0 CENTER_X=0.000000e+00 CENTER_Y=0.000000e+00 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</CAMERAAUTOS>
<PROJECTORAUTOS>
<AUTO POSITION=0 CENTER_X=0.000000e+00 CENTER_Y=0.000000e+00 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</PROJECTORAUTOS>
<MODEAUTOS>
<AUTO POSITION=0 VALUE=0>
</MODEAUTOS>
<MASKAUTOS>
<AUTO MODE=1 VALUE=100 FEATHER=0.000000e+00 POSITION=0>
 
</AUTO>
</MASKAUTOS>
<CZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</CZOOMAUTOS>
<PZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</PZOOMAUTOS>
<PLUGINSET RECORD=1>
<PLUGIN LENGTH=1 TYPE=1 TITLE="Difference key">
<IN><OUT><ON>
<KEYFRAME POSITION=0 DEFAULT=1><DIFFKEY THRESHOLD=1.000000e+01 SLOPE=5.000000e+00 DO_VALUE=0></KEYFRAME>
</PLUGIN>
</PLUGINSET>
<PLUGINSET RECORD=1>
<PLUGIN LENGTH=1 TYPE=1 TITLE="Hue saturation">
<IN><OUT><ON>
<KEYFRAME POSITION=0 DEFAULT=1><HUESATURATION HUE=0.000000e+00 SATURATION=1.000000e+02 VALUE=0.000000e+00></KEYFRAME>
</PLUGIN>
</PLUGINSET>
</TRACK>
 
 
 
<TRACK RECORD=0 NUDGE=0 PLAY=1 GANG=1 DRAW=0 EXPAND=1 TRACK_W=1820 TRACK_H=924 TYPE=VIDEO>
<TITLE>Video 1</TITLE>
<EDITS>
<EDIT STARTSOURCE=0 CHANNEL=0 LENGTH=1><FILE SRC=/tmp/bottom.exr></EDIT>
</EDITS>
<MUTEAUTOS>
<AUTO POSITION=0 VALUE=1>
</MUTEAUTOS>
<FADEAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+02 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</FADEAUTOS>
<CAMERAAUTOS>
<AUTO POSITION=0 CENTER_X=0.000000e+00 CENTER_Y=0.000000e+00 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</CAMERAAUTOS>
<PROJECTORAUTOS>
<AUTO POSITION=0 CENTER_X=0.000000e+00 CENTER_Y=0.000000e+00 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</PROJECTORAUTOS>
<MODEAUTOS>
<AUTO POSITION=0 VALUE=0>
</MODEAUTOS>
<MASKAUTOS>
<AUTO MODE=1 VALUE=100 FEATHER=0.000000e+00 POSITION=0>
 
</AUTO>
</MASKAUTOS>
<CZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</CZOOMAUTOS>
<PZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</PZOOMAUTOS>
<PLUGINSET RECORD=1>
<PLUGIN LENGTH=1 TYPE=2 TITLE=>
<SHARED_LOCATION SHARED_MODULE=1 SHARED_PLUGIN=0></SHARED_LOCATION>
<IN><OUT><ON>
<KEYFRAME POSITION=0 DEFAULT=1></KEYFRAME>
</PLUGIN>
</PLUGINSET>
</TRACK>
 
 
 
<TRACK RECORD=0 NUDGE=0 PLAY=1 GANG=1 DRAW=0 EXPAND=1 TRACK_W=1820 TRACK_H=924 TYPE=VIDEO>
<TITLE>Video 3</TITLE>
<EDITS>
<EDIT STARTSOURCE=0 CHANNEL=0 LENGTH=1><FILE SRC=/tmp/background.exr></EDIT>
</EDITS>
<MUTEAUTOS>
<AUTO POSITION=0 VALUE=0>
</MUTEAUTOS>
<FADEAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+02 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</FADEAUTOS>
<CAMERAAUTOS>
<AUTO POSITION=0 CENTER_X=2.898406e+02 CENTER_Y=-2.715307e+02 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</CAMERAAUTOS>
<PROJECTORAUTOS>
<AUTO POSITION=0 CENTER_X=0.000000e+00 CENTER_Y=0.000000e+00 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</PROJECTORAUTOS>
<MODEAUTOS>
<AUTO POSITION=0 VALUE=0>
</MODEAUTOS>
<MASKAUTOS>
<AUTO MODE=1 VALUE=100 FEATHER=0.000000e+00 POSITION=0>
 
</AUTO>
</MASKAUTOS>
<CZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</CZOOMAUTOS>
<PZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</PZOOMAUTOS>
<PLUGINSET RECORD=1>
<PLUGIN LENGTH=1 TYPE=1 TITLE="Color Balance">
<IN><OUT><ON>
<KEYFRAME POSITION=0 DEFAULT=1><COLORBALANCE CYAN=0.000000e+00 MAGENTA=-1.500000e+01 YELLOW=-2.700000e+01 PRESERVELUMINOSITY=0 LOCKPARAMS=0></KEYFRAME>
</PLUGIN>
</PLUGINSET>
<PLUGINSET RECORD=1>
<PLUGIN LENGTH=1 TYPE=1 TITLE="Hue saturation">
<IN><OUT><ON>
<KEYFRAME POSITION=0 DEFAULT=1><HUESATURATION HUE=0.000000e+00 SATURATION=1.000000e+02 VALUE=0.000000e+00></KEYFRAME>
</PLUGIN>
</PLUGINSET>
</TRACK>
 
 
 
</EDL>
/branches/automake-1_1_5/hvirtual/cinelerra/tests/chromakey.xml
New file
0,0 → 1,121
<?xml version="1.0"?>
<EDL VERSION=1.2.2>
<LOCALSESSION IN_POINT=-1.0000000000000000e+00 LOOP_PLAYBACK=0 LOOP_START=0.0000000000000000e+00 LOOP_END=1.2445766666666668e+01 OUT_POINT=-1.0000000000000000e+00 SELECTION_START=0.0000000000000000e+00 SELECTION_END=0.0000000000000000e+00 CLIP_TITLE=img_0734.cr2 CLIP_NOTES="Hello world" FOLDER=Clips TRACK_START=0 VIEW_START=0 ZOOM_SAMPLE=1 ZOOMY=64 ZOOM_TRACK=64 PREVIEW_START=0.0000000000000000e+00 PREVIEW_END=3.3366666666666669e-02 RED=3.358665e-01 GREEN=5.168500e-01 BLUE=8.511941e-01>
 
<SESSION ASSETLIST_FORMAT=1 ASSET_COLUMN0=295 ASSET_COLUMN1=82 SHOW_FADE=0 SHOW_PAN=1 SHOW_MUTE=0 SHOW_TRANSITIONS=1 SHOW_PLUGINS=1 SHOW_CAMERA=1 SHOW_PROJECTOR=1 SHOW_MODE=1 SHOW_MASK=1 SHOW_CZOOM=0 SHOW_PZOOM=0 AUTO_KEYFRAMES=0 AUTOS_FOLLOW_EDITS=1 BRENDER_START=3.1990291666666664e+01 CROP_X1=0 CROP_Y1=0 CROP_X2=720 CROP_Y2=480 CURRENT_FOLDER="Video Effects" CURSOR_ON_FRAMES=1 CWINDOW_DEST=0 CWINDOW_MASK=0 CWINDOW_METER=0 CWINDOW_OPERATION=8 CWINDOW_SCROLLBARS=0 CWINDOW_XSCROLL=4294966482 CWINDOW_YSCROLL=150 CWINDOW_ZOOM=2.500000e-01 DEFAULT_ATRANSITION=Crossfade DEFAULT_VTRANSITION=Dissolve DEFAULT_TRANSITION_LENGTH=5.0000000000000000e-01 EDITING_MODE=1 FOLDERLIST_FORMAT=1 HIGHLIGHTED_TRACK=0 LABELS_FOLLOW_EDITS=0 MPEG4_DEBLOCK=0 PLUGINS_FOLLOW_EDITS=0 PLAYBACK_PRELOAD=0 SAFE_REGIONS=0 SHOW_ASSETS=1 SHOW_TITLES=1 TEST_PLAYBACK_EDITS=1 TIME_FORMAT=0 NUDGE_SECONDS=1 TOOL_WINDOW=1 VWINDOW_METER=1 VWINDOW_FOLDER= VWINDOW_SOURCE=4294967295 VWINDOW_ZOOM=1.000000e+00>
 
<VIDEO INTERPOLATION_TYPE=2 COLORMODEL=RGBA-FLOAT CHANNELS=1 VCHANNEL_X_0=0 VCHANNEL_Y_0=0 FRAMERATE=2.9970029970029969e+01 FRAMES_PER_FOOT=1.600000e+01 OUTPUTW=3522 OUTPUTH=2348 ASPECTW=3.000000e+00 ASPECTH=2.000000e+00>
 
<AUDIO SAMPLERATE=48000 CHANNELS=2 ACHANNEL_ANGLE_0=544 ACHANNEL_ANGLE_1=0>
 
<FOLDER>Clips</FOLDER>
<FOLDER>Media</FOLDER>
<ASSETS>
<ASSET SRC=/home/jpeg/first_canon/img_0734.cr2>
<FOLDER>Media</FOLDER>
<FORMAT TYPE=Unknown USE_HEADER=1>
<AUDIO_OMIT CHANNELS=0 RATE=0 BITS=0 BYTE_ORDER=0 SIGNED=0 HEADER=0 DITHER=0 ACODEC=twos AUDIO_LENGTH=0 AMPEG_BITRATE=256 AMPEG_DERIVATIVE=3 VORBIS_VBR=0 VORBIS_MIN_BITRATE=4294967295 VORBIS_BITRATE=128000 VORBIS_MAX_BITRATE=4294967295 MP3_BITRATE=256000>
<VIDEO HEIGHT=2348 WIDTH=3522 LAYERS=1 FRAMERATE=1.0000000000000000e+00 VCODEC=yuv2 VIDEO_LENGTH=-1 JPEG_QUALITY=100 ASPECT_RATIO=-1.0000000000000000e+00 VMPEG_IFRAME_DISTANCE=45 VMPEG_BFRAME_DISTANCE=0 VMPEG_PROGRESSIVE=0 VMPEG_DENOISE=1 VMPEG_BITRATE=1000000 VMPEG_DERIVATIVE=1 VMPEG_QUANTIZATION=15 VMPEG_CMODEL=0 VMPEG_FIX_BITRATE=0 VMPEG_SEQ_CODES=0 DIVX_BITRATE=2000000 DIVX_RC_PERIOD=50 DIVX_RC_REACTION_RATIO=45 DIVX_RC_REACTION_PERIOD=10 DIVX_MAX_KEY_INTERVAL=250 DIVX_MAX_QUANTIZER=31 DIVX_MIN_QUANTIZER=1 DIVX_QUANTIZER=15 DIVX_QUALITY=5 DIVX_FIX_BITRATE=1 DIVX_USE_DEBLOCKING=1 MS_BITRATE=1000000 MS_BITRATE_TOLERANCE=500000 MS_INTERLACED=0 MS_QUANTIZATION=10 MS_GOP_SIZE=45 MS_FIX_BITRATE=1 AC3_BITRATE=128 PNG_USE_ALPHA=0 EXR_USE_ALPHA=0 EXR_COMPRESSION=0 TIFF_CMODEL=0 TIFF_COMPRESSION=0>
</ASSET>
<ASSET SRC=/home/jpeg/first_canon/apt3.jpg>
<FOLDER>Media</FOLDER>
<FORMAT TYPE=JPEG USE_HEADER=1>
<AUDIO_OMIT CHANNELS=0 RATE=0 BITS=0 BYTE_ORDER=0 SIGNED=0 HEADER=0 DITHER=0 ACODEC=twos AUDIO_LENGTH=0 AMPEG_BITRATE=256 AMPEG_DERIVATIVE=3 VORBIS_VBR=0 VORBIS_MIN_BITRATE=4294967295 VORBIS_BITRATE=128000 VORBIS_MAX_BITRATE=4294967295 MP3_BITRATE=256000>
<VIDEO HEIGHT=2348 WIDTH=3522 LAYERS=1 FRAMERATE=1.0000000000000000e+00 VCODEC=yuv2 VIDEO_LENGTH=-1 JPEG_QUALITY=100 ASPECT_RATIO=-1.0000000000000000e+00 VMPEG_IFRAME_DISTANCE=45 VMPEG_BFRAME_DISTANCE=0 VMPEG_PROGRESSIVE=0 VMPEG_DENOISE=1 VMPEG_BITRATE=1000000 VMPEG_DERIVATIVE=1 VMPEG_QUANTIZATION=15 VMPEG_CMODEL=0 VMPEG_FIX_BITRATE=0 VMPEG_SEQ_CODES=0 DIVX_BITRATE=2000000 DIVX_RC_PERIOD=50 DIVX_RC_REACTION_RATIO=45 DIVX_RC_REACTION_PERIOD=10 DIVX_MAX_KEY_INTERVAL=250 DIVX_MAX_QUANTIZER=31 DIVX_MIN_QUANTIZER=1 DIVX_QUANTIZER=15 DIVX_QUALITY=5 DIVX_FIX_BITRATE=1 DIVX_USE_DEBLOCKING=1 MS_BITRATE=1000000 MS_BITRATE_TOLERANCE=500000 MS_INTERLACED=0 MS_QUANTIZATION=10 MS_GOP_SIZE=45 MS_FIX_BITRATE=1 AC3_BITRATE=128 PNG_USE_ALPHA=0 EXR_USE_ALPHA=0 EXR_COMPRESSION=0 TIFF_CMODEL=0 TIFF_COMPRESSION=0>
</ASSET>
</ASSETS>
 
 
 
<LABELS>
</LABELS>
 
<TRACK RECORD=0 NUDGE=0 PLAY=1 GANG=1 DRAW=0 EXPAND=1 TRACK_W=3522 TRACK_H=2348 TYPE=VIDEO>
<TITLE>Video 1</TITLE>
<EDITS>
<EDIT STARTSOURCE=0 CHANNEL=0 LENGTH=1><FILE SRC=/home/jpeg/first_canon/img_0734.cr2></EDIT>
</EDITS>
<MUTEAUTOS>
<AUTO POSITION=0 VALUE=0>
</MUTEAUTOS>
<FADEAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+02 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</FADEAUTOS>
<CAMERAAUTOS>
<AUTO POSITION=0 CENTER_X=0.000000e+00 CENTER_Y=0.000000e+00 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</CAMERAAUTOS>
<PROJECTORAUTOS>
<AUTO POSITION=0 CENTER_X=0.000000e+00 CENTER_Y=0.000000e+00 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</PROJECTORAUTOS>
<MODEAUTOS>
<AUTO POSITION=0 VALUE=0>
</MODEAUTOS>
<MASKAUTOS>
<AUTO MODE=1 VALUE=100 FEATHER=0.000000e+00 POSITION=0>
 
</AUTO>
</MASKAUTOS>
<CZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</CZOOMAUTOS>
<PZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</PZOOMAUTOS>
<PLUGINSET RECORD=1>
<PLUGIN LENGTH=1 TYPE=1 TITLE="Color Balance">
<IN><OUT><ON>
<KEYFRAME POSITION=0 DEFAULT=1><COLORBALANCE CYAN=-1.000000e+01 MAGENTA=-9.000000e+00 YELLOW=0.000000e+00 PRESERVELUMINOSITY=0 LOCKPARAMS=0></KEYFRAME>
</PLUGIN>
</PLUGINSET>
<PLUGINSET RECORD=1>
<PLUGIN LENGTH=1 TYPE=1 TITLE=Brightness/Contrast>
<IN><OUT><ON>
<KEYFRAME POSITION=0 DEFAULT=1><BRIGHTNESS BRIGHTNESS=3.600000e+01 CONTRAST=1.000000e+02 LUMA=0></KEYFRAME>
</PLUGIN>
</PLUGINSET>
<PLUGINSET RECORD=1>
<PLUGIN LENGTH=1 TYPE=1 TITLE="Chroma key">
<IN><OUT><SHOW><ON>
<KEYFRAME POSITION=0 DEFAULT=1><CHROMAKEY RED=3.358665e-01 GREEN=5.168500e-01 BLUE=8.511941e-01 THRESHOLD=2.650000e+01 SLOPE=1.900000e+01 USE_VALUE=0></KEYFRAME>
</PLUGIN>
</PLUGINSET>
</TRACK>
 
 
 
<TRACK RECORD=1 NUDGE=0 PLAY=1 GANG=1 DRAW=1 EXPAND=0 TRACK_W=3522 TRACK_H=2348 TYPE=VIDEO>
<TITLE>Video 2</TITLE>
<EDITS>
<EDIT STARTSOURCE=0 CHANNEL=0 LENGTH=1><FILE SRC=/home/jpeg/first_canon/apt3.jpg></EDIT>
</EDITS>
<MUTEAUTOS>
<AUTO POSITION=0 VALUE=0>
</MUTEAUTOS>
<FADEAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+02 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</FADEAUTOS>
<CAMERAAUTOS>
<AUTO POSITION=0 CENTER_X=0.000000e+00 CENTER_Y=0.000000e+00 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</CAMERAAUTOS>
<PROJECTORAUTOS>
<AUTO POSITION=0 CENTER_X=0.000000e+00 CENTER_Y=0.000000e+00 CENTER_Z=1.000000e+00 CONTROL_IN_X=0.000000e+00 CONTROL_IN_Y=0.000000e+00 CONTROL_IN_Z=0.000000e+00 CONTROL_OUT_X=0.000000e+00 CONTROL_OUT_Y=0.000000e+00 CONTROL_OUT_Z=0.000000e+00>
</PROJECTORAUTOS>
<MODEAUTOS>
<AUTO POSITION=0 VALUE=0>
</MODEAUTOS>
<MASKAUTOS>
<AUTO MODE=1 VALUE=100 FEATHER=0.000000e+00 POSITION=0>
 
</AUTO>
</MASKAUTOS>
<CZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</CZOOMAUTOS>
<PZOOMAUTOS>
<AUTO POSITION=0 VALUE=1.000000e+00 CONTROL_IN_VALUE=0.000000e+00 CONTROL_OUT_VALUE=0.000000e+00 CONTROL_IN_POSITION=0 CONTROL_OUT_POSITION=0>
</PZOOMAUTOS>
</TRACK>
 
 
 
</EDL>
/branches/automake-1_1_5/hvirtual/cinelerra/iec61883output.inc
New file
0,0 → 1,14
#ifndef IEC61883OUTPUT_INC
#define IEC61883OUTPUT_INC
 
 
 
 
 
class IEC61883Output;
 
 
 
 
 
#endif
/branches/automake-1_1_5/hvirtual/cinelerra/gwindow.h
New file
0,0 → 1,21
#ifndef GWINDOW_H
#define GWINDOW_H
 
 
#include "gwindowgui.inc"
#include "mwindow.inc"
#include "thread.h"
 
class GWindow : public Thread
{
public:
GWindow(MWindow *mwindow);
void run();
void create_objects();
MWindow *mwindow;
GWindowGUI *gui;
};
 
 
 
#endif
/branches/automake-1_1_5/hvirtual/doc/fit_curves.png
New file
0,0 → 1,5
‰PNG

+(b[µˆ¹IEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/doc/autozoom.png
New file
0,0 → 1,4
‰PNG

+IHDRŒV0é pHYs ‰ ‰7ÉË­tIMEÕ+"“Ť¬IDAThÞíXA ܙòW¿ð5Oðì=l•ReÄ "¶ºM·$Æåœûºa¬µPA9nH“˜“ÄaÒ5}º¼÷ó†ޜ‹|Xêª}«™Z †ˆµÝ]“ÒžçZü(SK®ï›×C-–刵u˜”ößFDÀ˜X©%ëP­Ý0r?fl¤æ½)ÄË£fÄ´†ªò3¹03_ֈò°¢Š²Së‡á=‰Ã2ÍËú¯1§»2äP³d–[¸YXsâ’#¿VÑÿ:Q/ªI½fõII×ß$è:™6R÷úôOµåu¿8ª_€uyq˜´ß§fFº;ˆ$˜pà Nõ¶Q6'IEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/doc/cwindow_light.png
New file
0,0 → 1,5
‰PNG

+IHDR üí£ pHYs ‰ ‰7ÉË­tIMEÕ-“} íIDATHÇՖ1„ Ecvíèi,8Ž· ÷@ôފÂÂÖ[l±3»#‹ð°X*‹Ì{•Ÿ ó<Óω1R§óÌÒ­µ½|+=t§Ÿwп~‡F€Ó÷}÷ދƒs§¿ŸC뺢HéD´, ÞKéR+è"ë踃ÕtÐÁ-tÄÁôªƒÛéew¡'µÖ9§doxúŠÔŽ«üÈ|d…£NùßTä(gßåEÕd-EEՁäv%ì
+p*Ôã:ëÀg#E‰C6ÑÀºCD'¢Ç4M`©1fÇmۚ6»j­«ã]‹× ^æî›7™<’=IEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/doc/cwindow_zoom.png
New file
0,0 → 1,10
‰PNG

+IHDRƒ ¾w\q pHYs ‰ ‰7ÉË­tIMEÕ Xk­µ‹IDAThÞíš[
+녝Ýøy@ø¶$ ’썑1fš&ûûޒ
+X³ŽjIEND®B`‚
\ No newline at end of file
/branches/automake-1_1_5/hvirtual/plugins/histogram/histogram.h
New file
0,0 → 1,111
#ifndef HISTOGRAM_H
#define HISTOGRAM_H
 
 
#include "histogram.inc"
#include "histogramconfig.h"
#include "histogramwindow.inc"
#include "loadbalance.h"
#include "plugincolors.h"
#include "pluginvclient.h"
 
 
class HistogramMain : public PluginVClient
{
public:
HistogramMain(PluginServer *server);
~HistogramMain();
 
int process_realtime(VFrame *input_ptr, VFrame *output_ptr);
int is_realtime();
int load_defaults();
int save_defaults();
void save_data(KeyFrame *keyframe);
void read_data(KeyFrame *keyframe);
void update_gui();
void render_gui(void *data);
 
PLUGIN_CLASS_MEMBERS(HistogramConfig, HistogramThread)
 
// Convert input to linear output
float calculate_linear(float input, int mode, int do_value);
float calculate_smooth(float input, int subscript);
// Convert input to smoothed output by looking up in smooth table.
float calculate_curve(float input);
// Calculate automatic settings
void calculate_automatic(VFrame *data);
// Calculate histogram
void calculate_histogram(VFrame *data);
// Calculate the linear, smoothed, lookup curves
void tabulate_curve(int subscript, int use_value);
 
 
 
YUV yuv;
VFrame *input, *output;
HistogramEngine *engine;
int *lookup[HISTOGRAM_MODES];
float *smoothed[HISTOGRAM_MODES];
float *linear[HISTOGRAM_MODES];
int *accum[HISTOGRAM_MODES];
// Input point being dragged or edited
int current_point;
// Current channel being viewed
int mode;
int dragging_point;
int point_x_offset;
int point_y_offset;
};
 
class HistogramPackage : public LoadPackage
{
public:
HistogramPackage();
int start, end;
};
 
class HistogramUnit : public LoadClient
{
public:
HistogramUnit(HistogramEngine *server, HistogramMain *plugin);
~HistogramUnit();
void process_package(LoadPackage *package);
HistogramEngine *server;
HistogramMain *plugin;
int *accum[5];
};
 
class HistogramEngine : public LoadServer
{
public:
HistogramEngine(HistogramMain *plugin,
int total_clients,
int total_packages);
void process_packages(int operation, VFrame *data);
void init_packages();
LoadClient* new_client();
LoadPackage* new_package();
HistogramMain *plugin;
int total_size;
 
 
int operation;
enum
{
HISTOGRAM,
APPLY
};
VFrame *data;
};
 
 
 
 
 
 
 
 
 
 
 
#endif
/branches/automake-1_1_5/hvirtual/plugins/histogram/histogramconfig.C
New file
0,0 → 1,258
#include "clip.h"
#include "histogramconfig.h"
#include "units.h"
 
#include <math.h>
 
 
 
 
 
HistogramPoint::HistogramPoint()
: ListItem<HistogramPoint>()
{
}
 
HistogramPoint::~HistogramPoint()
{
}
 
int HistogramPoint::equivalent(HistogramPoint *src)
{
return EQUIV(x, src->x) && EQUIV(y, src->y);
}
 
 
 
 
HistogramPoints::HistogramPoints()
: List<HistogramPoint>()
{
}
 
HistogramPoints::~HistogramPoints()
{
}
 
HistogramPoint* HistogramPoints::insert(float x, float y)
{
HistogramPoint *current = first;
 
// Get existing point after new point
while(current)
{
if(current->x > x)
break;
else
current = NEXT;
}
 
// Insert new point before current point
HistogramPoint *new_point = new HistogramPoint;
if(current)
{
insert_before(current, new_point);
}
else
// Append new point to list
{
append(new_point);
}
 
new_point->x = x;
new_point->y = y;
 
 
return new_point;
}
 
void HistogramPoints::boundaries()
{
HistogramPoint *current = first;
while(current)
{
CLAMP(current->x, 0.0, 1.0);
CLAMP(current->y, 0.0, 1.0);
current = NEXT;
}
}
 
int HistogramPoints::equivalent(HistogramPoints *src)
{
HistogramPoint *current_this = first;
HistogramPoint *current_src = src->first;
while(current_this && current_src)
{
if(!current_this->equivalent(current_src)) return 0;
current_this = current_this->next;
current_src = current_src->next;
}
 
if(!current_this && current_src ||
current_this && !current_src)
return 0;
return 1;
}
 
void HistogramPoints::copy_from(HistogramPoints *src)
{
while(last)
delete last;
HistogramPoint *current = src->first;
while(current)
{
HistogramPoint *new_point = new HistogramPoint;
new_point->x = current->x;
new_point->y = current->y;
append(new_point);
current = NEXT;
}
}
 
void HistogramPoints::interpolate(HistogramPoints *prev,
HistogramPoints *next,
double prev_scale,
double next_scale)
{
HistogramPoint *current = first;
HistogramPoint *current_prev = prev->first;
HistogramPoint *current_next = next->first;
 
while(current && current_prev && current_next)
{
current->x = current_prev->x * prev_scale +
current_next->x * next_scale;
current->y = current_prev->y * prev_scale +
current_next->y * next_scale;
current = NEXT;
current_prev = current_prev->next;
current_next = current_next->next;
}
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
HistogramConfig::HistogramConfig()
{
reset(1);
}
 
void HistogramConfig::reset(int do_mode)
{
reset_points();
 
for(int i = 0; i < HISTOGRAM_MODES; i++)
{
output_min[i] = 0.0;
output_max[i] = 1.0;
}
 
if(do_mode)
{
automatic = 0;
threshold = 0.1;
}
}
 
void HistogramConfig::reset_points()
{
for(int i = 0; i < HISTOGRAM_MODES; i++)
{
while(points[i].last) delete points[i].last;
}
}
 
 
void HistogramConfig::boundaries()
{
for(int i = 0; i < HISTOGRAM_MODES; i++)
{
points[i].boundaries();
CLAMP(output_min[i], MIN_INPUT, MAX_INPUT);
CLAMP(output_max[i], MIN_INPUT, MAX_INPUT);
output_min[i] = Units::quantize(output_min[i], PRECISION);
output_max[i] = Units::quantize(output_max[i], PRECISION);
}
CLAMP(threshold, 0, 1);
}
 
int HistogramConfig::equivalent(HistogramConfig &that)
{
for(int i = 0; i < HISTOGRAM_MODES; i++)
{
if(!points[i].equivalent(&that.points[i]) ||
!EQUIV(output_min[i], that.output_min[i]) ||
!EQUIV(output_max[i], that.output_max[i])) return 0;
}
 
if(automatic != that.automatic ||
!EQUIV(threshold, that.threshold)) return 0;
 
return 1;
}
 
void HistogramConfig::copy_from(HistogramConfig &that)
{
for(int i = 0; i < HISTOGRAM_MODES; i++)
{
points[i].copy_from(&that.points[i]);
output_min[i] = that.output_min[i];
output_max[i] = that.output_max[i];
}
 
automatic = that.automatic;
threshold = that.threshold;
}
 
void HistogramConfig::interpolate(HistogramConfig &prev,
HistogramConfig &next,
int64_t prev_frame,
int64_t next_frame,
int64_t current_frame)
{
double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
double prev_scale = 1.0 - next_scale;
 
for(int i = 0; i < HISTOGRAM_MODES; i++)
{
points[i].interpolate(&prev.points[i], &next.points[i], next_scale, prev_scale);
output_min[i] = prev.output_min[i] * prev_scale + next.output_min[i] * next_scale;
output_max[i] = prev.output_max[i] * prev_scale + next.output_max[i] * next_scale;
}
 
threshold = prev.threshold * prev_scale + next.threshold * next_scale;
automatic = prev.automatic;
}
 
 
void HistogramConfig::dump()
{
for(int j = 0; j < HISTOGRAM_MODES; j++)
{
printf("HistogramConfig::dump mode=%d\n", j);
HistogramPoints *points = &this->points[j];
HistogramPoint *current = points->first;
while(current)
{
printf("%f,%f ", current->x, current->y);
fflush(stdout);
current = NEXT;
}
printf("\n");
}
}
 
 
 
/branches/automake-1_1_5/hvirtual/plugins/histogram/histogram.inc
New file
0,0 → 1,37
#ifndef HISTOGRAM_INC
#define HISTOGRAM_INC
 
 
 
 
 
// modes
#define HISTOGRAM_MODES 4
#define HISTOGRAM_RED 0
#define HISTOGRAM_GREEN 1
#define HISTOGRAM_BLUE 2
#define HISTOGRAM_VALUE 3
 
// Number of divisions in histogram.
// 65536 + min and max range to speed up the tabulation
#define HISTOGRAM_SLOTS 0x13333
#define FLOAT_RANGE 1.2
// Minimum value in percentage
#define HISTOGRAM_MIN -10
#define MIN_INPUT -0.1
// Maximum value in percentage
#define HISTOGRAM_MAX 110
#define MAX_INPUT 1.1
 
#define PRECISION 0.001
#define DIGITS 3
#define THRESHOLD_SCALE 1000
 
#define BOX_SIZE 10
 
 
class HistogramEngine;
class HistogramMain;
 
 
#endif
/branches/automake-1_1_5/hvirtual/plugins/histogram/histogramwindow.C
New file
0,0 → 1,848
#include "bcdisplayinfo.h"
#include "bcsignals.h"
#include "histogram.h"
#include "histogramconfig.h"
#include "histogramwindow.h"
#include "keys.h"
#include "language.h"
 
 
#include <unistd.h>
 
PLUGIN_THREAD_OBJECT(HistogramMain, HistogramThread, HistogramWindow)
 
 
 
HistogramWindow::HistogramWindow(HistogramMain *plugin, int x, int y)
: BC_Window(plugin->gui_string,
x,
y,
440,
480,
440,
480,
0,
1,
1)
{
this->plugin = plugin;
}
 
HistogramWindow::~HistogramWindow()
{
}
 
#include "max_picon_png.h"
#include "mid_picon_png.h"
#include "min_picon_png.h"
static VFrame max_picon_image(max_picon_png);
static VFrame mid_picon_image(mid_picon_png);
static VFrame min_picon_image(min_picon_png);
 
int HistogramWindow::create_objects()
{
int x = 10, y = 10, x1 = 10;
BC_Title *title = 0;
 
max_picon = new BC_Pixmap(this, &max_picon_image);
mid_picon = new BC_Pixmap(this, &mid_picon_image);
min_picon = new BC_Pixmap(this, &min_picon_image);
add_subwindow(mode_v = new HistogramMode(plugin,
x,
y,
HISTOGRAM_VALUE,
_("Value")));
x += 70;
add_subwindow(mode_r = new HistogramMode(plugin,
x,
y,
HISTOGRAM_RED,
_("Red")));
x += 70;
add_subwindow(mode_g = new HistogramMode(plugin,
x,
y,
HISTOGRAM_GREEN,
_("Green")));
x += 70;
add_subwindow(mode_b = new HistogramMode(plugin,
x,
y,
HISTOGRAM_BLUE,
_("Blue")));
// x += 70;
// add_subwindow(mode_a = new HistogramMode(plugin,
// x,
// y,
// HISTOGRAM_ALPHA,
// _("Alpha")));
 
x = x1;
y += 30;
add_subwindow(title = new BC_Title(x, y, _("Input X:")));
x += title->get_w() + 10;
input_x = new HistogramInputText(plugin,
this,
x,
y,
1);
input_x->create_objects();
 
x += input_x->get_w() + 10;
add_subwindow(title = new BC_Title(x, y, _("Input Y:")));
x += title->get_w() + 10;
input_y = new HistogramInputText(plugin,
this,
x,
y,
0);
input_y->create_objects();
 
y += 30;
x = x1;
 
canvas_w = get_w() - x - x;
canvas_h = get_h() - y - 170;
title1_x = x;
title2_x = x + (int)(canvas_w * -MIN_INPUT / FLOAT_RANGE);
title3_x = x + (int)(canvas_w * (1.0 - MIN_INPUT) / FLOAT_RANGE);
title4_x = x + (int)(canvas_w);
add_subwindow(canvas = new HistogramCanvas(plugin,
this,
x,
y,
canvas_w,
canvas_h));
draw_canvas_overlay();
canvas->flash();
 
y += canvas->get_h() + 1;
add_subwindow(new BC_Title(title1_x,
y,
"-10%"));
add_subwindow(new BC_Title(title2_x,
y,
"0%"));
add_subwindow(new BC_Title(title3_x - get_text_width(MEDIUMFONT, "100"),
y,
"100%"));
add_subwindow(new BC_Title(title4_x - get_text_width(MEDIUMFONT, "110"),
y,
"110%"));
 
y += 20;
add_subwindow(title = new BC_Title(x, y, _("Output min:")));
x += title->get_w() + 10;
output_min = new HistogramOutputText(plugin,
this,
x,
y,
&plugin->config.output_min[plugin->mode]);
output_min->create_objects();
x += output_min->get_w() + 10;
add_subwindow(new BC_Title(x, y, _("Output Max:")));
x += title->get_w() + 10;
output_max = new HistogramOutputText(plugin,
this,
x,
y,
&plugin->config.output_max[plugin->mode]);
output_max->create_objects();
 
x = x1;
y += 30;
 
add_subwindow(output = new HistogramSlider(plugin,
this,
x,
y,
get_w() - 20,
30,
0));
output->update();
y += 40;
 
 
add_subwindow(automatic = new HistogramAuto(plugin,
x,
y));
 
x += 120;
add_subwindow(new HistogramReset(plugin,
x,
y));
x += 100;
add_subwindow(new BC_Title(x, y, _("Threshold:")));
x += 100;
threshold = new HistogramOutputText(plugin,
this,
x,
y,
&plugin->config.threshold);
threshold->create_objects();
 
 
show_window();
 
return 0;
}
 
WINDOW_CLOSE_EVENT(HistogramWindow)
 
int HistogramWindow::keypress_event()
{
int result = 0;
if(get_keypress() == BACKSPACE ||
get_keypress() == DELETE)
{
if(plugin->current_point >= 0)
{
HistogramPoint *current =
plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
delete current;
plugin->current_point = -1;
update_input();
update_canvas();
plugin->send_configure_change();
result = 1;
}
}
return result;
}
 
void HistogramWindow::update(int do_input)
{
automatic->update(plugin->config.automatic);
threshold->update(plugin->config.threshold);
update_mode();
 
if(do_input) update_input();
update_output();
}
 
void HistogramWindow::update_input()
{
input_x->update();
input_y->update();
}
 
void HistogramWindow::update_output()
{
output->update();
output_min->update(plugin->config.output_min[plugin->mode]);
output_max->update(plugin->config.output_max[plugin->mode]);
}
 
void HistogramWindow::update_mode()
{
mode_v->update(plugin->mode == HISTOGRAM_VALUE ? 1 : 0);
mode_r->update(plugin->mode == HISTOGRAM_RED ? 1 : 0);
mode_g->update(plugin->mode == HISTOGRAM_GREEN ? 1 : 0);
mode_b->update(plugin->mode == HISTOGRAM_BLUE ? 1 : 0);
output_min->output = &plugin->config.output_min[plugin->mode];
output_max->output = &plugin->config.output_max[plugin->mode];
}
 
void HistogramWindow::draw_canvas_overlay()
{
canvas->set_color(0x00ff00);
int y1;
 
// Calculate output curve
plugin->tabulate_curve(plugin->mode, 0);
 
// Draw output line
for(int i = 0; i < canvas_w; i++)
{
float input = (float)i /
canvas_w *
FLOAT_RANGE +
MIN_INPUT;
float output = plugin->calculate_smooth(input, plugin->mode);
 
int y2 = canvas_h - (int)(output * canvas_h);
if(i > 0)
{
canvas->draw_line(i - 1, y1, i, y2);
}
y1 = y2;
}
 
// Draw output points
HistogramPoint *current = plugin->config.points[plugin->mode].first;
int number = 0;
while(current)
{
int x = (int)((current->x - MIN_INPUT) * canvas_w / FLOAT_RANGE);
int y = (int)(canvas_h - current->y * canvas_h);
if(number == plugin->current_point)
canvas->draw_box(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
else
canvas->draw_rectangle(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
current = NEXT;
number++;
}
 
 
// Draw 0 and 100% lines.
canvas->set_color(0xff0000);
canvas->draw_line(title2_x - canvas->get_x(),
0,
title2_x - canvas->get_x(),
canvas_h);
canvas->draw_line(title3_x - canvas->get_x(),
0,
title3_x - canvas->get_x(),
canvas_h);
}
 
void HistogramWindow::update_canvas()
{
int *accum = plugin->accum[plugin->mode];
int accum_per_canvas_i = HISTOGRAM_SLOTS / canvas_w + 1;
float accum_per_canvas_f = (float)HISTOGRAM_SLOTS / canvas_w;
int normalize = 0;
int max = 0;
 
for(int i = 0; i < HISTOGRAM_SLOTS; i++)
{
if(accum && accum[i] > normalize) normalize = accum[i];
}
 
 
if(normalize)
{
for(int i = 0; i < canvas_w; i++)
{
int accum_start = (int)(accum_per_canvas_f * i);
int accum_end = accum_start + accum_per_canvas_i;
max = 0;
for(int j = accum_start; j < accum_end; j++)
{
max = MAX(accum[j], max);
}
 
// max = max * canvas_h / normalize;
max = (int)(log(max) / log(normalize) * canvas_h);
 
canvas->set_color(0xffffff);
canvas->draw_line(i, 0, i, canvas_h - max);
canvas->set_color(0x000000);
canvas->draw_line(i, canvas_h - max, i, canvas_h);
}
}
else
{
canvas->set_color(0xffffff);
canvas->draw_box(0, 0, canvas_w, canvas_h);
}
 
 
draw_canvas_overlay();
canvas->flash();
}
 
 
 
 
 
 
 
 
HistogramCanvas::HistogramCanvas(HistogramMain *plugin,
HistogramWindow *gui,
int x,
int y,
int w,
int h)
: BC_SubWindow(x,
y,
w,
h,
0xffffff)
{
this->plugin = plugin;
this->gui = gui;
}
 
int HistogramCanvas::button_press_event()
{
int result = 0;
if(is_event_win() && cursor_inside())
{
if(!plugin->dragging_point)
{
HistogramPoint *new_point = 0;
gui->deactivate();
// Search for existing point under cursor
HistogramPoint *current = plugin->config.points[plugin->mode].first;
plugin->current_point = -1;
while(current)
{
int x = (int)((current->x - MIN_INPUT) * gui->canvas_w / FLOAT_RANGE);
int y = (int)(gui->canvas_h - current->y * gui->canvas_h);
 
if(get_cursor_x() >= x - BOX_SIZE / 2 &&
get_cursor_y() >= y - BOX_SIZE / 2 &&
get_cursor_x() < x + BOX_SIZE / 2 &&
get_cursor_y() < y + BOX_SIZE / 2)
{
plugin->current_point =
plugin->config.points[plugin->mode].number_of(current);
plugin->point_x_offset = get_cursor_x() - x;
plugin->point_y_offset = get_cursor_y() - y;
break;
}
current = NEXT;
}
 
if(plugin->current_point < 0)
{
// Create new point under cursor
float current_x = (float)get_cursor_x() *
FLOAT_RANGE /
get_w() +
MIN_INPUT;
float current_y = 1.0 -
(float)get_cursor_y() /
get_h();
new_point =
plugin->config.points[plugin->mode].insert(current_x, current_y);
plugin->current_point =
plugin->config.points[plugin->mode].number_of(new_point);
plugin->point_x_offset = 0;
plugin->point_y_offset = 0;
}
 
plugin->dragging_point = 1;
result = 1;
 
plugin->config.boundaries();
gui->update_input();
gui->update_canvas();
if(new_point)
{
plugin->send_configure_change();
}
}
}
return result;
}
 
int HistogramCanvas::cursor_motion_event()
{
if(plugin->dragging_point)
{
float current_x =
(float)(get_cursor_x() - plugin->point_x_offset) *
FLOAT_RANGE /
get_w() +
MIN_INPUT;
float current_y = 1.0 -
(float)(get_cursor_y() - plugin->point_y_offset) /
get_h();
HistogramPoint *current_point =
plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
current_point->x = current_x;
current_point->y = current_y;
plugin->config.boundaries();
gui->update_input();
gui->update_canvas();
plugin->send_configure_change();
return 1;
}
return 0;
}
 
int HistogramCanvas::button_release_event()
{
if(plugin->dragging_point)
{
// Test for out of order points to delete.
HistogramPoint *current =
plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
HistogramPoint *prev = PREVIOUS;
HistogramPoint *next = NEXT;
 
if((prev && prev->x >= current->x) ||
(next && next->x <= current->x))
{
delete current;
plugin->current_point = -1;
plugin->config.boundaries();
gui->update_input();
gui->update_canvas();
plugin->send_configure_change();
}
 
plugin->dragging_point = 0;
}
return 0;
}
 
 
 
 
 
 
 
HistogramReset::HistogramReset(HistogramMain *plugin,
int x,
int y)
: BC_GenericButton(x, y, _("Reset"))
{
this->plugin = plugin;
}
int HistogramReset::handle_event()
{
plugin->config.reset(0);
plugin->thread->window->update(1);
plugin->thread->window->update_canvas();
plugin->send_configure_change();
return 1;
}
 
 
 
 
 
 
 
 
 
HistogramSlider::HistogramSlider(HistogramMain *plugin,
HistogramWindow *gui,
int x,
int y,
int w,
int h,
int is_input)
: BC_SubWindow(x, y, w, h)
{
this->plugin = plugin;
this->gui = gui;
this->is_input = is_input;
operation = NONE;
}
 
int HistogramSlider::input_to_pixel(float input)
{