/* * This file is part of RawTherapee. * * Created on: 20/nov/2010 */ #include #include #include #include #ifdef WIN32 #include #else #include #endif namespace rtengine{ extern Settings* settings; RawImage::RawImage( const Glib::ustring name ) :allocation(NULL) ,data(NULL) ,profile_data(NULL) ,filename(name) ,prefilters(0) { } RawImage::~RawImage() { if(ifp) fclose(ifp); if( image ) free(image); if(allocation){ delete [] allocation; allocation=NULL;} if(data){ delete [] data; data=NULL;} if(profile_data){ delete [] profile_data; profile_data=NULL;} } /* Similar to dcraw scale_colors for coeff. calculation, but without actual pixels scaling. * need pixels in data[][] available */ int RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, int *cblack_ ) { unsigned row, col, ur, uc, i, x, y, c, sum[8]; unsigned W = this->get_width(); unsigned H = this->get_height(); int val, dark, sat; double dsum[8], dmin, dmax; for (int c = 0; c < 4; c++){ cblack_[c] = this->get_cblack(c) + this->get_black(); pre_mul_[c] = this->get_pre_mul(c); } if ( this->get_cam_mul(0) == -1 ) { memset(dsum, 0, sizeof dsum); for (row = 0; row < H; row += 8) for (col = 0; col < W ; col += 8) { memset(sum, 0, sizeof sum); for (y = row; y < row + 8 && y < H; y++) for (x = col; x < col + 8 && x < W; x++) for (int c = 0; c < 3; c++) { if (this->isBayer()) { c = FC(y, x); val = data[y][x]; } else val = data[y][3*x+c]; if (val > this->get_white() - 25) goto skip_block; if ((val -= cblack_[c]) < 0) val = 0; sum[c] += val; sum[c + 4]++; if ( this->isBayer()) break; } for (c = 0; c < 8; c++) dsum[c] += sum[c]; skip_block: ; } for (int c = 0; c < 4; c++) if (dsum[c]) pre_mul_[c] = dsum[c + 4] / dsum[c]; }else{ memset(sum, 0, sizeof sum); for (row = 0; row < 8; row++) for (col = 0; col < 8; col++) { int c = FC(row, col); if ((val = white[row][col] - cblack_[c]) > 0) sum[c] += val; sum[c + 4]++; } if (sum[0] && sum[1] && sum[2] && sum[3]) for (int c = 0; c < 4; c++) pre_mul_[c] = (float) sum[c + 4] / sum[c]; else if (this->get_cam_mul(0) && this->get_cam_mul(2)){ pre_mul_[0] = this->get_cam_mul(0); pre_mul_[1] = this->get_cam_mul(1); pre_mul_[2] = this->get_cam_mul(2); pre_mul_[3] = this->get_cam_mul(3); }else fprintf(stderr, "Cannot use camera white balance.\n"); } if (pre_mul_[3] == 0) pre_mul_[3] = this->get_colors() < 4 ? pre_mul_[1] : 1; dark = this->get_black(); sat = this->get_white(); sat -= this->get_black(); for (dmin = DBL_MAX, dmax = c = 0; c < 4; c++) { if (dmin > pre_mul_[c]) dmin = pre_mul_[c]; if (dmax < pre_mul_[c]) dmax = pre_mul_[c]; } for (c = 0; c < 4; c++) scale_mul_[c] = (pre_mul_[c] /= dmax) * 65535.0 / sat; if (settings->verbose) { fprintf(stderr,"Scaling with darkness %d, saturation %d, and\nmultipliers", dark, sat); for (c = 0; c < 4; c++) fprintf(stderr, " %f", pre_mul[c]); fputc('\n', stderr); } } int RawImage::loadRaw (bool loadData, bool closeFile) { ifname = filename.c_str(); image = NULL; verbose = settings->verbose; oprof = NULL; ifp = gfopen (filename.c_str()); if (!ifp) return 3; thumb_length = 0; thumb_offset = 0; thumb_load_raw = 0; use_camera_wb = 0; highlight = 1; half_size = 0; //***************** Read ALL raw file info identify (); if (!is_raw) { fclose(ifp); ifp=NULL; return 2; } if (flip==5) this->rotate_deg = 270; else if (flip==3) this->rotate_deg = 180; else if (flip==6) this->rotate_deg = 90; else this->rotate_deg = 0; if( loadData ){ use_camera_wb = 1; shrink = 0; if (settings->verbose) printf ("Loading %s %s image from %s...\n", make, model, filename.c_str()); iheight = height; iwidth = width; // dcraw needs this global variable to hold pixel data image = (dcrawImage_t)calloc (height*width*sizeof *image + meta_length, 1); meta_data = (char *) (image + height*width); if(!image) return 200; if (setjmp (failure)) { if (image) free (image); fclose (ifp); return 100; } // Load raw pixels data fseek (ifp, data_offset, SEEK_SET); (this->*load_raw)(); // Load embedded profile if (profile_length) { profile_data = new char[profile_length]; fseek ( ifp, profile_offset, SEEK_SET); fread ( profile_data, 1, profile_length, ifp); } // Setting the black and cblack int i = cblack[3]; for (int c=0; c <3; c++) if (i > cblack[c]) i = cblack[c]; for (int c=0; c < 4; c++) cblack[c] -= i; black += i; } if( closeFile ){ fclose(ifp); ifp=NULL; } return 0; } unsigned short** RawImage::compress_image() { if( !image ) return NULL; if (filters) { if (!allocation) { allocation = new unsigned short[height * width]; data = new unsigned short*[height]; for (int i = 0; i < height; i++) data[i] = allocation + i * width; } } else { if (!allocation) { allocation = new unsigned short[3 * height * width]; data = new unsigned short*[height]; for (int i = 0; i < height; i++) data[i] = allocation + 3 * i * width; } } // copy pixel raw data: the compressed format earns space if (filters != 0) { for (int row = 0; row < height; row++) for (int col = 0; col < width; col++) this->data[row][col] = image[row * width + col][FC(row, col)]; } else { for (int row = 0; row < height; row++) for (int col = 0; col < width; col++) { this->data[row][3 * col + 0] = image[row * width + col][0]; this->data[row][3 * col + 1] = image[row * width + col][1]; this->data[row][3 * col + 2] = image[row * width + col][2]; } } free(image); // we don't need this anymore image=NULL; return data; } bool RawImage::is_supportedThumb() const { return ( (thumb_width * thumb_height) > 0 && ( write_thumb == &rtengine::RawImage::jpeg_thumb || write_thumb == &rtengine::RawImage::ppm_thumb || thumb_load_raw == &rtengine::RawImage::kodak_thumb_load_raw )); } bool RawImage::get_thumbSwap() const { return ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) ? true : false; } }; //namespace rtengine