add VFrameJpeg for shapewipe shapes, switch to jpeg for shapes, cam/prjr x,y,z range...
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / shapewipe / shapewipe.C
index ca675e2d14fc2107d561e8877f6d581073b39fe8..a0128fea35e538200dc9eeff5a97d31fdef62c3b 100644 (file)
@@ -34,6 +34,7 @@
 #include <png.h>
 #include <math.h>
 #include <stdint.h>
+#include <fcntl.h>
 #include <string.h>
 
 #define SHAPE_SEARCHPATH "/shapes"
@@ -346,8 +347,6 @@ ShapeWipeMain::ShapeWipeMain(PluginServer *server)
        current_filename[0] = '\0';
        current_name[0] = 0;
        pattern_image = 0;
-       min_value = 255;
-       max_value = 0;
        last_preserve_aspect = 0;
        shapes_initialized = 0;
        shape_paths.set_array_delete();
@@ -381,7 +380,7 @@ void ShapeWipeMain::init_shapes()
 {
        if( !shapes_initialized ) {
                FileSystem fs;
-               fs.set_filter("*.png");
+               fs.set_filter("[*.png][*.jpg]");
                char shape_path[BCTEXTLEN];
                sprintf(shape_path, "%s%s", get_plugin_dir(), SHAPE_SEARCHPATH);
                fs.update(shape_path);
@@ -401,7 +400,6 @@ void ShapeWipeMain::init_shapes()
        }
 }
 
