QValueVector<QColor> amaroK::readMood(const QString path) { debug() << "MakeMood: Reading mood file " << path << endl; QString filebase = path; QValueVector<QColor> theArray; filebase.truncate(filebase.findRev('.')); filebase += ".mood"; QString dotfilebase = filebase, homefilebase = filebase; dotfilebase.insert(filebase.findRev('/') + 1, '.'); homefilebase.replace('/', ','); homefilebase = ::locateLocal("data", "amarok/moods/" + homefilebase); QFile mood; if(QFile::exists(filebase)) mood.setName(filebase); if(QFile::exists(dotfilebase)) mood.setName(dotfilebase); if(QFile::exists(homefilebase)) mood.setName(homefilebase); if(mood.name() != "" && mood.open(IO_ReadOnly)) { int r, g, b, s = mood.size() / 3; debug() << "ReadMood: File opened. Proceeding to read contents... s=" << s << endl; QMemArray<int> huedist(360); int total = 0, mx = 0; for(int i = 0; i < 360; i++) huedist[i] = 0; theArray.resize(s); for(int i = 0; i < s; i++) { r = mood.getch(); g = mood.getch(); b = mood.getch(); theArray[i] = QColor(CLAMP(0, r, 255), CLAMP(0, g, 255), CLAMP(0, b, 255), QColor::Rgb); int h, s, v; theArray[i].getHsv(&h, &s, &v); if(h < 0) h = 0; else h = h % 360; huedist[h]++; if(mx < huedist[h]) mx = huedist[h]; } debug() << "ReadMood: File read. Maximum hue bin size = " << mx << endl; if(AmarokConfig::makeMoodier()) { debug() << "ReadMood: Making moodier!" << endl; int threshold, rangeStart = 0, rangeDelta = 359, sat = 100, val = 100; switch(AmarokConfig::alterMood()) { // Angry case 1: threshold = s / 360 * 9; rangeStart = 45; rangeDelta = -45; sat = 200; val = 100; break; // Frozen case 2: threshold = s / 360 * 1; rangeStart = 140; rangeDelta = 160; sat = 50; val = 100; break; // Happy default: threshold = s / 360 * 2; rangeStart = 0; rangeDelta = 359; sat = 150; val = 250; } debug() << "ReadMood: Appling filter t=" << threshold << ", rS=" << rangeStart << ", rD=" << rangeDelta << ", s=" << sat << "%, v=" << val << "%" << endl; for(int i = 0; i < 360; i++) if(huedist[i] > threshold) total++; debug() << "ReadMood: Total=" << total << endl; if(total < 360 && total > 0) { for(int i = 0, n = 0; i < 360; i++) huedist[i] = ((huedist[i] > threshold ? n++ : n) * rangeDelta / total + rangeStart) % 360; for(uint i = 0; i < theArray.size(); i++) { int h, s, v; theArray[i].getHsv(&h, &s, &v); if(h < 0) h = 0; else h = h % 360; if(h > 359) debug() << "ReadMood: Bad hue in array[" << i << "]: " << h << endl; theArray[i].setHsv(CLAMP(0, huedist[h], 359), CLAMP(0, s * sat / 100, 255), CLAMP(0, v * val / 100, 255)); } } } } debug() << "ReadMood: All done." << endl; return theArray; }
//-------------------------------------------------------------------------- // Parse the marker stream until SOS or EOI is seen; //-------------------------------------------------------------------------- int ExifData::ReadJpegSections (QFile & infile, ReadMode_t ReadMode) { int a; a = infile.getch(); if (a != 0xff || infile.getch() != M_SOI) { SectionsRead = 0; return false; } for(SectionsRead = 0; SectionsRead < MAX_SECTIONS-1; ) { int marker = 0; int got; unsigned int ll,lh; unsigned int itemlen; uchar * Data; for (a=0; a<7; a++) { marker = infile.getch(); if (marker != 0xff) break; if (a >= 6) { kdDebug(7034) << "too many padding bytes\n"; return false; } } if (marker == 0xff) { // 0xff is legal padding, but if we get that many, something's wrong. throw FatalError("too many padding bytes!"); } Sections[SectionsRead].Type = marker; // Read the length of the section. lh = (uchar) infile.getch(); ll = (uchar) infile.getch(); itemlen = (lh << 8) | ll; if (itemlen < 2) { throw FatalError("invalid marker"); } Sections[SectionsRead].Size = itemlen; Data = (uchar *)malloc(itemlen+1); // Add 1 to allow sticking a 0 at the end. Sections[SectionsRead].Data = Data; // Store first two pre-read bytes. Data[0] = (uchar)lh; Data[1] = (uchar)ll; got = infile.readBlock((char*)Data+2, itemlen-2); // Read the whole section. if (( unsigned ) got != itemlen-2) { throw FatalError("reading from file"); } SectionsRead++; switch(marker) { case M_SOS: // stop before hitting compressed data // If reading entire image is requested, read the rest of the data. if (ReadMode & READ_IMAGE) { unsigned long size; size = kMax( 0ul, infile.size()-infile.at() ); Data = (uchar *)malloc(size); if (Data == NULL) { throw FatalError("could not allocate data for entire image"); } got = infile.readBlock((char*)Data, size); if (( unsigned ) got != size) { throw FatalError("could not read the rest of the image"); } Sections[SectionsRead].Data = Data; Sections[SectionsRead].Size = size; Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER; SectionsRead ++; //HaveAll = 1; } return true; case M_EOI: // in case it's a tables-only JPEG stream kdDebug(7034) << "No image in jpeg!\n"; return false; case M_COM: // Comment section // pieczy 2002-02-12 // now the User comment goes to UserComment // so we can store a Comment section also in READ_EXIF mode process_COM(Data, itemlen); break; case M_JFIF: // Regular jpegs always have this tag, exif images have the exif // marker instead, althogh ACDsee will write images with both markers. // this program will re-create this marker on absence of exif marker. // hence no need to keep the copy from the file. free(Sections[--SectionsRead].Data); break; case M_EXIF: // Seen files from some 'U-lead' software with Vivitar scanner // that uses marker 31 for non exif stuff. Thus make sure // it says 'Exif' in the section before treating it as exif. if ((ReadMode & READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0) { process_EXIF((uchar *)Data, itemlen); // FIXME: This call // requires Data to be array of at least 8 bytes. Code // above only checks for itemlen < 2. } else { // Discard this section. free(Sections[--SectionsRead].Data); } break; case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: process_SOFn(Data, marker); //FIXME: This call requires Data to // be array of at least 8 bytes. Code above only checks for // itemlen < 2. break; default: break; } } return true; }