segv in reosurce constructor, add histeq plugin, 2pass formats, cleanup, colormatrix...
authorGood Guy <good1.2guy@gmail.com>
Sat, 16 Dec 2017 16:19:22 +0000 (09:19 -0700)
committerGood Guy <good1.2guy@gmail.com>
Sat, 16 Dec 2017 16:19:22 +0000 (09:19 -0700)
35 files changed:
cinelerra-5.1/cinelerra/appearanceprefs.C
cinelerra-5.1/cinelerra/awindowgui.C
cinelerra-5.1/cinelerra/filebase.C
cinelerra-5.1/cinelerra/filecr2.C
cinelerra-5.1/cinelerra/filempeg.C
cinelerra-5.1/cinelerra/mainindexes.C
cinelerra-5.1/cinelerra/mwindow.C
cinelerra-5.1/cinelerra/performanceprefs.inc
cinelerra-5.1/cinelerra/playback3d.h
cinelerra-5.1/cinelerra/record.C
cinelerra-5.1/cinelerra/resample.C
cinelerra-5.1/cinelerra/resourcethread.C
cinelerra-5.1/cinelerra/trackcanvas.C
cinelerra-5.1/cinelerra/undostack.C
cinelerra-5.1/ffmpeg/audio/h264.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/audio/mp4.dfl
cinelerra-5.1/ffmpeg/audio/passes1and2_h264.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/audio/passes1and2_h265.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/pass1of2_h264.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/pass1of2_h265.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/pass2of2_h264.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/pass2of2_h265.mp4 [new file with mode: 0644]
cinelerra-5.1/guicast/bccolors.C
cinelerra-5.1/guicast/bccolors.h
cinelerra-5.1/guicast/vframe.C
cinelerra-5.1/info/plugins.txt
cinelerra-5.1/picon/cinfinity/histeq.png [new file with mode: 0644]
cinelerra-5.1/plugin_defs
cinelerra-5.1/plugins/Makefile
cinelerra-5.1/plugins/histeq/.gdb_history [new file with mode: 0644]
cinelerra-5.1/plugins/histeq/Makefile [new file with mode: 0644]
cinelerra-5.1/plugins/histeq/histeq.C [new file with mode: 0644]
cinelerra-5.1/plugins/histeq/histeq.h [new file with mode: 0644]
cinelerra-5.1/plugins/histeq/histeq.inc [new file with mode: 0644]
cinelerra-5.1/plugins/histogram/histogram.C

index 7342e3eab42f491837b6afb3622c6e8b79312ce9..0960bb308dc253b786563a77875b3a94839fedd4 100644 (file)
@@ -135,6 +135,12 @@ void AppearancePrefs::create_objects()
                x, y));
        x = x0;
        y += 35;
+       add_subwindow(new BC_Bar(5, y,  get_w()/2 - 30));
+       y += 15;
+
+       add_subwindow(new BC_Title(x, y, _("Color:"), LARGEFONT,
+               resources->text_default));
+       y += 35;
        add_subwindow(title = new BC_Title(x, y, _("Highlighting Inversion color:")));
        x += title->get_w() + margin;
        char hex_color[BCSTRLEN];
index 7195d4e78b2bcb1d35ba3497634bedc1070fd2af..a0b7d385550fae02eab637e394919cc10aaef119 100644 (file)
@@ -106,14 +106,14 @@ VFrame *AssetVIcon::frame()
                        delete temp;  temp = 0;
                }
                if( !temp )
-                       temp = new VFrame(asset->width, asset->height, BC_RGB888, 0);
+                       temp = new VFrame(0, -1, asset->width, asset->height, BC_RGB888, -1);
                int ww = picon->gui->vicon_thread->view_w;
                int hh = picon->gui->vicon_thread->view_h;
                while( seq_no >= images.size() ) {
                        file->set_layer(0);
                        int64_t pos = images.size() / picon->gui->vicon_thread->refresh_rate * frame_rate;
                        file->set_video_position(pos,0);
-                       file->read_frame(temp);
+                       if( file->read_frame(temp) ) temp->clear_frame();
                        add_image(temp, ww, hh, BC_RGB8);
                }
                mwindow->video_cache->check_in(asset);
