ImageJpg.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <stdio.h>
00022 #include <math.h>
00023 
00024 #ifdef __cplusplus
00025 extern "C" { 
00026 #endif /* __cplusplus */
00027 
00028 #ifdef __DARWIN__
00029 #include <UnixImageIO/jpeglib.h>
00030 #else
00031 #include <jpeglib.h>
00032 #endif
00033 
00034 #ifdef __cplusplus
00035 }
00036 #endif
00037 
00038 #include <common/Defines.h>
00039 #include <image/ImageJpg.h>
00040 
00041 ImageJpg::ImageJpg() :
00042         width_(0), height_(0), bits_(0), alpha_(false),
00043         owner_(true)
00044 {
00045 
00046 }
00047 
00048 bool ImageJpg::loadFromFile(const char * filename, const char *alphafilename, bool invert)
00049 {
00050         ImageJpg bitmap;
00051         if (!bitmap.loadFromFile(filename)) return false;
00052         ImageJpg alpha;
00053         if (!alpha.loadFromFile(alphafilename)) return false;
00054 
00055         if (bitmap.getBits() && alpha.getBits() && 
00056                 bitmap.getWidth() == alpha.getWidth() &&
00057                 bitmap.getHeight() == alpha.getHeight())
00058         {
00059                 createBlankInternal(bitmap.getWidth(), bitmap.getHeight(), true);
00060                 unsigned char *bbits = bitmap.getBits();
00061                 unsigned char *abits = alpha.getBits();
00062                 unsigned char *bits = getBits();
00063                 for (int y=0; y<bitmap.getHeight(); y++)
00064                 {
00065                         for (int x=0; x<bitmap.getWidth(); x++)
00066                         {
00067                                 bits[0] = bbits[0];
00068                                 bits[1] = bbits[1];
00069                                 bits[2] = bbits[2];
00070 
00071                                 unsigned char avg = (unsigned char)(int(abits[0] + abits[1] + abits[2]) / 3);
00072                                 if (invert)
00073                                 {
00074                                         bits[3] = (unsigned char)(255 - avg);
00075                                 }
00076                                 else
00077                                 {
00078                                         bits[3] = avg;
00079                                 }
00080 
00081                                 bbits += 3;
00082                                 abits += 3;
00083                                 bits += 4;
00084                         }
00085                 }
00086         }
00087         return true;
00088 }
00089 
00090 ImageJpg::~ImageJpg()
00091 {
00092         clear();
00093 }
00094 
00095 void ImageJpg::clear()
00096 {
00097         if (owner_) delete [] bits_;
00098         bits_ = 0;
00099         width_ = 0;
00100         height_ = 0;
00101 }
00102 
00103 void ImageJpg::createBlankInternal(int width, int height, bool alpha, unsigned char fill)
00104 {
00105         clear();
00106         width_ = width;
00107         height_ = height;
00108         alpha_ = alpha;
00109         int bitsize = getComponents() * width * height;
00110 
00111         bits_ = new unsigned char[bitsize];
00112         memset(bits_, fill, bitsize);
00113 }
00114 
00115 bool ImageJpg::loadFromFile(const char * filename, bool readalpha)
00116 {
00117         FILE *file = fopen(filename, "rb");
00118         if (!file) return false;
00119 
00120         int read = 0;
00121         char buffer[256];
00122         NetBuffer netBuffer;
00123         while (read = fread(buffer, 1, 256, file))
00124         {
00125                 netBuffer.addDataToBuffer(buffer, read);
00126         }
00127         fclose(file);
00128 
00129         return loadFromBuffer(netBuffer, readalpha);
00130 }
00131 
00132 METHODDEF(void)
00133 init_source (j_decompress_ptr cinfo)
00134 {
00135 }
00136 
00137 METHODDEF(boolean)
00138 fill_input_buffer (j_decompress_ptr cinfo)
00139 {
00140         struct jpeg_source_mgr * src = cinfo->src;
00141         static JOCTET FakeEOI[] = { 0xFF, JPEG_EOI };
00142 
00143         /* Insert a fake EOI marker */
00144         src->next_input_byte = FakeEOI;
00145         src->bytes_in_buffer = 2;
00146 
00147         return TRUE;
00148 }
00149 
00150 METHODDEF(void)
00151 skip_input_data (j_decompress_ptr cinfo, long num_bytes)
00152 {
00153         struct jpeg_source_mgr * src = cinfo->src;
00154 
00155         if(num_bytes >= (long)src->bytes_in_buffer)
00156         {
00157                 fill_input_buffer(cinfo);
00158                 return;
00159         }
00160 
00161         src->bytes_in_buffer -= num_bytes;
00162         src->next_input_byte += num_bytes;
00163 }
00164 
00165 METHODDEF(void)
00166 term_source (j_decompress_ptr cinfo)
00167 {
00168   /* no work necessary here */
00169 }
00170 
00171 bool ImageJpg::loadFromBuffer(NetBuffer &buffer, bool readalpha)
00172 {
00173         struct jpeg_decompress_struct cinfo;
00174         struct jpeg_error_mgr jerr;
00175 
00176         cinfo.err = jpeg_std_error(&jerr);      
00177         jpeg_create_decompress(&cinfo);
00178 
00179         // Get the buffer reading entry points
00180         if (!cinfo.src)
00181         {
00182                 cinfo.src = (struct jpeg_source_mgr *)
00183                         (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
00184                                 sizeof(struct jpeg_source_mgr));
00185         }
00186         struct jpeg_source_mgr *src = cinfo.src;
00187 
00188         // Set up buffer reading functions
00189         src->init_source = init_source;
00190         src->fill_input_buffer = fill_input_buffer;
00191         src->skip_input_data = skip_input_data;
00192         src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
00193         src->term_source = term_source;
00194 
00195         // Set up buffer
00196         src->bytes_in_buffer = buffer.getBufferUsed();
00197         src->next_input_byte = (JOCTET *) buffer.getBuffer();
00198 
00199         jpeg_read_header(&cinfo, TRUE);
00200         jpeg_start_decompress(&cinfo);
00201 
00202         bool result = false;
00203         if ((cinfo.output_components == 3 && !readalpha) ||
00204                 (cinfo.output_components == 4 && readalpha))
00205         {
00206                 width_ = cinfo.output_width;
00207                 height_ = cinfo.output_height;
00208                 alpha_ = readalpha;
00209                 createBlankInternal(width_, height_, readalpha);
00210 
00211                 JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)
00212                         ((j_common_ptr) &cinfo, JPOOL_IMAGE, 
00213                                 cinfo.output_width * cinfo.output_components, 1);
00214 
00215                 while (cinfo.output_scanline < cinfo.output_height)
00216                 {
00217                         int currentLine = cinfo.output_scanline;
00218                         int lines = jpeg_read_scanlines(&cinfo, buffer, 1);
00219 
00220                         if (lines > 0)
00221                         {
00222                                 int destPos = cinfo.output_width * cinfo.output_components * 
00223                                         (cinfo.output_height - currentLine - 1);
00224                                 JSAMPLE *src = buffer[0];
00225                                 unsigned char *dest = &bits_[destPos];
00226 
00227                                 for (unsigned int i = 0; i < cinfo.output_width; ++i, 
00228                                         dest+=cinfo.output_components, src+=cinfo.output_components)
00229                                 {
00230                                         dest[0] = src[0];
00231                                         dest[1] = src[1];
00232                                         dest[2] = src[2];
00233                                         if (readalpha) dest[3] = src[3];
00234                                 }
00235                         }
00236                 }
00237 
00238                 result = true;
00239         }
00240 
00241         jpeg_finish_decompress(&cinfo);
00242         jpeg_destroy_decompress(&cinfo);
00243 
00244         return result;
00245 }

Generated on Mon Feb 16 15:14:50 2009 for Scorched3D by  doxygen 1.5.3