rework histogram_bezier, init wm icon set_icon(gg), update de.po+msg/txt
[goodguy/history.git] / cinelerra-5.1 / cinelerra / filejpeg.C
index 2a162836ce4564c76c3c8b77a9834b5cebf5f5c0..d35e9bd49ba30512511f7a1d26f8028f8e6f5abd 100644 (file)
@@ -48,41 +48,35 @@ FileJPEG::~FileJPEG()
 
 int FileJPEG::check_sig(Asset *asset)
 {
-       FILE *stream = fopen(asset->path, "rb");
-
-       if(stream)
-       {
-               char test[10];
-               (void)fread(test, 10, 1, stream);
-               fclose(stream);
-
-               if(test[6] == 'J' && test[7] == 'F' && test[8] == 'I' && test[9] == 'F')
-               {
-                       return 1;
+       FILE *fp = fopen(asset->path, "r");
+       if( !fp ) return 0;
+       char test[10];
+       int result = -1;
+       if( fread(test, 1, sizeof(test), fp) == sizeof(test) ) {
+               if( test[6] == 'J' && test[7] == 'F' && test[8] == 'I' && test[9] == 'F' ) {
+                       fseek(fp, 0, SEEK_SET);
+                       int w = 0, h = 0;
+                       result = read_header(fp, w, h);
                }
-               else
-               if(test[0] == 'J' && test[1] == 'P' && test[2] == 'E' && test[3] == 'G' &&
-                       test[4] == 'L' && test[5] == 'I' && test[6] == 'S' && test[7] == 'T')
-               {
-                       return 1;
+               else if(test[0] == 'J' && test[1] == 'P' && test[2] == 'E' && test[3] == 'G' &&
+                       test[4] == 'L' && test[5] == 'I' && test[6] == 'S' && test[7] == 'T') {
+                       result = 0;
                }
        }
+       fclose(fp);
 
-       if(strlen(asset->path) > 4)
-       {
-               int len = strlen(asset->path);
-               if(!strncasecmp(asset->path + len - 4, ".jpg", 4)) return 1;
+       if( result < 0 ) {
+               int i = strlen(asset->path) - 4;
+               if( i >= 0 && !strcasecmp(asset->path+i, ".jpg") )
+                       result = 0;
        }
-       return 0;
+       return !result ? 1 : 0;
 }
 
 
-
 void FileJPEG::get_parameters(BC_WindowBase *parent_window,
-       Asset *asset,
-       BC_WindowBase* &format_window,
-       int audio_options,
-       int video_options)
+       Asset *asset, BC_WindowBase* &format_window,
+       int audio_options, int video_options, EDL *edl)
 {
        if(video_options)
        {
@@ -127,16 +121,9 @@ int FileJPEG::get_best_colormodel(Asset *asset, int driver)
                case PLAYBACK_X11_GL:
                        return BC_YUV888;
                        break;
-               case PLAYBACK_LML:
-               case PLAYBACK_BUZ:
-                       return BC_YUV422P;
-                       break;
-               case VIDEO4LINUX:
                case VIDEO4LINUX2:
                        return BC_YUV420P;
                        break;
-               case CAPTURE_BUZ:
-               case CAPTURE_LML:
                case VIDEO4LINUX2JPEG:
                        return BC_YUV422;
                        break;
@@ -174,6 +161,59 @@ int FileJPEG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
                frame->get_color_model(),
                1);
 
+// insert spherical tag
+       if(asset->jpeg_sphere)
+       {
+               const char *sphere_tag = 
+                       "http://ns.adobe.com/xap/1.0/\x00<?xpacket begin='\xef\xbb\xbf' id='W5M0MpCehiHzreSzNTczkc9d'?>\n"
+                       "<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::Cinelerra'>\n"
+                       "<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n"
+                       "\n"
+                       " <rdf:Description rdf:about=''\n"
+                       "  xmlns:GPano='http://ns.google.com/photos/1.0/panorama/'>\n"
+                       "  <GPano:ProjectionType>equirectangular</GPano:ProjectionType>\n"
+                       " </rdf:Description>\n"
+                       "</rdf:RDF>\n"
+                       "</x:xmpmeta>\n"
+                       "<?xpacket end='w'?>";
+
+// calculate length by skipping the \x00 byte
+               int skip = 32;
+               int tag_len = strlen(sphere_tag + skip) + skip;
+               int tag_len2 = tag_len + 2;
+               int tag_len3 = tag_len + 4;
+               
+               data->allocate_compressed_data(
+                       mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor) + tag_len3);
+               data->set_compressed_size(
+                       mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor) + tag_len3);
+                       
+               int jfif_size = 0x14;
+               uint8_t *ptr = data->get_data();
+               memcpy(ptr, 
+                       mjpeg_output_buffer((mjpeg_t*)jpeg_unit->compressor), 
+                       jfif_size);
+               ptr += jfif_size;
+               *ptr++ = 0xff;
+               *ptr++ = 0xe1;
+               *ptr++ = (tag_len2 >> 8) & 0xff;
+               *ptr++ = tag_len2 & 0xff;
+               memcpy(ptr,
+                       sphere_tag,
+                       tag_len);
+               ptr += tag_len;
+               memcpy(ptr,
+                       mjpeg_output_buffer((mjpeg_t*)jpeg_unit->compressor) + jfif_size,
+                       mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor) - jfif_size);
+       }
+       else
+       {
+               data->allocate_compressed_data(mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor));
+               data->set_compressed_size(mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor));
+               memcpy(data->get_data(), 
+                       mjpeg_output_buffer((mjpeg_t*)jpeg_unit->compressor), 
+                       mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor));
+       }
        data->allocate_compressed_data(mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor));
        data->set_compressed_size(mjpeg_output_size((mjpeg_t*)jpeg_unit->compressor));
        memcpy(data->get_data(),
@@ -194,51 +234,49 @@ int FileJPEG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
 
 int FileJPEG::read_frame_header(char *path)
 {
-       int result = 0;
-
-
-       FILE *stream;
-
-       if(!(stream = fopen(path, "rb")))
-       {
+       FILE *fp = fopen(path, "rb");
+       if( !fp ) {
                eprintf("FileJPEG::read_frame_header %s: %m\n", path);
                return 1;
        }
-
-
+       int w = 0, h = 0, result = 1;
        unsigned char test[2];
-       (void)fread(test, 2, 1, stream);
-       if(test[0] != 0xff || test[1] != 0xd8)
-       {
-               eprintf("FileJPEG::read_frame_header %s bad header %02x%02x\n",
-                       path, test[0], test[1]);
-               fclose(stream);
-               return 1;
+       if( fread(test, 1, sizeof(test), fp) == sizeof(test) &&
+           test[0] == 0xff && test[1] == 0xd8 ) {
+               fseek(fp, 0, SEEK_SET);
+               result = read_header(fp, w, h);
+       }
+       fclose(fp);
+       if( !result ) {
+               asset->width = w;  asset->height = h;
+               asset->interlace_mode = ILACE_MODE_NOTINTERLACED;
        }
-       fseek(stream, 0, SEEK_SET);
+       else
+               eprintf("FileJPEG::read_frame_header %s bad header\n", path);
+       return result;
+}
 
-       struct jpeg_decompress_struct jpeg_decompress;
+int FileJPEG::read_header(FILE *fp, int &w, int &h)
+{
+       int result = 0;
        struct jpeg_error_mgr jpeg_error;
-
+       struct jpeg_decompress_struct jpeg_decompress;
        jpeg_decompress.err = jpeg_std_error(&jpeg_error);
        jpeg_create_decompress(&jpeg_decompress);
-
-       jpeg_stdio_src(&jpeg_decompress, stream);
-       jpeg_read_header(&jpeg_decompress, TRUE);
-
-       asset->width = jpeg_decompress.image_width;
-       asset->height = jpeg_decompress.image_height;
-
-       asset->interlace_mode = BC_ILACE_MODE_NOTINTERLACED;
-
+       jpeg_stdio_src(&jpeg_decompress, fp);
+       if( jpeg_read_header(&jpeg_decompress, TRUE) != JPEG_HEADER_OK ) result = 1;
+       if( !result && jpeg_decompress.jpeg_color_space != JCS_YCbCr ) result = 1;
+       if( !result && jpeg_decompress.comp_info[0].h_samp_factor > 2 ) result = 1;
+       if( !result && jpeg_decompress.comp_info[0].v_samp_factor > 2 ) result = 1;
+       if( !result ) {
+               w = jpeg_decompress.image_width;
+               h = jpeg_decompress.image_height;
+       }
        jpeg_destroy((j_common_ptr)&jpeg_decompress);
-       fclose(stream);
-
        return result;
 }
 
 
-
 int FileJPEG::read_frame(VFrame *output, VFrame *input)
 {
        if(input->get_compressed_size() < 2 ||
@@ -307,8 +345,7 @@ JPEGConfigVideo::JPEGConfigVideo(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),
-       400,
-       100)
+       400, 200)
 {
        this->parent_window = parent_window;
        this->asset = asset;
@@ -323,17 +360,13 @@ void JPEGConfigVideo::create_objects()
        int x = 10, y = 10;
        lock_window("JPEGConfigVideo::create_objects");
        add_subwindow(new BC_Title(x, y, _("Quality:")));
-       add_subwindow(new BC_ISlider(x + 80,
-               y,
-               0,
-               200,
-               200,
-               0,
-               100,
-               asset->jpeg_quality,
-               0,
-               0,
+       BC_ISlider *slider;
+       add_subwindow(slider = new BC_ISlider(x + 80, y,
+               0, 200, 200, 0, 100, asset->jpeg_quality, 0, 0,
                &asset->jpeg_quality));
+       y += slider->get_h() + 10;
+       add_subwindow(new BC_CheckBox(x, y, 
+               &asset->jpeg_sphere, _("Tag for spherical playback")));
 
        add_subwindow(new BC_OKButton(this));
        show_window(1);