index 29813196beb308005ab5ac159175574fd4f1db27..4671fc4aab94032af9ddf77bf1e0693df87a247a 100644 (file)
@@ -42,26 +42,20 @@ FileBase::FileBase(Asset *asset, File *file)
 FileBase::~FileBase()
 {
        close_file();
-       if(row_pointers_in) delete [] row_pointers_in;
-       if(row_pointers_out) delete [] row_pointers_out;
-       if(float_buffer) delete [] float_buffer;
 }
 
 int FileBase::close_file()
 {
-       if(row_pointers_in) delete [] row_pointers_in;
-       if(row_pointers_out) delete [] row_pointers_out;
-       if(float_buffer) delete [] float_buffer;
+       delete [] row_pointers_in;   row_pointers_in = 0;
+       delete [] row_pointers_out;  row_pointers_out = 0;
+       delete [] float_buffer;      float_buffer = 0;
 
-
-       if(pcm_history)
-       {
+       if( pcm_history ) {
                for(int i = 0; i < history_channels; i++)
                        delete [] pcm_history[i];
-               delete [] pcm_history;
+               delete [] pcm_history;  pcm_history = 0;
        }
 
-
        close_file_derived();
        reset_parameters();
        return 0;
@@ -72,8 +66,7 @@ void FileBase::update_pcm_history(int64_t len)
        decode_start = 0;
        decode_len = 0;
 
-       if(!pcm_history)
-       {
+       if( !pcm_history ) {
                history_channels = asset->channels;
                pcm_history = new double*[history_channels];
                for(int i = 0; i < history_channels; i++)
index f7466a0c1155637b57abfce1bd9790d8a368b9f5..f7db2f01f7b830cef56a0ebfd44af8bc1dcf43bd 100644 (file)
@@ -196,7 +196,7 @@ int FileCR2::get_best_colormodel(Asset *asset, int driver)
 // int64_t FileCR2::get_memory_usage()
 // {
 //     int64_t result = asset->width * asset->height * sizeof(float) * 3;
-//printf("FileCR2::get_memory_usage %d " _LD "\n", __LINE__, result);
+//printf("FileCR2::get_memory_usage %d %jd\n", __LINE__, result);
 //     return result;
 // }
 
index 4617fe3f5b6f160e69d38072c48037feb2f5e5ba..9913a98b93a3c91c3ddb11c61944ab99fac2e5ad 100644 (file)
@@ -786,7 +786,7 @@ int FileMPEG::toc_nail(void *vp, int track)
        if( mpeg->get_video_info(track, pid, framerate, width, height) ) return 1;
        if( pid < 0 || framerate <= 0 ) return 1;
        double position = framenum / framerate;
-//printf("t%d/%03x f"_LD", %dx%d %dx%d\n",track,pid,framenum,mw,mh,width,height);
+//printf("t%d/%03x f%jd, %dx%d %dx%d\n",track,pid,framenum,mw,mh,width,height);
        MWindow::commercials->get_frame(file, pid, position, tdat, mw, mh, width, height);
        return 0;
 }
index 679441bd896d00a1d3c479bebdd6999ffdb5fc40..d871a50b39100ac72ffdcd2a6cefc9e19bc606c1 100644 (file)
@@ -74,8 +74,7 @@ void MainIndexes::add_next_asset(File *file, Indexable *indexable)
 SET_TRACE
 // Test current asset
        IndexFile indexfile(mwindow, indexable);
-       IndexState *index_state = 0;
-       index_state = indexable->index_state;
+       IndexState *index_state = indexable->index_state;
 
 SET_TRACE
        int ret = indexfile.open_index();
index 84ba6830aa88bd39cfea54d154dd94ead97a07ff..317900677c602cc2d6ae5d8cab67de4608ec1f51 100644 (file)
@@ -3352,6 +3352,7 @@ void MWindow::rebuild_indices()
                                asset->reset_audio();
                        }
                        asset->reset_video();
+                       remove_asset_from_caches(asset);
 //                     File file; // re-probe the asset
 //                     file.open_file(preferences, asset, 1, 0);
                }
index 6e9a2a4ab16e9a34056ef6b89f16796f66d74918..b8793fb12349a7a9cd5d227fd25b649b77acbb3f 100644 (file)
@@ -28,8 +28,6 @@ class PrefsBRenderFragment;
 class PrefsRenderPreroll;
 class PrefsBRenderPreroll;
 class PrefsForceUniprocessor;
-class PrefsTrapSigSEGV;
-class PrefsTrapSigINTR;
 class PrefsFFMPEGMarkerIndecies;
 class PrefsRenderFarm;
 class PrefsRenderFarmConsolidate;
index 452b367c2facaa0aa127dcc8fffe8e6f2b367cbd..2139ba7ba7ec9e52e58469c6c90a295f74c16d67 100644 (file)
@@ -42,7 +42,7 @@
 
 // use static presets YUV in bccolors.h
 #define BC_GL_MATRIX(shader, mat) \
-       glUniformMatrix3fv(glGetUniformLocation(shader, #mat), 1, 0, YUV::mat)
+       glUniformMatrix3fv(glGetUniformLocation(shader, #mat), 1, 1, YUV::mat)
 #define BC_GL_VECTOR(shader, vec) \
        glUniform3fv(glGetUniformLocation(shader, #vec), 1, YUV::vec)
 
index ece6d088a3710079dad8afd721771c103ec9cb90..417063bded189c06a197c067a1a1e95e5d7f55b2 100644 (file)
@@ -702,8 +702,7 @@ const char* Record::current_mode()
 
 double Record::current_display_position()
 {
-//printf("Record::current_display_position "
-//  _LD " " _LD "\n", total_samples, total_frames)
+//printf("Record::current_display_position "%jd %jd\n", total_samples, total_frames);
        double result = -1.;
        Asset *asset = default_asset;
        if( writing_file ) {
index a09cbad94a434ef910d070915583037b3b06563e..9e51a994b485ebab0486d51ee8aa9586373a8880 100644 (file)
@@ -126,10 +126,8 @@ void Resample::resample_chunk(Samples *input_buffer,
        int num_used;
        int i, j, k;
        double *input = input_buffer->get_data();
-//printf("Resample::resample_chunk %d in_len=" _LD " input_size=%d\n",
-//__LINE__,
-//in_len,
-//input_size);
+//printf("Resample::resample_chunk %d in_len=%jd input_size=%d\n",
+// __LINE__, in_len, input_size);
 
        intratio = (fabs(resample_ratio - floor(.5 + resample_ratio)) < .0001);
        fcn = .90 / resample_ratio;
@@ -273,10 +271,8 @@ int Resample::resample(Samples *output,
        int result = 0;
 
 
-// printf("Resample::resample 1 output_position=" _LD " out_position=" _LD " out_len=" _LD "\n",
-// output_position,
-// out_position,
-// out_len);
+//printf("Resample::resample 1 output_position=%jd out_position=%jd out_len=%jd\n",
+// output_position, out_position, out_len);
 // Changed position
        if(labs(this->output_position - out_position) > 0 ||
                direction != this->direction)
index 2e53c4da4f6415038793af88d6cbc373747c3a15..70138be063718066ce11e5474bbb1849ca1e21ac 100644 (file)
@@ -448,7 +448,7 @@ void ResourceThread::do_video(VResourceThreadItem *item)
 
        if(!temp_picon)
        {
-               temp_picon = new VFrame(source_w, source_h, source_cmodel, 0);
+               temp_picon = new VFrame(0, -1, source_w, source_h, source_cmodel, -1);
        }
 
 // Get temporary to copy cached frame to
index 81537be29f3f9e1ce65397cb531cf277f8705379..e781c0023f335b6e1e14372c48cb7b69eb1626d7 100644 (file)
@@ -676,17 +676,11 @@ void TrackCanvas::test_timer()
 
 void TrackCanvas::draw_indexes(Indexable *indexable)
 {
+       IndexState *index_state = indexable->index_state;
 // Don't redraw raw samples
-       IndexState *index_state = 0;
-       index_state = indexable->index_state;
-
-
        if(index_state->index_zoom > mwindow->edl->local_session->zoom_sample)
                return;
-
-
        draw_resources(0, 1, indexable);
-
        draw_overlays();
        flash(0);
 }
index 9216c2e17ad1a2734b6d5bd6cb89f52a32a5d86e..acc6544f010dd0467b2150b206fd1b38d08a3221 100644 (file)
@@ -506,7 +506,7 @@ void UndoStackItem::set_data(char *data)
                        new_size,
                        &this->data_size,
                        0);
-//printf("UndoStackItem::set_data 2 " _LD "\n", timer.get_difference());
+//printf("UndoStackItem::set_data 2 %jd\n", timer.get_difference());
 
 // Testing
 // FILE *test1 = fopen("/tmp/undo1", "w");
diff --git a/cinelerra-5.1/ffmpeg/audio/h264.mp4 b/cinelerra-5.1/ffmpeg/audio/h264.mp4
new file mode 100644 (file)
index 0000000..7a2d70e
--- /dev/null
@@ -0,0 +1 @@
+mp4 libfdk_aac
index ca4ccd77ac5949020409619de2416377b0fe3125..2a9f34376100bc44390b4a5c1e5175a5fe7fd566 100644 (file)
@@ -1 +1 @@
-h265.mp4
+h264.mp4
diff --git a/cinelerra-5.1/ffmpeg/audio/passes1and2_h264.mp4 b/cinelerra-5.1/ffmpeg/audio/passes1and2_h264.mp4
new file mode 100644 (file)
index 0000000..ab6b0cc
--- /dev/null
@@ -0,0 +1,2 @@
+fmp4 libfdk_aac
+b=128k
diff --git a/cinelerra-5.1/ffmpeg/audio/passes1and2_h265.mp4 b/cinelerra-5.1/ffmpeg/audio/passes1and2_h265.mp4
new file mode 100644 (file)
index 0000000..ab6b0cc
--- /dev/null
@@ -0,0 +1,2 @@
+fmp4 libfdk_aac
+b=128k
diff --git a/cinelerra-5.1/ffmpeg/video/pass1of2_h264.mp4 b/cinelerra-5.1/ffmpeg/video/pass1of2_h264.mp4
new file mode 100644 (file)
index 0000000..85f8f8f
--- /dev/null
@@ -0,0 +1,8 @@
+mp4 libx264
+# pass 1 of 2, you must render the 2nd pass using pass2of2...
+flags +pass1
+passlogfile /tmp/2passes_h264.log
+b=2600k
+# use framerate for 1 keyframe/sec, needed for seeks
+keyint_min=25
+x264opts keyint=25
diff --git a/cinelerra-5.1/ffmpeg/video/pass1of2_h265.mp4 b/cinelerra-5.1/ffmpeg/video/pass1of2_h265.mp4
new file mode 100644 (file)
index 0000000..ba0d4a2
--- /dev/null
@@ -0,0 +1,7 @@
+mp4 libx265
+# Pass 1 of 2, you must next render using pass2of2...
+cin_quality=-1
+b=2600k
+# use framerate for 1 keyframe/sec, needed for seeks
+keyint_min=30
+x265-params=keyint=30:pass=1:stats=/tmp/2passes_h265.log
diff --git a/cinelerra-5.1/ffmpeg/video/pass2of2_h264.mp4 b/cinelerra-5.1/ffmpeg/video/pass2of2_h264.mp4
new file mode 100644 (file)
index 0000000..25c7dd1
--- /dev/null
@@ -0,0 +1,8 @@
+mp4 libx264
+# 2nd pass, you must render first with pass1of2...
+flags +pass2
+passlogfile /tmp/2passes_h264.log
+b=2600k
+# use framerate for 1 keyframe/sec, needed for seeks
+keyint_min=25
+x264opts keyint=25
diff --git a/cinelerra-5.1/ffmpeg/video/pass2of2_h265.mp4 b/cinelerra-5.1/ffmpeg/video/pass2of2_h265.mp4
new file mode 100644 (file)
index 0000000..131865d
--- /dev/null
@@ -0,0 +1,7 @@
+mp4 libx265
+# Pass 2 of 2, you must first render using pass1of2...
+cin_quality=-1
+b=2600k
+# use framerate for 1 keyframe/sec, needed for seeks
+keyint_min=30
+x265-params=keyint=30:pass=2:stats=/tmp/2passes_h265.log
index 5d181696488497b91c093c29a28f74ffab806dd4..e587321d5d347f597e962fe752dccac642d3330f 100644 (file)
@@ -128,7 +128,7 @@ int HSV::hsv_to_yuv(int &y, int &u, int &v, float h, float s, float va, int max)
 YUV YUV::yuv;
 float YUV::yuv_to_rgb_matrix[9];
 float YUV::rgb_to_yuv_matrix[9];
-float YUV::rgb_to_y_vector[3];
+float *const YUV::rgb_to_y_vector = YUV::rgb_to_yuv_matrix;
 
 YUV::YUV()
 {
@@ -225,28 +225,24 @@ void YUV::init(double Kr, double Kb, int mpeg)
                vtor16f, vtog16f, utog16f, utob16f);
 
        rgb_to_yuv_matrix[0] = r_to_y;
-       rgb_to_yuv_matrix[1] = r_to_u;
-       rgb_to_yuv_matrix[2] = r_to_v;
-       rgb_to_yuv_matrix[3] = g_to_y;
+       rgb_to_yuv_matrix[1] = g_to_y;
+       rgb_to_yuv_matrix[2] = b_to_y;
+       rgb_to_yuv_matrix[3] = r_to_u;
        rgb_to_yuv_matrix[4] = g_to_u;
-       rgb_to_yuv_matrix[5] = g_to_v;
-       rgb_to_yuv_matrix[6] = b_to_y;
-       rgb_to_yuv_matrix[7] = b_to_u;
+       rgb_to_yuv_matrix[5] = b_to_u;
+       rgb_to_yuv_matrix[6] = r_to_v;
+       rgb_to_yuv_matrix[7] = g_to_v;
        rgb_to_yuv_matrix[8] = b_to_v;
 
-       rgb_to_y_vector[0] = r_to_y;
-       rgb_to_y_vector[1] = g_to_y;
-       rgb_to_y_vector[2] = b_to_y;
-
        float yscale = 1.f / yrangef;
        yuv_to_rgb_matrix[0] = yscale;
-       yuv_to_rgb_matrix[1] = yscale;
-       yuv_to_rgb_matrix[2] = yscale;
-       yuv_to_rgb_matrix[3] = 0;
+       yuv_to_rgb_matrix[1] = 0;
+       yuv_to_rgb_matrix[2] = v_to_r;
+       yuv_to_rgb_matrix[3] = yscale;
        yuv_to_rgb_matrix[4] = u_to_g;
-       yuv_to_rgb_matrix[5] = u_to_b;
-       yuv_to_rgb_matrix[6] = v_to_r;
-       yuv_to_rgb_matrix[7] = v_to_g;
+       yuv_to_rgb_matrix[5] = v_to_g;
+       yuv_to_rgb_matrix[6] = yscale;
+       yuv_to_rgb_matrix[7] = u_to_b;
        yuv_to_rgb_matrix[8] = 0;
 }
 
index 8687735268ff21b8c0ac7eeb0a665daa94477b02..9226f3a5771d5207cccbc0d5310f0bd85cc1d837 100644 (file)
@@ -188,7 +188,7 @@ public:
        static YUV yuv;
        static float yuv_to_rgb_matrix[9];
        static float rgb_to_yuv_matrix[9];
-       static float rgb_to_y_vector[3];
+       static float *const rgb_to_y_vector;
        inline float get_yminf() { return yminf; }
 
 #define YUV_rgb_to_yuv_8(r,g,b, y,u,v) \
index e8dad7ea1315ee913bb439c355767f4de725dc1b..799041921aad42bed98d9154cc7d67ff95a2b47a 100644 (file)
@@ -280,7 +280,8 @@ int VFrame::reset_parameters(int do_opengl)
        timestamp = -1.;
        is_keyframe = 0;
        draw_point = 0;
-       set_pixel_color(BLACK);
+       pixel_rgb = 0x000000; // BLACK
+       pixel_yuv = 0x008080;
        stipple = 0;
 
        if(do_opengl)
index 3318eaf4230de550b770cf5191dac2a742664950..b8e9253e9e1f042ad9ae4b92ab907f8454325b99 100644 (file)
@@ -91,6 +91,7 @@ Gamma:                Converts the logarithmic colors to linear colors
                using gamma and maximum value.
 Gradient:      Overlays a smooth color gradient on top of every
                video frame.
+HistEq:                Remap colors using blended histogram weights.
 Histogram:     Shows the number of occurrences of each color on a
                histogram plot.
 Histogram Bezier: Uses a Bezier curve (parametric) on the histogram plot.
diff --git a/cinelerra-5.1/picon/cinfinity/histeq.png b/cinelerra-5.1/picon/cinfinity/histeq.png
new file mode 100644 (file)
index 0000000..658d2f3
Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/histeq.png differ
index 39a72d7dbc7044afd3256217b77d65c063528af0..2d4690eaa6cb65b695aa16b2113fad7324898155 100644 (file)
@@ -20,7 +20,7 @@ transforms := 1080to480 1080to540 720to480 lens perspective photoscale \
 
 plugin_dirs += colors
 colors := brightness bluebanana C41 color3way colorbalance huesaturation \
-       gamma gradient histogram histogram_bezier threshold
+       gamma gradient histeq histogram histogram_bezier threshold
 
 plugin_dirs += exotic
 exotic := aging burn dot holo oil edge spherecam
index bf9b83673424e97788bcecbcb6e013b490cf2f03..a492ca869a08c377fa3215bd1ac151737beeb85c 100644 (file)
@@ -67,6 +67,7 @@ DIRS = $(OPENCV_OBJS) \
        gamma \
        gradient \
        graphic \
+       histeq \
        histogram \
        histogram_bezier \
        holo \
diff --git a/cinelerra-5.1/plugins/histeq/.gdb_history b/cinelerra-5.1/plugins/histeq/.gdb_history
new file mode 100644 (file)
index 0000000..ee24cbc
--- /dev/null
@@ -0,0 +1,23 @@
+p /x 0xff*3
+p /x 0xff*3 * 0x55
+p /x 0xff*3 * 0x57
+p /x 0xff*3 * 0x56
+p /x 0x5555*3
+p /x 0xff*3 * 0x5555
+p /x 0xff*3 * 0x5555 /257
+p /x 0xff*3 * 0x5555 /256
+p /x 0xff*3 * 0x5555 /254
+p /x 0xff*3 * 0x5555 /253
+p /x 0xff*3 * 0x5555 /254
+p /x 0xff*3 * 0x5555 /255
+p (766*0x5555)/255
+p /x (766*0x5555)/255
+p /x (0x2fd*0x5555)/255
+0xffff/0x5555
+p (double)0xffff/0x5555
+r
+y
+r
+y
+r
+q
diff --git a/cinelerra-5.1/plugins/histeq/Makefile b/cinelerra-5.1/plugins/histeq/Makefile
new file mode 100644 (file)
index 0000000..a30b327
--- /dev/null
@@ -0,0 +1,10 @@
+include ../../plugin_defs
+
+OBJS = \
+       $(OBJDIR)/histeq.o \
+
+PLUGIN = histeq
+
+include ../../plugin_config
+
+$(OBJDIR)/histeq.o: histeq.C
diff --git a/cinelerra-5.1/plugins/histeq/histeq.C b/cinelerra-5.1/plugins/histeq/histeq.C
new file mode 100644 (file)
index 0000000..a4f647c
--- /dev/null
@@ -0,0 +1,696 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008-2012 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <math.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "histeq.h"
+#include "filexml.h"
+#include "language.h"
+#include "loadbalance.h"
+#include "bccolors.h"
+#include "vframe.h"
+
+class HistEqMain;
+class HistEqEngine;
+class HistEqWindow;
+
+REGISTER_PLUGIN(HistEqMain)
+
+HistEqConfig::HistEqConfig()
+{
+       split = 0;
+       plot = 0;
+       blend = 0.5;
+       gain = 1.0;
+}
+
+HistEqConfig::~HistEqConfig()
+{
+}
+
+void HistEqConfig::copy_from(HistEqConfig &that)
+{
+       split = that.split;
+       plot = that.plot;
+       blend = that.blend;
+       gain = that.gain;
+}
+
+int HistEqConfig::equivalent(HistEqConfig &that)
+{
+       return 1;
+}
+
+void HistEqConfig::interpolate(HistEqConfig &prev, HistEqConfig &next,
+               int64_t prev_frame, int64_t next_frame, int64_t current_frame)
+{
+       copy_from(prev);
+}
+
+
+HistEqWindow::HistEqWindow(HistEqMain *plugin)
+ : PluginClientWindow(plugin, plugin->w, plugin->h, plugin->w, plugin->h, 0)
+{
+       this->plugin = plugin;
+}
+
+HistEqWindow::~HistEqWindow()
+{
+}
+
+
+void HistEqWindow::create_objects()
+{
+       int x = 10, y = 10;
+       int cw = get_w()-2*x, ch = cw*3/4;
+       add_subwindow(canvas = new HistEqCanvas(this, plugin, x, y, cw, ch));
+       y += canvas->get_h() + 10;
+       
+       add_subwindow(split = new HistEqSplit(this, plugin, x, y));
+       y += split->get_h() + 10;
+
+       add_subwindow(plot = new HistEqPlot(this, plugin, x, y));
+       y += plot->get_h() + 10;
+
+       int x1 = x + 60;
+       add_subwindow(new BC_Title(x, y, _("Blend:")));
+       add_subwindow(blend = new HistEqBlend(this, plugin, x1, y));
+       y += blend->get_h() + 10;
+
+       add_subwindow(new BC_Title(x, y, _("Gain:")));
+       add_subwindow(gain = new HistEqGain(this, plugin, x1, y));
+       y += gain->get_h() + 10;
+
+       show_window();
+}
+
+void HistEqWindow::update()
+{
+}
+
+HistEqCanvas::HistEqCanvas(HistEqWindow *gui, HistEqMain *plugin,
+                int x, int y, int w, int h)
+ : BC_SubWindow(x, y, w, h, BLACK)
+{
+        this->gui = gui;
+        this->plugin = plugin;
+}
+void HistEqCanvas::clear()
+{
+       clear_box(0,0, get_w(),get_h());
+}
+
+void HistEqCanvas::draw_bins(HistEqMain *plugin)
+{
+       set_color(GREEN);
+       int *data = plugin->bins;
+       int n = plugin->binsz, max = 0;
+       for( int i=0; i<n; ++i )
+               if( max < data[i] ) max = data[i];
+       double lmax = log(max);
+       int cw = get_w(), ch = get_h();
+       int x0 = 0, x = 0;
+       while( x < cw ) {
+               int mx = data[x0];
+               int x1 = (n * ++x) / cw;
+               for( int i=x0; ++i<x1; ) {
+                       int m = data[i];
+                       if( m > mx ) mx = m;
+               }
+               double lmx = mx>0 ? log(mx) : 0;
+               int y1 = ch * (1 - lmx/lmax);
+               draw_line(x,0, x,y1);
+               x0 = x1;
+       }
+}
+
+void HistEqCanvas::draw_wts(HistEqMain *plugin)
+{
+       float *wts = plugin->wts;
+       int n = plugin->binsz;
+       set_color(BLUE);
+       int cw1 = get_w()-1, ch1 = get_h()-1;
+       float g0 = plugin->config.gain, g1 = 1-g0;
+       int x1 = 0, y1 = ch1;
+       while( x1 < cw1 ) {
+               int x0 = x1++, y0 = y1;
+               int is = (n * x1) / cw1;
+               float fy = wts[is]*g0 + ((float)x1/cw1)*g1;
+               y1 = (1-fy) * ch1;
+               draw_line(x0,y0, x1,y1);
+       }
+}
+
+void HistEqCanvas::draw_reg(HistEqMain *plugin)
+{
+       set_color(WHITE);
+       int cw1 = get_w()-1, ch1 = get_h()-1;
+       float g0 = plugin->config.gain, g1 = 1-g0;
+       int x0 = 0, x1 = plugin->binsz-1;
+       double a = plugin->a, b = plugin->b;
+       float fy0 = (a*x0 + b)*g0 + 0*g1;
+       float fy1 = (a*x1 + b)*g0 + 1*g1;
+       int y0 = (1 - fy0) * ch1;
+       int y1 = (1 - fy1) * ch1;
+       draw_line(0,y0, cw1,y1);
+}
+
+void HistEqCanvas::draw_lut(HistEqMain *plugin)
+{
+       int *lut = plugin->lut;
+       int n = plugin->lutsz-1;
+       double s = 1. / n;
+       set_color(RED);
+       int cw1 = get_w()-1, ch1 = get_h()-1;
+       int x1 = 0, y1 = ch1;
+       while( x1 < cw1 ) {
+               int x0 = x1++, y0 = y1;
+               int is = (n * x1) / cw1;
+               y1 = (1-s*lut[is]) * ch1;
+               draw_line(x0,y0, x1,y1);
+       }
+}
+
+void HistEqCanvas::update(HistEqMain *plugin)
+{
+       clear();
+       draw_bins(plugin);
+       draw_wts(plugin);
+       draw_reg(plugin);
+       draw_lut(plugin);
+       flash();
+}
+
+HistEqSplit::HistEqSplit(HistEqWindow *gui, HistEqMain *plugin, int x, int y)
+ : BC_CheckBox(x, y, plugin->config.split, _("Split output"))
+{
+        this->gui = gui;
+        this->plugin = plugin;
+}
+HistEqSplit::~HistEqSplit()
+{
+}
+
+int HistEqSplit::handle_event()
+{
+        plugin->config.split = get_value();
+        plugin->send_configure_change();
+        return 1;
+}
+
+HistEqPlot::HistEqPlot(HistEqWindow *gui, HistEqMain *plugin, int x, int y)
+ : BC_CheckBox(x, y, plugin->config.plot, _("Plot bins/lut"))
+{
+        this->gui = gui;
+        this->plugin = plugin;
+}
+HistEqPlot::~HistEqPlot()
+{
+}
+
+int HistEqPlot::handle_event()
+{
+        plugin->config.plot = get_value();
+        plugin->send_configure_change();
+        return 1;
+}
+
+HistEqBlend::HistEqBlend(HistEqWindow *gui, HistEqMain *plugin, int x, int y)
+ : BC_FSlider(x, y, 0, 150, 200, 0, 1.0, plugin->config.blend, 0)
+{
+        this->gui = gui;
+        this->plugin = plugin;
+        set_precision(0.01);
+}
+HistEqBlend::~HistEqBlend()
+{
+}
+
+int HistEqBlend::handle_event()
+{
+        plugin->config.blend = get_value();
+        plugin->send_configure_change();
+        return 1;
+}
+
+
+HistEqGain::HistEqGain(HistEqWindow *gui, HistEqMain *plugin, int x, int y)
+ : BC_FSlider(x, y, 0, 150, 200, 0, 1.0, plugin->config.gain, 0)
+{
+        this->gui = gui;
+        this->plugin = plugin;
+        set_precision(0.01);
+}
+HistEqGain::~HistEqGain()
+{
+}
+
+int HistEqGain::handle_event()
+{
+        plugin->config.gain = get_value();
+        plugin->send_configure_change();
+        return 1;
+}
+
+
+HistEqMain::HistEqMain(PluginServer *server)
+ : PluginVClient(server)
+{
+       w = 300;  h = 375;
+       engine = 0;
+       sz = 0;
+       binsz = bsz = 0;  bins = 0;
+       lutsz = lsz = 0;  lut = 0;
+       wsz = 0;          wts = 0;
+       a = 0;  b = 0;
+}
+
+HistEqMain::~HistEqMain()
+{
+       delete engine;
+       delete [] bins;
+       delete [] lut;
+       delete [] wts;
+}
+
+const char* HistEqMain::plugin_title() { return _("HistEq"); }
+int HistEqMain::is_realtime() { return 1; }
+
+
+NEW_WINDOW_MACRO(HistEqMain, HistEqWindow)
+
+LOAD_CONFIGURATION_MACRO(HistEqMain, HistEqConfig)
+
+void HistEqMain::update_gui()
+{
+       if( !thread ) return;
+       if( !load_configuration() ) return;
+       ((HistEqWindow*)thread->window)->lock_window("HistEqMain::update_gui");
+       HistEqWindow* gui = (HistEqWindow*)thread->window;
+       gui->update();
+       gui->unlock_window();
+}
+
+void HistEqMain::save_data(KeyFrame *keyframe)
+{
+       FileXML output;
+       output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
+       output.tag.set_title("HISTEQ");
+       output.tag.set_property("W", w);
+       output.tag.set_property("H", h);
+       output.tag.set_property("SPLIT", config.split);
+       output.tag.set_property("PLOT", config.plot);
+       output.tag.set_property("BLEND", config.blend);
+       output.tag.set_property("GAIN", config.gain);
+       output.append_tag();
+       output.tag.set_title("/HISTEQ");
+       output.append_tag();
+       output.append_newline();
+       output.terminate_string();
+}
+
+void HistEqMain::read_data(KeyFrame *keyframe)
+{
+       FileXML input;
+       input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
+       int result = 0;
+       while( !(result=input.read_tag()) ) {
+               if( input.tag.title_is("HISTEQ") ) {
+                       if(is_defaults()) {
+                               w = input.tag.get_property("W", w);
+                               h = input.tag.get_property("H", h);
+                       }
+                       config.split = input.tag.get_property("SPLIT", config.split);
+                       config.plot = input.tag.get_property("PLOT", config.plot);
+                       config.blend = input.tag.get_property("BLEND", config.blend);
+                       config.gain = input.tag.get_property("GAIN", config.gain);
+               }
+       }
+}
+
+void HistEqMain::render_gui(void *data)
+{
+       if( !thread ) return;
+       ((HistEqWindow*)thread->window)->lock_window("HistEqMain::render_gui 1");
+       HistEqWindow *gui = (HistEqWindow*)thread->window;
+       gui->canvas->update((HistEqMain *)data);
+       gui->unlock_window();
+}
+
+// regression line
+static void fit(float *dat, int n, double &a, double &b)
+{
+       double sy = 0;
+       for( int i=0; i<n; ++i ) sy += dat[i];
+       double s = 0, mx = (n-1)/2., my = sy / n;
+       for( int i=0; i<n; ++i ) s += (i-mx) * dat[i];
+       double m = (n+1)/2;
+       double ss = 2. * ((m+1)*m*(m-1)/3. + m*(m-1)/2.);
+       a = s / ss;
+       b = my - mx*a;
+}
+
+int HistEqMain::process_buffer(VFrame *frame, int64_t start_position, double frame_rate)
+{
+       load_configuration();
+       read_frame(frame, 0, start_position, frame_rate, 0);
+       this->input = this->output = frame;
+
+       int colormodel = frame->get_color_model();
+       lutsz = 0x10000;
+       binsz = (3*0xffff) + 1;
+       switch( colormodel ) {
+       case BC_RGB888:
+       case BC_RGBA8888:
+               binsz = (3*0xff) + 1;
+               lutsz = 0x100;
+               break;
+       case BC_RGB_FLOAT:
+       case BC_RGBA_FLOAT:
+               binsz = (3*0x5555) + 1;
+               break;
+       }
+       if( binsz != bsz ) { delete bins;  bins = 0;  bsz = 0; }
+       if( !bins ) bins = new int[bsz = binsz];
+       if( binsz+1 != wsz ) { delete wts;   wts = 0;   wsz = 0; }
+       if( !wts ) wts = new float[wsz = binsz+1];
+       if( lutsz != lsz ) { delete lut;   lut = 0;   lsz = 0; }
+       if( !lut  ) lut  = new int[lsz = lutsz];
+
+       if(!engine) engine = new HistEqEngine(this,
+               get_project_smp() + 1, get_project_smp() + 1);
+       engine->process_packages(HistEqEngine::HISTEQ, frame);
+
+// sum the results, not all clients may have run
+       memset(bins, 0, binsz*sizeof(bins[0]));
+       for( int i=0, n=engine->get_total_clients(); i<n; ++i ) {
+               HistEqUnit *unit = (HistEqUnit*)engine->get_client(i);
+               if( !unit->valid ) continue;
+               for( int i=0; i<binsz; ++i ) bins[i] += unit->bins[i];
+       }
+
+// Remove top and bottom from calculations.
+//  Doesn't work in high precision colormodels.
+       int n = frame->get_w() * frame->get_h();
+       int binsz1 = binsz-1, lutsz1 = lutsz-1;
+       n -= bins[0];       bins[0] = 0;
+       n -= bins[binsz1];  bins[binsz1] = 0;
+       sz = n;
+
+// integrate and normalize
+       for( int i=0,t=0; i<binsz; ++i ) { t += bins[i];  wts[i] = (float)t / n; }
+       wts[binsz] = 1.f;
+// exclude margins (+-2%)
+       float fmn =  0.02f, fmx = 1. - fmn;
+       int mn = 0;    while( mn < binsz && wts[mn] < fmn ) ++mn;
+       int mx = binsz; while( mx > mn  && wts[mx-1] > fmx ) --mx;
+       n = mx-mn+1;  fit(&wts[mn], n, a, b);
+// home y intercept
+       b -= a * mn;
+       if( (a*n + b) < 1 ) a = (1 - b) / n;
+       if( b > 0 ) { a = (a*n + b) / n;  b = 0; }
+       double blend = config.blend, blend1 = 1-blend;
+       double r = (double)binsz1 / lutsz1;
+       float g0 = config.gain, g1 = 1-g0;
+       for( int i=0; i<lutsz; ++i ) {
+               double is = i * r;
+               int is0 = is, is1 = is0+1;
+               double s0 = is-is0, s1 = 1-s0;
+// piecewise linear interp btwn wts[is]..wts[is+1]
+               float u = wts[is0]*s0 + wts[is1]*s1;
+// regression line
+               float v = is*a + b;
+// blend bins eq with linear regression, add scalar gain
+               float t = u*blend + v*blend1;
+               int iy = (t*lutsz1)*g0 + i*g1;
+               lut[i] = bclip(iy, 0, lutsz1);
+       }
+       if( config.plot && gui_open() )
+               send_render_gui(this);
+
+       engine->process_packages(HistEqEngine::APPLY, frame);
+       return 0;
+}
+
+HistEqPackage::HistEqPackage()
+ : LoadPackage()
+{
+}
+
+HistEqUnit::HistEqUnit(HistEqEngine *server, HistEqMain *plugin)
+ : LoadClient(server)
+{
+       this->plugin = plugin;
+       this->server = server;
+       bins = 0;
+       binsz = 0;
+       valid = 0;
+}
+
+HistEqUnit::~HistEqUnit()
+{
+       delete [] bins;
+}
+
+void HistEqUnit::process_package(LoadPackage *package)
+{
+       if( binsz != plugin->binsz ) {
+               delete bins;  bins = 0;  binsz = 0;
+       }
+       if( !bins ) {
+               bins = new int[binsz = plugin->binsz];
+       }
+       if( !valid ) {
+               valid = 1;
+               bzero(bins, binsz*sizeof(bins[0]));
+       }
+
+       HistEqPackage *pkg = (HistEqPackage*)package;
+       switch( server->operation ) {
+       case HistEqEngine::HISTEQ: {
+
+#define HISTEQ_HEAD(type) { \
+       type **rows = (type**)data->get_rows(); \
+       for( int iy=pkg->y0; iy<pkg->y1; ++iy ) { \
+               type *row = rows[iy]; \
+               for( int ix=0; ix<w; ++ix ) {
+
+#define HISTEQ_TAIL(components) \
+                       ++bins[i]; \
+                       row += components; \
+               } \
+       } \
+}
+               VFrame *data = server->data;
+               int colormodel = data->get_color_model();
+               int w = data->get_w(), comps = BC_CModels::components(colormodel);
+
+               switch( colormodel ) {
+               case BC_RGB888:
+               case BC_RGBA8888:
+                       HISTEQ_HEAD(unsigned char)
+                       int r = row[0], g = row[1], b = row[2];
+                       int i = r + g + b;
+                       HISTEQ_TAIL(comps)
+                       break;
+               case BC_RGB161616:
+               case BC_RGBA16161616:
+                       HISTEQ_HEAD(uint16_t)
+                       int r = row[0], g = row[1], b = row[2];
+                       int i = r + g + b;
+                       HISTEQ_TAIL(comps)
+                       break;
+               case BC_RGB_FLOAT:
+               case BC_RGBA_FLOAT:
+                       HISTEQ_HEAD(float)
+                       int r = (int)(row[0] * 0x5555);
+                       int g = (int)(row[1] * 0x5555);
+                       int b = (int)(row[2] * 0x5555);
+                       int i = r + g + b;  bclamp(i, 0,0xffff);
+                       HISTEQ_TAIL(comps)
+                       break;
+               case BC_YUV888:
+               case BC_YUVA8888:
+                       HISTEQ_HEAD(unsigned char)
+                       int y = (row[0]<<8) + row[0];
+                       int u = (row[1]<<8) + row[1];
+                       int v = (row[2]<<8) + row[2];
+                       int r, g, b;
+                       YUV::yuv.yuv_to_rgb_16(r, g, b, y, u, v);
+                       int i = r + g + b;
+                       HISTEQ_TAIL(comps)
+                       break;
+               case BC_YUV161616:
+               case BC_YUVA16161616:
+                       HISTEQ_HEAD(uint16_t)
+                       int r, g, b;
+                       YUV::yuv.yuv_to_rgb_16(r, g, b, row[0], row[1], row[2]);
+                       int i = r + g + b;
+                       HISTEQ_TAIL(comps)
+                       break;
+               }
+               break; }
+       case HistEqEngine::APPLY: {
+#define PROCESS_RGB(type, components, max) { \
+       type **rows = (type**)input->get_rows(); \
+       for( int iy=pkg->y0; iy<pkg->y1; ++iy ) { \
+               type *row = rows[iy]; \
+               int x1 = !split ? w : (iy * w) / h; \
+               for( int x=0; x<x1; ++x ) { \
+                       int r = row[0], g = row[1], b = row[2]; \
+                       row[0] = lut[r];  row[1] = lut[g];  row[2] = lut[b]; \
+                       row += components; \
+               } \
+       } \
+}
+#define PROCESS_YUV(type, components, max) { \
+       type **rows = (type**)input->get_rows(); \
+       for( int iy=pkg->y0; iy<pkg->y1; ++iy ) { \
+               type *row = rows[iy]; \
+               int x1 = !split ? w : (iy * w) / h; \
+               for( int ix=0; ix<x1; ++ix ) { \
+                       int r, g, b, y, u, v; \
+                       if( max == 0xff ) { \
+                               y = (row[0] << 8) | row[0]; \
+                               u = (row[1] << 8) | row[1]; \
+                               v = (row[2] << 8) | row[2]; \
+                       } \
+                       else { \
+                               y = row[0]; u = row[1]; v = row[2]; \
+                       } \
+                       YUV::yuv.yuv_to_rgb_16(r, g, b, y, u, v); \
+                       YUV::yuv.rgb_to_yuv_16(lut[r], lut[g], lut[b], y, u, v); \
+                       if( max == 0xff ) { \
+                               row[0] = y >> 8; \
+                               row[1] = u >> 8; \
+                               row[2] = v >> 8; \
+                       } \
+                       else { \
+                               row[0] = y; row[1] = u; row[2] = v; \
+                       } \
+                       row += components; \
+               } \
+       } \
+}
+#define PROCESS_FLOAT(components) { \
+       float **rows = (float**)input->get_rows(); \
+       for( int iy=pkg->y0; iy<pkg->y1; ++iy ) { \
+               float *row = rows[iy]; \
+               int x1 = !split ? w : (iy * w) / h; \
+               for( int ix=0; ix<x1; ++ix ) { \
+                       int r = row[0]*0xffff, g = row[1]*0xffff, b = row[2]*0xffff; \
+                       bclamp(r, 0,0xffff);  bclamp(g, 0,0xffff);  bclamp(b, 0,0xffff); \
+                       row[0] = (float)lut[r] / 0xffff; \
+                       row[1] = (float)lut[g] / 0xffff; \
+                       row[2] = (float)lut[b] / 0xffff; \
+                       row += components; \
+               } \
+       } \
+}
+
+               VFrame *input = plugin->input;
+               int w = input->get_w(), h = input->get_h();
+               int split = plugin->config.split;
+               int *lut = plugin->lut;
+
+               switch(input->get_color_model()) {
+               case BC_RGB888:
+                       PROCESS_RGB(unsigned char, 3, 0xff)
+                       break;
+               case BC_RGBA8888:
+                       PROCESS_RGB(unsigned char, 4, 0xff)
+                       break;
+               case BC_RGB161616:
+                       PROCESS_RGB(uint16_t, 3, 0xffff)
+                       break;
+               case BC_RGBA16161616:
+                       PROCESS_RGB(uint16_t, 4, 0xffff)
+                       break;
+               case BC_RGB_FLOAT:
+                       PROCESS_FLOAT(3);
+                       break;
+               case BC_RGBA_FLOAT:
+                       PROCESS_FLOAT(4);
+                       break;
+               case BC_YUV888:
+                       PROCESS_YUV(unsigned char, 3, 0xff)
+                       break;
+               case BC_YUVA8888:
+                       PROCESS_YUV(unsigned char, 4, 0xff)
+                       break;
+               case BC_YUV161616:
+                       PROCESS_YUV(uint16_t, 3, 0xffff)
+                       break;
+               case BC_YUVA16161616:
+                       PROCESS_YUV(uint16_t, 4, 0xffff)
+                       break;
+               }
+               break; }
+       }
+}
+
+HistEqEngine::HistEqEngine(HistEqMain *plugin,
+       int total_clients,
+       int total_packages)
+ : LoadServer(total_clients, total_packages)
+{
+       this->plugin = plugin;
+}
+
+void HistEqEngine::init_packages()
+{
+       int h = data->get_h();
+       int y0 = 0;
+
+       for( int i=0, n=get_total_packages(); i<n; ) {
+               HistEqPackage *pkg = (HistEqPackage *)get_package(i);
+               int y1 = ++i * h / n;
+               pkg->y0 = y0;  pkg->y1 = y1;
+               y0 = y1;
+       }
+       for( int i=0, n=get_total_clients(); i<n; ++i ) {
+               HistEqUnit *unit = (HistEqUnit*)get_client(i);
+               unit->valid = 0; // set if unit runs
+       }
+}
+
+LoadClient* HistEqEngine::new_client()
+{
+       return new HistEqUnit(this, plugin);
+}
+
+LoadPackage* HistEqEngine::new_package()
+{
+       return new HistEqPackage;
+}
+
+void HistEqEngine::process_packages(int operation, VFrame *data)
+{
+       this->data = data;
+       this->operation = operation;
+
+       LoadServer::process_packages();
+}
+
+
diff --git a/cinelerra-5.1/plugins/histeq/histeq.h b/cinelerra-5.1/plugins/histeq/histeq.h
new file mode 100644 (file)
index 0000000..f8da016
--- /dev/null
@@ -0,0 +1,184 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef HISTOGRAM_H
+#define HISTOGRAM_H
+
+
+#include "histeq.inc"
+#include "loadbalance.h"
+#include "bccolors.h"
+#include "pluginvclient.h"
+
+class HistEqConfig {
+public:
+       HistEqConfig();
+       ~HistEqConfig();
+
+       int split;
+       int plot;
+       float blend;
+       float gain;
+
+       void copy_from(HistEqConfig &that);
+       int equivalent(HistEqConfig &that);
+       void interpolate(HistEqConfig &prev, HistEqConfig &next,
+               int64_t prev_frame, int64_t next_frame, int64_t current_frame);
+};
+
+class HistEqSplit : public BC_CheckBox
+{
+public:
+       HistEqSplit(HistEqWindow *gui, HistEqMain *plugin, int x, int y);
+       ~HistEqSplit();
+       int handle_event();
+
+       HistEqWindow *gui;
+       HistEqMain *plugin;
+};
+
+class HistEqPlot : public BC_CheckBox
+{
+public:
+       HistEqPlot(HistEqWindow *gui, HistEqMain *plugin, int x, int y);
+       ~HistEqPlot();
+       int handle_event();
+
+       HistEqWindow *gui;
+       HistEqMain *plugin;
+};
+
+class HistEqBlend : public BC_FSlider
+{
+public:
+       HistEqBlend(HistEqWindow *gui, HistEqMain *plugin, int x, int y);
+       ~HistEqBlend();
+       int handle_event();
+
+       HistEqWindow *gui;
+       HistEqMain *plugin;
+};
+
+class HistEqGain : public BC_FSlider
+{
+public:
+       HistEqGain(HistEqWindow *gui, HistEqMain *plugin, int x, int y);
+       ~HistEqGain();
+       int handle_event();
+
+       HistEqWindow *gui;
+       HistEqMain *plugin;
+};
+
+class HistEqCanvas : public BC_SubWindow
+{
+public:
+        HistEqCanvas(HistEqWindow *gui, HistEqMain *plugin,
+                int x, int y, int w, int h);
+       void clear();
+       void draw_bins(HistEqMain *plugin);
+       void draw_wts(HistEqMain *plugin);
+       void draw_reg(HistEqMain *plugin);
+       void draw_lut(HistEqMain *plugin);
+       void update(HistEqMain *plugin);
+
+        HistEqMain *plugin;
+        HistEqWindow *gui;
+};
+
+class HistEqWindow : public PluginClientWindow
+{
+public:
+       HistEqWindow(HistEqMain *plugin);
+       ~HistEqWindow();
+
+       HistEqMain *plugin;
+       HistEqSplit *split;
+       HistEqPlot *plot;
+       HistEqBlend *blend;
+       HistEqGain *gain;
+       HistEqCanvas *canvas;
+
+       void create_objects();
+       void update();
+};
+
+class HistEqMain : public PluginVClient
+{
+public:
+       HistEqMain(PluginServer *server);
+       ~HistEqMain();
+
+       int process_buffer(VFrame *frame, int64_t start_position, double frame_rate);
+       int is_realtime();
+       void save_data(KeyFrame *keyframe);
+       void read_data(KeyFrame *keyframe);
+       void update_gui();
+
+       void render_gui(void *data);
+
+       PLUGIN_CLASS_MEMBERS(HistEqConfig)
+
+       VFrame *input, *output;
+       HistEqEngine *engine;
+       int w, h;
+       int sz;
+       double a, b;
+       int binsz, bsz, *bins;
+       int lutsz, lsz, *lut;
+       int wsz;  float *wts;
+};
+
+class HistEqPackage : public LoadPackage
+{
+public:
+       HistEqPackage();
+       int y0, y1;
+};
+
+class HistEqUnit : public LoadClient
+{
+public:
+       HistEqUnit(HistEqEngine *server, HistEqMain *plugin);
+       ~HistEqUnit();
+       void process_package(LoadPackage *package);
+       HistEqEngine *server;
+       HistEqMain *plugin;
+       int valid;
+       int binsz, *bins;
+};
+
+class HistEqEngine : public LoadServer
+{
+public:
+       HistEqEngine(HistEqMain *plugin, int total_clients, int total_packages);
+       void process_packages(int operation, VFrame *data);
+       void init_packages();
+       LoadClient* new_client();
+       LoadPackage* new_package();
+       HistEqMain *plugin;
+       int operation;
+
+       enum { HISTEQ, APPLY };
+       VFrame *data;
+};
+
+#endif
diff --git a/cinelerra-5.1/plugins/histeq/histeq.inc b/cinelerra-5.1/plugins/histeq/histeq.inc
new file mode 100644 (file)
index 0000000..ae7ae3c
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __HISTEQ_H__
+#define __HISTEQ_H__
+
+class HistEqConfig;
+class HistEqSplit;
+class HistEqBlend;
+class HistEqGain;
+class HistEqWindow;
+class HistEqMain;
+class HistEqPackage;
+class HistEqUnit;
+class HistEqEngine;
+
+#endif
index 996edac9f0604549c8e6a444e67e72ead8c84b62..183d5c0e7e3df7c2dbf1d35695b24b1e26de40d3 100644 (file)
@@ -677,9 +677,6 @@ int HistogramMain::handle_opengl()
        if(!strcmp(get_output()->get_prev_effect(0), _("Color Balance")))
                aggregate_colorbalance = 1;
 
-       if( BC_CModels::is_yuv(get_output()->get_color_model()) )
-               shader_stack[current_shader++] = bc_gl_colors;
-
 // The order of processing is fixed by this sequence
        if(aggregate_interpolation)
                INTERPOLATE_COMPILE(shader_stack, current_shader);