core/vil1/file_formats/vil1_jpeg.cxx

Go to the documentation of this file.
00001 // This is core/vil1/file_formats/vil1_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 
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> // CHAR_BIT
00018 #include <vcl_iostream.h>
00019 #include <vcl_cstring.h> // memcpy()
00020 
00021 #include <vil1/vil1_stream.h>
00022 #include <vil1/vil1_image.h>
00023 #include <vil1/vil1_property.h>
00024 
00025 //: the file probe, as a C function.
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   // 0xFF followed by 0xD8
00038   return ( (magic[0] == char(0xFF)) && (magic[1] == char(0xD8)) );
00039 }
00040 
00041 // static data
00042 static char const jpeg_string[] = "jpeg";
00043 
00044 //--------------------------------------------------------------------------------
00045 // class vil1_jpeg_file_format
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 // class vil1_jpeg_generic_image
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   // warn
00107   if (planes != 1)
00108     vcl_cerr << __FILE__ " : prototype has != 1 planes. ignored\n";
00109 
00110   // use same number of components as prototype, obviously.
00111   jc->jobj.input_components = components;
00112 
00113   // store size
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); // FIXME.
00121   assert(format == VIL1_COMPONENT_FORMAT_UNSIGNED_INT); // FIXME
00122 }
00123 
00124 vil1_jpeg_generic_image::~vil1_jpeg_generic_image()
00125 {
00126   // FIXME: I suspect there's a core leak here because jpeg_destroy() does not
00127   // free the vil1_jpeg_stream_source_mgr allocated in vil1_jpeg_stream_xxx_set()
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 //: decompressing from the vil1_stream to a section buffer.
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   // number of bytes per pixel
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; // failed
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 //: compressing a section onto the vil1_stream.
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   // "compression makes no sense unless the section covers the whole image."
00176   // Relaxed slightly.. awf.
00177   // It will work if you send entire scan lines sequentially
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   // bytes per pixel in the section
00188   unsigned bpp = jc->jobj.input_components;
00189 
00190   // write each scanline
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 //: assume only one plane
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 //--------------------------------------------------------------------------------

Generated on Sat Nov 22 05:08:28 2008 for core/vil1 by  doxygen 1.5.1