Credit Andrew - improve in-tree documentation
[goodguy/cinelerra.git] / cinelerra / fileppm.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "asset.h"
23 #include "bccmodels.h"
24 #include "file.h"
25 #include "fileppm.h"
26 #include "interlacemodes.h"
27 #include "mainerror.h"
28
29 #include <string.h>
30 #include <unistd.h>
31
32
33 FilePPM::FilePPM(Asset *asset, File *file)
34  : FileList(asset, file, "PPMLIST", ".ppm", FILE_PPM, FILE_PPM_LIST)
35 {
36         reset();
37         if( asset->format == FILE_UNKNOWN )
38                 asset->format = FILE_PPM;
39 }
40
41 FilePPM::~FilePPM()
42 {
43         close_file();
44 }
45
46 void FilePPM::reset()
47 {
48 }
49
50 int FilePPM::check_sig(Asset *asset)
51 {
52         FILE *stream = fopen(asset->path, "r");
53         if( stream ) {
54                 char test[10];
55                 (void)fread(test, 10, 1, stream);
56                 fclose(stream);
57                 if( !strncmp("PPMLIST",test,6) ) return 1;
58                 if( !strncmp("P6\n",test,3) ) return 1;
59         }
60         return 0;
61 }
62
63 int FilePPM::check_frame_header(FILE *fp)
64 {
65         char text[BCSTRLEN];
66         if( !fgets(text, sizeof(text), fp) ) return 1;
67         if( strcmp("P6\n",text) ) return 1;
68         int ch = getc(fp);
69         while( ch == '#' ) { while( (ch=getc(fp))>=0 && ch!='\n' ); }
70         ungetc(ch,fp);
71         int w, h;
72         if( !fgets(text, sizeof(text), fp) ||
73             sscanf(text, "%d %d\n", &w, &h) != 2 ) return 1;
74         if( !fgets(text, sizeof(text), fp) ||
75             sscanf(text, "%d\n", &ch) != 1 || ch != 255 ) return 1;
76
77         asset->width = w;  asset->height = h;
78         asset->interlace_mode = ILACE_MODE_NOTINTERLACED;
79         return 0;
80 }
81
82 int FilePPM::read_frame_header(char *path)
83 {
84         int ret = 1;
85         FILE *fp = fopen(path, "r");
86         if( fp ) {
87                 ret = check_frame_header(fp);
88                 fclose(fp);
89         }
90         return ret;
91 }
92
93 int FilePPM::read_ppm(FILE *fp, VFrame *frame)
94 {
95         int ch;
96         char text[BCSTRLEN];
97         if( !fgets(text, sizeof(text), fp) ) return 1;
98         if( strcmp("P6\n",text) ) {
99                 printf("FilePPM::read_ppm: header err\n");
100                 return 1;
101         }
102         while( (ch=getc(fp)) == '#' ) { while( (ch=getc(fp))>=0 && ch!='\n' ); }
103         ungetc(ch,fp);
104         int w, h;
105         if( !fgets(text, sizeof(text), fp) ||
106             sscanf(text, "%d %d\n", &w, &h) != 2 ) {
107                 printf("FilePPM::read_ppm: geom err\n");
108                 return 1;
109         }
110         if( w != frame->get_w() || h != frame->get_h() ) {
111                 printf("FilePPM::read_ppm: geom mismatch\n");
112                 return 1;
113         }
114         if( !fgets(text, sizeof(text), fp) ||
115             sscanf(text, "%d\n", &ch) != 1 || ch != 255 ) {
116                 printf("FilePPM::read_ppm: mask err\n");
117                 return 1;
118         }
119
120         unsigned char **rows = frame->get_rows();
121         int bpl = 3*w;
122         for( int y=0; y<h; ++y ) {
123                 int ret = fread(rows[y],1,bpl,fp);
124                 if( ret != bpl ) {
125                         printf("FilePPM::read_ppm: read (%d,%d) err: %m\n", bpl, ret);
126                         return 1;
127                 }
128         }
129         return 0;
130 }
131
132 int FilePPM::read_frame(VFrame *frame, char *path)
133 {
134         int result = 1;
135         FILE *fp = fopen(path,"r");
136         if( fp ) {
137                 result = read_ppm(fp, frame);
138                 fclose(fp);
139         }
140         if( result )
141                 eprintf("FilePPM::read_frame: cant read file %s\n", path);
142         return result;
143 }
144
145 PPMUnit::PPMUnit(FilePPM *file, FrameWriter *writer)
146  : FrameWriterUnit(writer)
147 {
148         this->file = file;
149         temp_frame = 0;
150 }
151 PPMUnit::~PPMUnit()
152 {
153         delete temp_frame;
154 }
155
156 FrameWriterUnit* FilePPM::new_writer_unit(FrameWriter *writer)
157 {
158         return new PPMUnit(this, writer);
159 }
160
161 int FilePPM::write_frame(VFrame *frame, VFrame *output,
162                 FrameWriterUnit *frame_writer_unit)
163 {
164         int w = asset->width, h = asset->height;
165         char prefix[BCTEXTLEN];
166         int pfx = sprintf(prefix, "P6\n%d %d\n%d\n", w, h, 255);
167         int bpl = 3*w, image_length = h*bpl, total_length = pfx + image_length;
168         if( output->get_compressed_allocated() < total_length ) {
169                 int new_length = total_length + 255;
170                 output->allocate_compressed_data(new_length);
171         }
172         unsigned char *dp = output->get_data(), *bp = dp;
173         memcpy(dp, prefix, pfx);  dp += pfx;
174         unsigned char *rows[h+1], **rp = rows;
175         for( int y=h; --y>=0; dp+=bpl ) *rp++ = dp;
176         BC_CModels::transfer(rows, frame->get_rows(),
177                 0, 0, 0, frame->get_y(), frame->get_u(), frame->get_v(),
178                 0, 0, frame->get_w(), frame->get_h(), 0, 0, w, h,
179                 frame->get_color_model(), BC_RGB888, 0,
180                 frame->get_bytes_per_line(), bpl);
181
182         output->set_compressed_size(dp - bp);
183         return 0;
184 }
185
186 int FilePPM::colormodel_supported(int colormodel)
187 {
188         return BC_RGB888;
189 }
190
191 int FilePPM::get_best_colormodel(Asset *asset, int driver)
192 {
193         return BC_RGB888;
194 }
195
196 PPMConfigVideo::PPMConfigVideo(BC_WindowBase *gui, Asset *asset)
197  : BC_Window(_(PROGRAM_NAME ": Video Compression"),
198         gui->get_abs_cursor_x(1), gui->get_abs_cursor_y(1), 200, 100)
199 {
200         this->gui = gui;
201         this->asset = asset;
202 }
203
204 void PPMConfigVideo::create_objects()
205 {
206         lock_window("PPMConfigVideo::create_objects");
207         int x = 10, y = 10;
208         add_subwindow(new BC_Title(x, y, _("PPM, RGB raw only")));
209         add_subwindow(new BC_OKButton(this));
210         show_window(1);
211         unlock_window();
212 }
213
214 void FilePPM::get_parameters(BC_WindowBase *parent_window,
215         Asset *asset, BC_WindowBase* &format_window,
216         int audio_options, int video_options, EDL *edl)
217 {
218         if(video_options) {
219                 PPMConfigVideo *window = new PPMConfigVideo(parent_window, asset);
220                 window->create_objects();
221                 format_window = window;
222                 window->run_window();
223                 delete window;
224         }
225 }
226
227 int FilePPM::use_path()
228 {
229         return 1;
230 }