+ block_t *p_block;
+ FILE *file;
+
+ if( !p_fmt_out->i_chroma )
+ {
+ /* Try to guess format from file name */
+ p_fmt_out->i_chroma = image_Ext2Fourcc( psz_url );
+ }
+
+ file = utf8_fopen( psz_url, "wb" );
+ if( !file )
+ {
+ msg_Err( p_image->p_parent, "%s: %m", psz_url );
+ return VLC_EGENERIC;
+ }
+
+ p_block = ImageWrite( p_image, p_pic, p_fmt_in, p_fmt_out );
+
+ int err = 0;
+ if( p_block )
+ {
+ if( fwrite( p_block->p_buffer, p_block->i_buffer, 1, file ) != 1 )
+ err = errno;
+ block_Release( p_block );
+ }
+
+ if( fclose( file ) && !err )
+ err = errno;
+
+ if( err )
+ {
+ errno = err;
+ msg_Err( p_image->p_parent, "%s: %m", psz_url );
+ }
+
+ return err ? VLC_EGENERIC : VLC_SUCCESS;
+}
+
+/**
+ * Convert an image to a different format
+ *
+ */
+
+static picture_t *ImageConvert( image_handler_t *p_image, picture_t *p_pic,
+ video_format_t *p_fmt_in,
+ video_format_t *p_fmt_out )
+{
+ picture_t *p_pif;
+
+ if( !p_fmt_out->i_width && !p_fmt_out->i_height &&
+ p_fmt_out->i_sar_num && p_fmt_out->i_sar_den &&
+ p_fmt_out->i_sar_num * p_fmt_in->i_sar_den !=
+ p_fmt_out->i_sar_den * p_fmt_in->i_sar_num )
+ {
+ p_fmt_out->i_width =
+ p_fmt_in->i_sar_num * (int64_t)p_fmt_out->i_sar_den *
+ p_fmt_in->i_width / p_fmt_in->i_sar_den / p_fmt_out->i_sar_num;
+ p_fmt_out->i_visible_width =
+ p_fmt_in->i_sar_num * (int64_t)p_fmt_out->i_sar_den *
+ p_fmt_in->i_visible_width / p_fmt_in->i_sar_den /
+ p_fmt_out->i_sar_num;
+ }
+
+ if( !p_fmt_out->i_chroma ) p_fmt_out->i_chroma = p_fmt_in->i_chroma;
+ if( !p_fmt_out->i_width )
+ p_fmt_out->i_width = p_fmt_out->i_visible_width = p_fmt_in->i_width;
+ if( !p_fmt_out->i_height )
+ p_fmt_out->i_height = p_fmt_out->i_visible_height = p_fmt_in->i_height;
+ if( !p_fmt_out->i_sar_num ) p_fmt_out->i_sar_num = p_fmt_in->i_sar_num;
+ if( !p_fmt_out->i_sar_den ) p_fmt_out->i_sar_den = p_fmt_in->i_sar_den;
+ if( !p_fmt_out->i_aspect ) p_fmt_out->i_aspect = p_fmt_in->i_aspect;
+
+ if( p_image->p_filter )
+ if( p_image->p_filter->fmt_in.video.i_chroma != p_fmt_in->i_chroma ||
+ p_image->p_filter->fmt_out.video.i_chroma != p_fmt_out->i_chroma )
+ {
+ /* We need to restart a new filter */
+ DeleteFilter( p_image->p_filter );
+ p_image->p_filter = NULL;
+ }
+
+ /* Start a filter */
+ if( !p_image->p_filter )
+ {
+ es_format_t fmt_in;
+ es_format_Init( &fmt_in, VIDEO_ES, p_fmt_in->i_chroma );
+ fmt_in.video = *p_fmt_in;
+
+ p_image->p_filter =
+ CreateFilter( p_image->p_parent, &fmt_in, p_fmt_out, NULL );
+
+ if( !p_image->p_filter )
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ /* Filters should handle on-the-fly size changes */
+ p_image->p_filter->fmt_in.video = *p_fmt_in;
+ p_image->p_filter->fmt_out.video = *p_fmt_out;
+ }
+
+ picture_Hold( p_pic );
+
+ p_pif = p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
+
+ if( p_fmt_in->i_chroma == p_fmt_out->i_chroma &&
+ p_fmt_in->i_width == p_fmt_out->i_width &&
+ p_fmt_in->i_height == p_fmt_out->i_height )
+ {
+ /* Duplicate image */
+ picture_Release( p_pif ); /* XXX: Better fix must be possible */
+ p_pif = p_image->p_filter->pf_vout_buffer_new( p_image->p_filter );
+ if( p_pif )
+ picture_Copy( p_pif, p_pic );
+ }
+
+ return p_pif;
+}
+
+/**
+ * Filter an image with a psz_module filter
+ *
+ */
+
+static picture_t *ImageFilter( image_handler_t *p_image, picture_t *p_pic,
+ video_format_t *p_fmt, const char *psz_module )
+{
+ /* Start a filter */
+ if( !p_image->p_filter )
+ {
+ es_format_t fmt;
+ es_format_Init( &fmt, VIDEO_ES, p_fmt->i_chroma );
+ fmt.video = *p_fmt;
+
+ p_image->p_filter =
+ CreateFilter( p_image->p_parent, &fmt, &fmt.video, psz_module );
+
+ if( !p_image->p_filter )
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ /* Filters should handle on-the-fly size changes */
+ p_image->p_filter->fmt_in.video = *p_fmt;
+ p_image->p_filter->fmt_out.video = *p_fmt;
+ }
+
+ picture_Hold( p_pic );
+
+ return p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );