00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010 #include "vil1_jpeg.h"
00011 #include "vil1_jpeg_source_mgr.h"
00012 #include "vil1_jpeg_decompressor.h"
00013 #include "vil1_jpeg_destination_mgr.h"
00014 #include "vil1_jpeg_compressor.h"
00015
00016 #include <vcl_cassert.h>
00017 #include <vcl_climits.h>
00018 #include <vcl_iostream.h>
00019 #include <vcl_cstring.h>
00020
00021 #include <vil1/vil1_stream.h>
00022 #include <vil1/vil1_image.h>
00023 #include <vil1/vil1_property.h>
00024
00025
00026 bool vil1_jpeg_file_probe(vil1_stream *vs)
00027 {
00028 char magic[2];
00029 vs->seek(0L);
00030 int n = vs->read(magic, sizeof(magic));
00031
00032 if (n != sizeof(magic)) {
00033 vcl_cerr << __FILE__ << " : vil1_stream::read() failed\n";
00034 return false;
00035 }
00036
00037
00038 return ( (magic[0] == char(0xFF)) && (magic[1] == char(0xD8)) );
00039 }
00040
00041
00042 static char const jpeg_string[] = "jpeg";
00043
00044
00045
00046
00047 char const* vil1_jpeg_file_format::tag() const
00048 {
00049 return jpeg_string;
00050 }
00051
00052
00053 vil1_image_impl *vil1_jpeg_file_format::make_input_image(vil1_stream *vs)
00054 {
00055 return vil1_jpeg_file_probe(vs) ? new vil1_jpeg_generic_image(vs) : 0;
00056 }
00057
00058 vil1_image_impl *vil1_jpeg_file_format::make_output_image(vil1_stream *vs,
00059 int planes,
00060 int width,
00061 int height,
00062 int components,
00063 int bits_per_component,
00064 vil1_component_format format)
00065 {
00066 if (format != VIL1_COMPONENT_FORMAT_UNSIGNED_INT)
00067 return 0;
00068 return new vil1_jpeg_generic_image(vs, planes, width, height, components, bits_per_component, format);
00069 }
00070
00071
00072
00073
00074
00075 vil1_jpeg_generic_image::vil1_jpeg_generic_image(vil1_stream *s)
00076 : jc(0)
00077 , jd(new vil1_jpeg_decompressor(s))
00078 , stream(s)
00079 {
00080 stream->ref();
00081 }
00082
00083 bool vil1_jpeg_generic_image::get_property(char const *tag, void *prop) const
00084 {
00085 if (0==vcl_strcmp(tag, vil1_property_top_row_first))
00086 return prop ? (*(bool*)prop) = true : true;
00087
00088 if (0==vcl_strcmp(tag, vil1_property_left_first))
00089 return prop ? (*(bool*)prop) = true : true;
00090
00091 return false;
00092 }
00093
00094 vil1_jpeg_generic_image::vil1_jpeg_generic_image(vil1_stream *s,
00095 int planes,
00096 int width,
00097 int height,
00098 int components,
00099 int bits_per_component,
00100 vil1_component_format format)
00101 : jc(new vil1_jpeg_compressor(s))
00102 , jd(0)
00103 , stream(s)
00104 {
00105 stream->ref();
00106
00107 if (planes != 1)
00108 vcl_cerr << __FILE__ " : prototype has != 1 planes. ignored\n";
00109
00110
00111 jc->jobj.input_components = components;
00112
00113
00114 jc->jobj.image_width = width;
00115 jc->jobj.image_height = height;
00116 #ifdef DEBUG
00117 vcl_cerr << "w h = " << width << ' ' << height << '\n';
00118 #endif
00119
00120 assert(bits_per_component == CHAR_BIT);
00121 assert(format == VIL1_COMPONENT_FORMAT_UNSIGNED_INT);
00122 }
00123
00124 vil1_jpeg_generic_image::~vil1_jpeg_generic_image()
00125 {
00126
00127
00128 if (jd)
00129 delete jd;
00130 jd = 0;
00131 if (jc)
00132 delete jc;
00133 jc = 0;
00134 stream->unref();
00135 stream = 0;
00136 }
00137
00138
00139
00140
00141 bool vil1_jpeg_generic_image::get_section(void *buf, int x0, int y0, int w, int h) const
00142 {
00143 if (!jd) {
00144 vcl_cerr << "attempted put_section() failed -- no jpeg decompressor\n";
00145 return false;
00146 }
00147 #ifdef DEBUG
00148 vcl_cerr << "get_section " << buf << ' ' << x0 << ' ' << y0 << ' ' << w << ' ' << h << '\n';
00149 #endif
00150
00151
00152 unsigned bpp = jd->jobj.output_components;
00153
00154
00155 for (int i=0; i<h; ++i) {
00156 JSAMPLE const *scanline = jd->read_scanline(y0+i);
00157 if (!scanline)
00158 return false;
00159 vcl_memcpy(static_cast<char*>(buf) + i*w*bpp, &scanline[x0*bpp], w*bpp);
00160 }
00161
00162 return true;
00163 }
00164
00165
00166
00167
00168 bool vil1_jpeg_generic_image::put_section(void const *buf, int x0, int y0, int w, int h)
00169 {
00170 if (!jc) {
00171 vcl_cerr << "attempted get_section() failed -- no jpeg compressor\n";
00172 return false;
00173 }
00174
00175
00176
00177
00178 if (x0 != 0 || (unsigned int)w != jc->jobj.image_width) {
00179 vcl_cerr << __FILE__ << " : Can only compress complete scanlines\n";
00180 return false;
00181 }
00182 if ((unsigned int)y0 != jc->jobj.next_scanline) {
00183 vcl_cerr << __FILE__ << " : Scanlines must be sent sequentially\n";
00184 return false;
00185 }
00186
00187
00188 unsigned bpp = jc->jobj.input_components;
00189
00190
00191 for (int i=0; i<h; ++i) {
00192 JSAMPLE const *scanline = (JSAMPLE const*) ((char const*)buf + i*w*bpp);
00193 if (!jc->write_scanline(y0+i, scanline))
00194 return false;
00195 }
00196
00197 return true;
00198 }
00199
00200
00201
00202
00203 int vil1_jpeg_generic_image::planes() const
00204 {
00205 return 1;
00206 }
00207
00208
00209 int vil1_jpeg_generic_image::width() const
00210 {
00211 if (jd) return jd->jobj.output_width;
00212 if (jc) return jc->jobj.image_width;
00213 return 0;
00214 }
00215
00216
00217 int vil1_jpeg_generic_image::height() const
00218 {
00219 if (jd) return jd->jobj.output_height;
00220 if (jc) return jc->jobj.image_height;
00221 return 0;
00222 }
00223
00224
00225 int vil1_jpeg_generic_image::components() const
00226 {
00227 if (jd) return jd->jobj.output_components;
00228 if (jc) return jc->jobj.input_components;
00229 return 0;
00230 }
00231
00232
00233 int vil1_jpeg_generic_image::bits_per_component() const
00234 {
00235 return CHAR_BIT;
00236 }
00237
00238
00239 vil1_component_format vil1_jpeg_generic_image::component_format() const
00240 {
00241 return VIL1_COMPONENT_FORMAT_UNSIGNED_INT;
00242 }
00243
00244
00245 vil1_image vil1_jpeg_generic_image::get_plane(unsigned int p) const
00246 {
00247 assert(p == 0);
00248 return const_cast<vil1_jpeg_generic_image*>( this );
00249 }
00250
00251
00252 char const *vil1_jpeg_generic_image::file_format() const
00253 {
00254 return jpeg_string;
00255 }
00256
00257