00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <math.h>
00023
00024 #ifdef __cplusplus
00025 extern "C" {
00026 #endif
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
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
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
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
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;
00193 src->term_source = term_source;
00194
00195
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 }