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
00029
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
00042 return (magic[0] == char(0xFF)) && (magic[1] == char(0xD8));
00043 }
00044
00045
00046 static char const jpeg_string[] = "jpeg";
00047
00048
00049
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
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 * , void * ) const
00091 {
00092
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);
00108
00109 stream->ref();
00110
00111
00112 jc->jobj.input_components = nplanes;
00113
00114
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
00125
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
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
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;
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
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
00189
00190
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
00201 if (view2.planestep() == 1 || view2.nplanes() == 1)
00202 {
00203 assert(view2.istep() > 0);
00204 assert(view2.istep() == jc->jobj.input_components);
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
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