Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

vil_jpeg.cxx

Go to the documentation of this file.
00001 // This is core/vil/file_formats/vil_jpeg.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author fsm
00008 // \date   17 Feb 2000
00009 // \verbatim
00010 //  Modifications
00011 //     11 Oct 2002 Ian Scott - converted to vil
00012 //     30 Mar 2007 Peter Vanroose - replaced deprecated vil_new_image_view_j_i_plane()
00013 //\endverbatim
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> // memcpy()
00024 #include <vxl_config.h> // vxl_byte
00025 
00026 #include <vil/vil_stream.h>
00027 #include <vil/vil_image_view.h>
00028 
00029 //: the file probe, as a C function.
00030 bool vil_jpeg_file_probe(vil_stream *vs)
00031 {
00032   char magic[2];
00033   vs->seek(0L);
00034   vil_streampos n = vs->read(magic, sizeof(magic));
00035 
00036   if (n != sizeof(magic)) {
00037     vcl_cerr << __FILE__ << " : vil_stream::read() failed\n";
00038     return false;
00039   }
00040 
00041   // 0xFF followed by 0xD8
00042   return (magic[0] == char(0xFF)) && (magic[1] == char(0xD8));
00043 }
00044 
00045 // static data
00046 static char const jpeg_string[] = "jpeg";
00047 
00048 //--------------------------------------------------------------------------------
00049 // class vil_jpeg_file_format
00050 
00051 char const* vil_jpeg_file_format::tag() const
00052 {
00053   return jpeg_string;
00054 }
00055 
00056 //:
00057 vil_image_resource_sptr  vil_jpeg_file_format::make_input_image(vil_stream *vs)
00058 {
00059   return vil_jpeg_file_probe(vs) ? new vil_jpeg_image(vs) : 0;
00060 }
00061 
00062 vil_image_resource_sptr
00063   vil_jpeg_file_format::make_output_image(vil_stream* vs,
00064                                           unsigned nx,
00065                                           unsigned ny,
00066                                           unsigned nplanes,
00067                                           enum vil_pixel_format format)
00068 {
00069   if (format != VIL_PIXEL_FORMAT_BYTE)
00070   {
00071     vcl_cout<<"ERROR! vil_jpeg_file_format::make_output_image()\n"
00072             <<"Pixel format should be byte, but is "<<format<<" instead.\n";
00073     return 0;
00074   }
00075   return new vil_jpeg_image(vs, nx, ny, nplanes, format);
00076 }
00077 
00078 //--------------------------------------------------------------------------------
00079 
00080 // class vil_jpeg_image
00081 
00082 vil_jpeg_image::vil_jpeg_image(vil_stream *s)
00083   : jc(0)
00084   , jd(new vil_jpeg_decompressor(s))
00085   , stream(s)
00086 {
00087   stream->ref();
00088 }
00089 
00090 bool vil_jpeg_image::get_property(char const * /*tag*/, void * /*prop*/) const
00091 {
00092   // This is not an in-memory image type, nor is it read-only:
00093   return false;
00094 }
00095 
00096 vil_jpeg_image::vil_jpeg_image(vil_stream *s,
00097                                unsigned nx,
00098                                unsigned ny,
00099                                unsigned nplanes,
00100                                enum vil_pixel_format format)
00101   : jc(new vil_jpeg_compressor(s))
00102   , jd(0)
00103   , stream(s)
00104 {
00105   if (format != VIL_PIXEL_FORMAT_BYTE)
00106     vcl_cerr << "Sorry -- pixel format " << format << " not yet supported\n";
00107   assert(format == VIL_PIXEL_FORMAT_BYTE); // FIXME.
00108 
00109   stream->ref();
00110 
00111   // use same number of components as prototype, obviously.
00112   jc->jobj.input_components = nplanes;
00113 
00114   // store size
00115   jc->jobj.image_width = nx;
00116   jc->jobj.image_height = ny;
00117 #ifdef DEBUG
00118   vcl_cerr << "w h = " << nx << ' ' << ny << '\n';
00119 #endif
00120 }
00121 
00122 vil_jpeg_image::~vil_jpeg_image()
00123 {
00124   // FIXME: I suspect there's a core leak here because jpeg_destroy() does not
00125   // free the vil_jpeg_stream_source_mgr allocated in vil_jpeg_stream_xxx_set()
00126   if (jd)
00127     delete jd;
00128   jd = 0;
00129   if (jc)
00130     delete jc;
00131   jc = 0;
00132   stream->unref();
00133   stream = 0;
00134 }
00135 
00136 //--------------------------------------------------------------------------------
00137 
00138 //: decompressing from the vil_stream to a section buffer.
00139 vil_image_view_base_sptr vil_jpeg_image::get_copy_view(unsigned x0,
00140                                                        unsigned nx,
00141                                                        unsigned y0,
00142                                                        unsigned ny) const
00143 {
00144   if (!jd) {
00145     vcl_cerr << "attempted get_copy_view() failed -- no jpeg decompressor\n";
00146     return 0;
00147   }
00148 #ifdef DEBUG
00149   vcl_cerr << "get_copy_view " << ' ' << x0 << ' ' << nx << ' ' << y0 << ' ' << ny << '\n';
00150 #endif
00151 
00152   // number of bytes per pixel
00153   unsigned bpp = jd->jobj.output_components;
00154 
00155   vil_memory_chunk_sptr chunk = new vil_memory_chunk(bpp * nx * ny, pixel_format());
00156 
00157   for (unsigned int i=0; i<ny; ++i) {
00158     JSAMPLE const *scanline = jd->read_scanline(y0+i);
00159     if (!scanline)
00160       return 0; // failed
00161 
00162     vcl_memcpy(reinterpret_cast<char*>(chunk->data()) + i*nx*bpp, &scanline[x0*bpp], nx*bpp);
00163   }
00164 
00165   return new vil_image_view<vxl_byte>(chunk, reinterpret_cast<vxl_byte *>(chunk->data()), nx, ny, bpp, bpp, bpp*nx, 1);
00166 }
00167 
00168 //--------------------------------------------------------------------------------
00169 
00170 //: compressing a section onto the vil_stream.
00171 bool vil_jpeg_image::put_view(const vil_image_view_base &view,
00172                               unsigned x0, unsigned y0)
00173 {
00174   if (!jc) {
00175     vcl_cerr << "attempted put_view() failed -- no jpeg compressor\n";
00176     return false;
00177   }
00178 
00179   if (view.pixel_format() != VIL_PIXEL_FORMAT_BYTE)
00180   {
00181     vcl_cerr << "vil_jpeg_image::put_view() failed -- can only deal with byte images\n";
00182     return false;
00183   }
00184 
00185   const vil_image_view<vxl_byte>& view2 =
00186     static_cast<const vil_image_view<vxl_byte>&>(view);
00187 
00188   // "compression makes no sense unless the section covers the whole image."
00189   // Relaxed slightly.. awf.
00190   // It will work if you send entire scan lines sequentially
00191   if (x0 != 0 || view2.ni() != jc->jobj.image_width) {
00192     vcl_cerr << __FILE__ << " : Can only compress complete scanlines\n";
00193     return false;
00194   }
00195   if (y0 != jc->jobj.next_scanline) {
00196     vcl_cerr << __FILE__ << " : Scanlines must be sent sequentially\n";
00197     return false;
00198   }
00199 
00200   // write each scanline
00201   if (view2.planestep() == 1 || view2.nplanes() == 1)
00202   {
00203     assert(view2.istep() > 0);
00204     assert(view2.istep() == jc->jobj.input_components); // bytes per pixel in the section
00205     for (unsigned int j=0; j<view2.nj(); ++j) {
00206       JSAMPLE const *scanline = (JSAMPLE const*)
00207         &view2(0,j);
00208       if (!jc->write_scanline(y0+j, scanline))
00209         return false;
00210     }
00211   }
00212   else
00213   {
00214     vil_memory_chunk_sptr chunk = new vil_memory_chunk(view2.ni()*view2.nplanes(), vil_pixel_format_component_format(vil_pixel_format_of(vxl_byte())));
00215     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);
00216     JSAMPLE *scanline = line.top_left_ptr();
00217 
00218     for (unsigned int j=0; j<view2.nj(); ++j)
00219     {
00220       // arrange data into componentwise form.
00221       for (unsigned i = 0; i < view2.ni(); ++i)
00222         for (unsigned p = 0; p < view2.nplanes(); ++p)
00223           line(i,0,p) = view2(i,j,p);
00224       if (!jc->write_scanline(y0+j, scanline))
00225         return false;
00226     }
00227   }
00228 
00229   return true;
00230 }
00231 
00232 //--------------------------------------------------------------------------------
00233 
00234 
00235 unsigned vil_jpeg_image::ni() const
00236 {
00237   if (jd) return jd->jobj.output_width;
00238   if (jc) return jc->jobj.image_width;
00239   return 0;
00240 }
00241 
00242 unsigned vil_jpeg_image::nj() const
00243 {
00244   if (jd) return jd->jobj.output_height;
00245   if (jc) return jc->jobj.image_height;
00246   return 0;
00247 }
00248 
00249 unsigned vil_jpeg_image::nplanes() const
00250 {
00251   if (jd) return jd->jobj.output_components;
00252   if (jc) return jc->jobj.input_components;
00253   return 0;
00254 }
00255 
00256 
00257 vil_pixel_format vil_jpeg_image::pixel_format() const
00258 {
00259   return VIL_PIXEL_FORMAT_BYTE;
00260 }
00261 
00262 
00263 char const *vil_jpeg_image::file_format() const
00264 {
00265   return jpeg_string;
00266 }
00267 
00268 //--------------------------------------------------------------------------------

Generated on Thu Jan 10 14:39:59 2008 for core/vil by  doxygen 1.4.4