-
 int ShapeWipeMain::load_configuration()
 {
        read_data(get_prev_keyframe(get_source_position()));
@@ -409,89 +407,37 @@ int ShapeWipeMain::load_configuration()
 }
 
 int ShapeWipeMain::read_pattern_image(char *shape_name,
-               int new_frame_width, int new_frame_height)
-{
-       png_byte header[8];
-       int is_png;
-       int row, col;
-       int pixel_width;
-       unsigned char value;
-       png_uint_32 width;
-       png_uint_32 height;
-       png_byte color_type;
-       png_byte bit_depth;
-       png_structp png_ptr = 0;
-       png_infop info_ptr = 0;
-       png_infop end_info = 0;
-       png_bytep *image = 0;
-       FILE *fp = 0;
-       frame_width = new_frame_width;
-       frame_height = new_frame_height;
-       int ret = 0;
-
+               int frame_width, int frame_height)
+{
+       VFrame *pattern = 0;
+       int ret = 0, fd = -1;
+       int is_png = 0;
+       unsigned char header[10];
 // Convert name to filename
-       int k = shape_paths.size();
+       int k = shape_paths.size(), hsz = sizeof(header);
        while( --k>=0 && strcmp(shape_titles[k], shape_name) );
        if( k < 0 ) ret = 1;
        if( !ret ) {
                strcpy(current_filename, shape_paths[k]);
-               fp = fopen(current_filename, "rb");
-               if( !fp ) ret = 1;
-       }
-       if( !ret ) {
-               fread(header, 1, 8, fp);
-               is_png = !png_sig_cmp(header, 0, 8);
-               if( !is_png ) ret = 1;
+               fd = ::open(current_filename, O_RDONLY);
+               if( fd < 0 || read(fd,header,hsz) != hsz ) ret = 1;
        }
        if( !ret ) {
-               png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
-               if( !png_ptr ) ret = 1;
+               is_png = !png_sig_cmp(header, 0, hsz);
+               if( !is_png && strncmp("JFIF", (char*)header+6, 4) ) ret = 1;
        }
        if( !ret ) {
-               /* Tell libpng we already checked the first 8 bytes */
-               png_set_sig_bytes(png_ptr, 8);
-               info_ptr = png_create_info_struct(png_ptr);
-               if( !info_ptr ) ret = 1;
+               lseek(fd, 0, SEEK_SET);
+               pattern = is_png ?
+                       VFramePng::vframe_png(fd, 1, 1) :
+                       VFrameJpeg::vframe_jpeg(fd, 1, 1, BC_GREY8);
+               if( !pattern ) ret = 1;
        }
-       if( !ret ) {
-               end_info = png_create_info_struct(png_ptr);
-               if( !end_info ) ret = 1;
+       if( fd >= 0 ) {
+               close(fd);  fd = -1;
        }
        if( !ret ) {
-               png_init_io(png_ptr, fp);
-               png_read_info(png_ptr, info_ptr);
-
-               color_type = png_get_color_type(png_ptr, info_ptr);
-               bit_depth = png_get_bit_depth(png_ptr, info_ptr);
-               width  = png_get_image_width (png_ptr, info_ptr);
-               height = png_get_image_height(png_ptr, info_ptr);
-
-               /* Skip the alpha channel if present
-               * stripping alpha currently doesn't work in conjunction with
-               * converting to grayscale in libpng */
-               pixel_width = color_type & PNG_COLOR_MASK_ALPHA ? 2 : 1;
-               /* Convert 16 bit data to 8 bit */
-               if( bit_depth == 16 ) png_set_strip_16(png_ptr);
-               /* Expand to 1 pixel per byte if necessary */
-               if( bit_depth < 8 ) png_set_packing(png_ptr);
-
-               /* Convert to grayscale */
-               if( color_type == PNG_COLOR_TYPE_RGB ||
-                   color_type == PNG_COLOR_TYPE_RGB_ALPHA )
-                       png_set_rgb_to_gray_fixed(png_ptr, 1, -1, -1);
-
-               /* Allocate memory to hold the original png image */
-               image = (png_bytep*)new png_bytep[height];
-               for( row=0; row<(int)height; ++row )
-                       image[row] = new png_byte[width*pixel_width];
-
-               /* Allocate memory for the pattern image that will actually be
-               * used for the wipe */
-               pattern_image = new  unsigned char*[frame_height];
-
-               png_read_image(png_ptr, image);
-               png_read_end(png_ptr, end_info);
-
+               int width = pattern->get_w(), height = pattern->get_h();
                double row_factor, col_factor;
                double row_offset = 0.5, col_offset = 0.5;      // for rounding
 
@@ -514,39 +460,41 @@ int ShapeWipeMain::read_pattern_image(char *shape_name,
                        row_factor = (double)(height-1)/(double)(frame_height-1);
                        col_factor = (double)(width-1)/(double)(frame_width-1);
                }
+               int out_w = width * col_factor, out_h = height * row_factor;
+               if( out_w != width || out_h != height ) {
+                       VFrame *new_pattern = new VFrame(frame_width, frame_height, BC_GREY8);
+                       new_pattern->transfer_from(pattern, 0, col_offset,row_offset,
+                               frame_width*col_factor, frame_height*row_factor);
+                       delete pattern;  pattern = new_pattern;
+               }
+               unsigned char **rows = pattern->get_rows();
+               unsigned char min = 0xff, max = 0x00;
                // first, determine range min..max
                for( int y=0; y<frame_height; ++y ) {
-                       row = (int)(row_factor*y + row_offset);
+                       unsigned char *row = rows[y];
                        for( int x=0; x<frame_width; ++x ) {
-                               col = (int)(col_factor*x + col_offset)*pixel_width;
-                               value = image[row][col];
-                               if( value < min_value ) min_value = value;
-                               if( value > max_value ) max_value = value;
+                               unsigned char value = row[x];
+                               if( value < min ) min = value;
+                               if( value > max ) max = value;
                        }
                }
-               int range = max_value - min_value;
+               if( min > max ) min = max;
+               int range = max - min;
                if( !range ) range = 1;
+               pattern_image = new  unsigned char*[frame_height];
                // scale to fade normalized pattern_image
                for( int y=0; y<frame_height; ++y ) {
-                       row = (int)(row_factor*y + row_offset);
+                       unsigned char *row = rows[y];
                        pattern_image[y] = new unsigned char[frame_width];
                        for( int x=0; x<frame_width; ++x ) {
-                               col = (int)(col_factor*x + col_offset)*pixel_width;
-                               value = image[row][col];
-                               pattern_image[y][x] = 0xff*(value - min_value) / range;
+                               unsigned char value = row[x];
+                               pattern_image[y][x] = 0xff*(value-min) / range;
                        }
                }
+               this->frame_width = frame_width;
+               this->frame_height = frame_height;
        }
 
-       if( png_ptr || info_ptr || end_info )
-               png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
-       if( fp )
-               fclose(fp);
-       if( image ) {
-               for( row=0; row<(int)height; ++row )
-                       delete [] image[row];
-               delete [] image;
-       }
        return ret;
 }
 
@@ -556,8 +504,6 @@ void ShapeWipeMain::reset_pattern_image()
                for( int y=0; y<frame_height; ++y )
                        delete [] pattern_image[y];
                delete [] pattern_image;  pattern_image = 0;
-               min_value = 255;
-               max_value = 0;  // updated in read_pattern_image
        }
 }
 
