00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "vil_jpeg.h"
00016 #include "vil_jpeg_source_mgr.h"
00017 #include "vil_jpeg_decompressor.h"
00018 #include "vil_jpeg_destination_mgr.h"
00019 #include "vil_jpeg_compressor.h"
00020
00021 #include <vcl_cassert.h>
00022 #include <vcl_iostream.h>
00023 #include <vcl_cstring.h>
00024 #include <vxl_config.h>
00025
00026 #include <vil/vil_stream.h>
00027 #include <vil/vil_image_view.h>
00028 #include <vil/vil_exception.h>
00029
00030
00031 bool vil_jpeg_file_probe(vil_stream *vs)
00032 {
00033 char magic[2];
00034 vs->seek(0L);
00035 vil_streampos n = vs->read(magic, sizeof(magic));
00036
00037 if (n != sizeof(magic)) {
00038 vcl_cerr << __FILE__ << " : vil_stream::read() failed\n";
00039 return false;
00040 }
00041
00042
00043 return (magic[0] == char(0xFF)) && (magic[1] == char(0xD8));
00044 }
00045
00046
00047 static char const jpeg_string[] = "jpeg";
00048
00049
00050
00051
00052 char const* vil_jpeg_file_format::tag() const
00053 {
00054 return jpeg_string;
00055 }
00056
00057
00058 vil_image_resource_sptr vil_jpeg_file_format::make_input_image(vil_stream *vs)
00059 {
00060 return vil_jpeg_file_probe(vs) ? new vil_jpeg_image(vs) : 0;
00061 }
00062
00063 vil_image_resource_sptr
00064 vil_jpeg_file_format::make_output_image(vil_stream* vs,
00065 unsigned nx,
00066 unsigned ny,
00067 unsigned nplanes,
00068 enum vil_pixel_format format)
00069 {
00070 if (format != VIL_PIXEL_FORMAT_BYTE)
00071 {
00072 vcl_cout<<"ERROR! vil_jpeg_file_format::make_output_image()\n"
00073 <<"Pixel format should be byte, but is "<<format<<" instead.\n";
00074 return 0;
00075 }
00076 return new vil_jpeg_image(vs, nx, ny, nplanes, format);
00077 }
00078
00079
00080
00081
00082
00083 vil_jpeg_image::vil_jpeg_image(vil_stream *s)
00084 : jc(0)
00085 , jd(new vil_jpeg_decompressor(s))
00086 , stream(s)
00087 {
00088 stream->ref();
00089 }
00090
00091 bool vil_jpeg_image::get_property(char const * , void * ) const
00092 {
00093
00094 return false;
00095 }
00096
00097 void vil_jpeg_image::set_quality(int quality)
00098 {
00099 if( jc )
00100 jc->set_quality(quality);
00101 }
00102
00103 vil_jpeg_image::vil_jpeg_image(vil_stream *s,
00104 unsigned nx,
00105 unsigned ny,
00106 unsigned nplanes,
00107 enum vil_pixel_format format)
00108 : jc(new vil_jpeg_compressor(s))
00109 , jd(0)
00110 , stream(s)
00111 {
00112 if (format != VIL_PIXEL_FORMAT_BYTE)
00113 vcl_cerr << "Sorry -- pixel format " << format << " not yet supported\n";
00114 assert(format == VIL_PIXEL_FORMAT_BYTE);
00115
00116 stream->ref();
00117
00118
00119 jc->jobj.input_components = nplanes;
00120
00121
00122 jc->jobj.image_width = nx;
00123 jc->jobj.image_height = ny;
00124 #ifdef DEBUG
00125 vcl_cerr << "w h = " << nx << ' ' << ny << '\n';
00126 #endif
00127 }
00128
00129 vil_jpeg_image::~vil_jpeg_image()
00130 {
00131
00132
00133 if (jd)
00134 delete jd;
00135 jd = 0;
00136 if (jc)
00137 delete jc;
00138 jc = 0;
00139 stream->unref();
00140 stream = 0;
00141 }
00142
00143
00144
00145
00146 vil_image_view_base_sptr vil_jpeg_image::get_copy_view(unsigned x0,
00147 unsigned nx,
00148 unsigned y0,
00149 unsigned ny) const
00150 {
00151 if (!jd) {
00152 vcl_cerr << "attempted get_copy_view() failed -- no jpeg decompressor\n";
00153 return 0;
00154 }
00155 #ifdef DEBUG
00156 vcl_cerr << "get_copy_view " << ' ' << x0 << ' ' << nx << ' ' << y0 << ' ' << ny << '\n';
00157 #endif
00158
00159
00160 unsigned bpp = jd->jobj.output_components;
00161
00162 vil_memory_chunk_sptr chunk = new vil_memory_chunk(bpp * nx * ny, pixel_format());
00163
00164 for (unsigned int i=0; i<ny; ++i) {
00165 JSAMPLE const *scanline = jd->read_scanline(y0+i);
00166 if (!scanline)
00167 return 0;
00168
00169 vcl_memcpy(reinterpret_cast<char*>(chunk->data()) + i*nx*bpp, &scanline[x0*bpp], nx*bpp);
00170 }
00171
00172 return new vil_image_view<vxl_byte>(chunk, reinterpret_cast<vxl_byte *>(chunk->data()), nx, ny, bpp, bpp, bpp*nx, 1);
00173 }
00174
00175
00176
00177
00178 bool vil_jpeg_image::put_view(const vil_image_view_base &view,
00179 unsigned x0, unsigned y0)
00180 {
00181
00182 if (!view_fits(view, x0, y0))
00183 {
00184 vil_exception_warning(vil_exception_out_of_bounds("vil_jpeg_image::put_view"));
00185 return false;
00186 }
00187
00188 if (!jc) {
00189 vcl_cerr << "attempted put_view() failed -- no jpeg compressor\n";
00190 return false;
00191 }
00192
00193 if (view.pixel_format() != VIL_PIXEL_FORMAT_BYTE)
00194 {
00195 vcl_cerr << "vil_jpeg_image::put_view() failed -- can only deal with byte images\n";
00196 return false;
00197 }
00198
00199 const vil_image_view<vxl_byte>& view2 =
00200 static_cast<const vil_image_view<vxl_byte>&>(view);
00201
00202
00203
00204
00205 if (x0 != 0 || view2.ni() != jc->jobj.image_width) {
00206 vcl_cerr << __FILE__ << " : Can only compress complete scanlines\n";
00207 return false;
00208 }
00209 if (y0 != jc->jobj.next_scanline) {
00210 vcl_cerr << __FILE__ << " : Scanlines must be sent sequentially\n";
00211 return false;
00212 }
00213
00214
00215 if ((view2.planestep() == 1 || view2.nplanes() == 1) && view2.istep() == jc->jobj.input_components)
00216 {
00217 assert(view2.istep() > 0);
00218 assert(view2.istep() == jc->jobj.input_components);
00219 for (unsigned int j=0; j<view2.nj(); ++j) {
00220 JSAMPLE const *scanline = (JSAMPLE const*)
00221 &view2(0,j);
00222 if (!jc->write_scanline(y0+j, scanline))
00223 return false;
00224 }
00225 }
00226 else
00227 {
00228 vil_memory_chunk_sptr chunk = new vil_memory_chunk(view2.ni()*view2.nplanes(), vil_pixel_format_component_format(vil_pixel_format_of(vxl_byte())));
00229 vil_image_view<vxl_byte> line = vil_image_view<vxl_byte>(chunk, reinterpret_cast<vxl_byte*>(chunk->data()), view2.ni(), 1, view2.nplanes(), view2.nplanes(), view2.nplanes()*view2.ni(), 1);
00230 JSAMPLE *scanline = line.top_left_ptr();
00231
00232 for (unsigned int j=0; j<view2.nj(); ++j)
00233 {
00234
00235 for (unsigned i = 0; i < view2.ni(); ++i)
00236 for (unsigned p = 0; p < view2.nplanes(); ++p)
00237 line(i,0,p) = view2(i,j,p);
00238 if (!jc->write_scanline(y0+j, scanline))
00239 return false;
00240 }
00241 }
00242
00243 return true;
00244 }
00245
00246
00247
00248
00249 unsigned vil_jpeg_image::ni() const
00250 {
00251 if (jd) return jd->jobj.output_width;
00252 if (jc) return jc->jobj.image_width;
00253 return 0;
00254 }
00255
00256 unsigned vil_jpeg_image::nj() const
00257 {
00258 if (jd) return jd->jobj.output_height;
00259 if (jc) return jc->jobj.image_height;
00260 return 0;
00261 }
00262
00263 unsigned vil_jpeg_image::nplanes() const
00264 {
00265 if (jd) return jd->jobj.output_components;
00266 if (jc) return jc->jobj.input_components;
00267 return 0;
00268 }
00269
00270
00271 vil_pixel_format vil_jpeg_image::pixel_format() const
00272 {
00273 return VIL_PIXEL_FORMAT_BYTE;
00274 }
00275
00276
00277 char const *vil_jpeg_image::file_format() const
00278 {
00279 return jpeg_string;
00280 }
00281
00282