/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2010-2011, Tomasz Sowa * All rights reserved. * */ #include #include "image.h" #include "utf8.h" #include "log.h" #include "system.h" #include "plugin.h" void Image::SetDb(Db * pdb) { db = pdb; } void Image::SetConfig(Config * pconfig) { config = pconfig; } void Image::SetSystem(System * psystem) { system = psystem; } // first thread (objects locked) void Image::Resize(const Item & item, size_t cx, size_t cy, int aspect_mode, int quality) { item_temp.type = WINIX_IMAGE_TYPE_RESIZE; item_temp.file = item; item_temp.cx = cx; item_temp.cy = cy; item_temp.aspect_mode = aspect_mode; item_temp.quality = quality; CheckParam(item_temp); image_tab.insert(image_tab.end(), item_temp); WakeUpThread(); } // first thread (objects locked) void Image::CreateThumb(const Item & item, size_t cx, size_t cy, int aspect_mode, int quality) { item_temp.type = WINIX_IMAGE_TYPE_CREATE_THUMB; item_temp.file = item; item_temp.cx = cx; item_temp.cy = cy; item_temp.aspect_mode = aspect_mode; item_temp.quality = quality; CheckParam(item_temp); image_tab.insert(image_tab.end(), item_temp); WakeUpThread(); } void Image::CheckParam(ImageItem & item) { if( item.aspect_mode < 1 ) item.aspect_mode = 1; if( item.aspect_mode > 7 ) item.aspect_mode = 7; if( item.quality < 0 ) item.quality = 0; if( item.quality > 100 ) item.quality = 100; if( item_temp.cx < 5 ) item_temp.cx = 5; if( item_temp.cy < 5 ) item_temp.cy = 5; if( item_temp.cx > 10000 ) item_temp.cx = 10000; if( item_temp.cy > 10000 ) item_temp.cy = 10000; } // second thread (objects locked) bool Image::SignalReceived() { return !image_tab.empty(); } // second thread (objects not locked) void Image::Do() { ImageTab::iterator i; bool end; Lock(); i = image_tab.begin(); Unlock(); do { Lock(); if( i != image_tab.end() ) { item_work = *i; image_tab.erase(i++); end = false; } else { end = true; } Unlock(); if( !end ) CreateImage(); } while( !end && !IsExitSignal() ); } void Image::Add(const std::wstring & in, TextStream & out) { Ezc::WideToUTF8(in, add_tempa); out << add_tempa; } void Image::EscapePath(const std::string & path, TextStream & out, bool clear_stream) { if( clear_stream ) out.Clear(); out << '"'; for(size_t i=0 ; i Change as per widthxheight but only if an image dimension exceeds a specified dimension. widthxheight< Change dimensions only if both image dimensions exceed specified dimensions. */ void Image::SelectAspect() { switch( item_work.aspect_mode ) { case WINIX_IMAGE_MODE_1: command << item_work.cx; break; case WINIX_IMAGE_MODE_3: command << item_work.cx << "x" << item_work.cy; break; case WINIX_IMAGE_MODE_4: command << '"' << item_work.cx << "x" << item_work.cy << "^\""; break; case WINIX_IMAGE_MODE_5: command << '"' << item_work.cx << "x" << item_work.cy << "!\""; break; case WINIX_IMAGE_MODE_6: command << '"' << item_work.cx << "x" << item_work.cy << ">\""; break; case WINIX_IMAGE_MODE_7: command << '"' << item_work.cx << "x" << item_work.cy << "<\""; break; case WINIX_IMAGE_MODE_2: default: command << "x" << item_work.cy; break; } } // second thread (objects locked) bool Image::CreateInputFileName() { if( system->MakeFilePath(item_work.file, src_path) ) { Ezc::WideToUTF8(src_path, input_file_name); return true; } else { log << log1 << "Image: cannot create a source path" << logend; return false; } } // second thread (objects locked) void Image::CreateTmpFileName() { stream_tmp_path.Clear(); stream_tmp_path << config->upload_dir << L"/tmp/image_" << std::time(0); Ezc::WideToUTF8(stream_tmp_path.Str(), tmp_file_name); } // second thread (objects are not locked) bool Image::CreateCommand() { Lock(); iq.SetAll(true, false); iq.WhereId(item_work.file.id); // !! skoro teraz i tak wczytujemy caly obiekt // to teraz w kolejce wystarczy zapamietywac tylko samo item.id (a nie caly obiekt item) // the file could have been changed especially when there is a long queue of files if( db->GetItem(item_work.file, iq) != WINIX_ERR_OK ) { Unlock(); return false; } if( !CreateInputFileName() ) { Unlock(); return false; } command.Clear(); Add(config->convert_cmd, command); command << " "; EscapePath(input_file_name, command, false); command << " -quiet -quality " << item_work.quality; if( item_work.type == WINIX_IMAGE_TYPE_RESIZE ) command << " -resize "; else command << " -strip -thumbnail "; SelectAspect(); CreateTmpFileName(); command << " "; EscapePath(tmp_file_name, command, false); log << log4 << "Image: running: " << command.Str() << logend; Unlock(); return true; } // second thread (objects are not locked) void Image::SaveImage() { bool moved = false; Lock(); // the file could have been changed especially when creating the image lasted too long iq.SetAll(true, false); iq.WhereId(item_work.file.id); if( db->GetItem(item_work.file, iq) == WINIX_ERR_OK ) { bool thumb = (item_work.type == WINIX_IMAGE_TYPE_CREATE_THUMB); if( system->MakeFilePath(item_work.file, dst_path, thumb, true, config->upload_dirs_chmod) ) { if( RenameFile(stream_tmp_path.Str(), dst_path) ) { if( thumb ) { item_work.file.has_thumb = true; db->EditHasThumbById(true, item_work.file.id); log << log3 << "Image: generated a thumbnail: " << dst_path << logend; plugin.Call(WINIX_CREATED_THUMB, &item_work.file); } else { log << log3 << "Image: image resized: " << dst_path << logend; plugin.Call(WINIX_IMAGE_RESIZED, &item_work.file); } moved = true; } else { log << log1 << "Image: cannot move a temporary file: " << stream_tmp_path.Str() << ", to: " << dst_path << logend; } } else { log << log1 << "Image: cannot create a destination path" << logend; } } if( !moved ) ::RemoveFile(stream_tmp_path.Str()); Unlock(); } // second thread (objects are not locked) void Image::CreateImage() { if( !CreateCommand() ) return; int res = std::system(command.CStr()); if( res == 0 ) { SaveImage(); } else { Lock(); log << log3 << "Image: some problems with creating an image" << ", 'convert' process returned: " << res << logend; Unlock(); } } // second thread (objects are not locked) // !! there is a problem with GIF files // Bus error (core dumped) /* #include "wand/MagickWand.h" // compiler options: // include: -I/usr/local/include/ImageMagick // link with: `MagickWand-config --ldflags --libs` void Image::CreateThumbnail() { Ezc::WideToUTF8(item_work.source, sourcea); Ezc::WideToUTF8(item_work.dst, dsta); MagickWandGenesis(); MagickWand * wand = NewMagickWand(); if( MagickReadImage(wand, sourcea.c_str()) ) { MagickThumbnailImage(wand, item_work.cx, item_work.cy); if( MagickWriteImage(wand, dsta.c_str()) ) { Lock(); log << log3 << "Image: created a thumbnail: " << dsta << logend; Unlock(); } } DestroyMagickWand(wand); MagickWandTerminus(); } */