@@ -565,20 +511,40 @@ void ShapeWipeMain::reset_pattern_image()
        float scale = feather ? 1/feather : 0xff; \
        type  **in_rows = (type**)input->get_rows(); \
        type **out_rows = (type**)output->get_rows(); \
-       for( int y=y1; y<y2; ++y ) { \
-               type *in_row = (type*) in_rows[y]; \
-               type *out_row = (type*)out_rows[y]; \
-               unsigned char *pattern_row = pattern_image[y]; \
-               for( int x=0; x<w; ++x ) { \
-                       tmp_type d = (pattern_row[x] - threshold) * scale; \
-                       if( d > 0xff ) d = 0xff; \
-                       else if( d < -0xff ) d = -0xff; \
-                       tmp_type a = (d + 0xff) / 2, b = 0xff - a; \
-                       for( int i=0; i<components; ++i ) { \
-                               type ic = in_row[i], oc = out_row[i]; \
-                               out_row[i] = (ic * a + oc * b) / 0xff; \
+       if( !dir ) { \
+               for( int y=y1; y<y2; ++y ) { \
+                       type *in_row = (type*) in_rows[y]; \
+                       type *out_row = (type*)out_rows[y]; \
+                       unsigned char *pattern_row = pattern_image[y]; \
+                       for( int x=0; x<w; ++x ) { \
+                               tmp_type d = (pattern_row[x] - threshold) * scale; \
+                               if( d > 0xff ) d = 0xff; \
+                               else if( d < -0xff ) d = -0xff; \
+                               tmp_type a = (d + 0xff) / 2, b = 0xff - a; \
+                               for( int i=0; i<components; ++i ) { \
+                                       type ic = in_row[i], oc = out_row[i]; \
+                                       out_row[i] = (ic * a + oc * b) / 0xff; \
+                               } \
+                               in_row += components; out_row += components; \
+                       } \
+               } \
+       } \
+       else { \
+               for( int y=y1; y<y2; ++y ) { \
+                       type *in_row = (type*) in_rows[y]; \
+                       type *out_row = (type*)out_rows[y]; \
+                       unsigned char *pattern_row = pattern_image[y]; \
+                       for( int x=0; x<w; ++x ) { \
+                               tmp_type d = (pattern_row[x] - threshold) * scale; \
+                               if( d > 0xff ) d = 0xff; \
+                               else if( d < -0xff ) d = -0xff; \
+                               tmp_type b = (d + 0xff) / 2, a = 0xff - b; \
+                               for( int i=0; i<components; ++i ) { \
+                                       type ic = in_row[i], oc = out_row[i]; \
+                                       out_row[i] = (ic * a + oc * b) / 0xff; \
+                               } \
+                               in_row += components; out_row += components; \
                        } \
-                       in_row += components; out_row += components; \
                } \
        } \
 }
@@ -646,6 +612,7 @@ void ShapeUnit::process_package(LoadPackage *package)
        VFrame *input = server->plugin->input;
        VFrame *output = server->plugin->output;
        int w = input->get_w();
+       int dir = server->plugin->config.direction;
 
        unsigned char **pattern_image = server->plugin->pattern_image;
        unsigned char threshold = server->plugin->threshold;