Compare commits
	
		
			No commits in common. "d37e9e821a63f5e0dd8dfd878df782c5c745f0e8" and "4131bc5d3130e876d021e1cfa7fae4d3c3b86626" have entirely different histories.
		
	
	
		
			d37e9e821a
			...
			4131bc5d31
		
	
		
| @ -309,8 +309,8 @@ run(std::vector<Magick::Image> &images, const Config &config, | |||||||
| 			if (config.sigmoid) | 			if (config.sigmoid) | ||||||
| 				value = 1 / (1 + std::exp(-value)); | 				value = 1 / (1 + std::exp(-value)); | ||||||
| 			if (value > g.threshold) { | 			if (value > g.threshold) { | ||||||
| 				printf("%s\t%s\t%.2f\n", images.at(i).fileName().c_str(), | 				printf("%s\t%.2f\t%s\n", images.at(i).fileName().c_str(), | ||||||
| 					config.tags.at(t).c_str(), value); | 					value, config.tags.at(t).c_str()); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
							
								
								
									
										66
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								main.go
									
									
									
									
									
								
							| @ -41,9 +41,6 @@ import ( | |||||||
| 	"golang.org/x/image/webp" | 	"golang.org/x/image/webp" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // #include <unistd.h> |  | ||||||
| import "C" |  | ||||||
| 
 |  | ||||||
| var ( | var ( | ||||||
| 	db               *sql.DB // sqlite database | 	db               *sql.DB // sqlite database | ||||||
| 	galleryDirectory string  // gallery directory | 	galleryDirectory string  // gallery directory | ||||||
| @ -1418,11 +1415,7 @@ func syncPostProcess(c *syncContext, info syncFileInfo) error { | |||||||
| 	case info.err != nil: | 	case info.err != nil: | ||||||
| 		// * → error | 		// * → error | ||||||
| 		if ee, ok := info.err.(*exec.ExitError); ok { | 		if ee, ok := info.err.(*exec.ExitError); ok { | ||||||
| 			message := string(ee.Stderr) | 			syncPrintf(c, "%s: %s", info.fsPath, ee.Stderr) | ||||||
| 			if message == "" { |  | ||||||
| 				message = ee.String() |  | ||||||
| 			} |  | ||||||
| 			syncPrintf(c, "%s: %s", info.fsPath, message) |  | ||||||
| 		} else { | 		} else { | ||||||
| 			return info.err | 			return info.err | ||||||
| 		} | 		} | ||||||
| @ -2179,13 +2172,8 @@ func makeThumbnail(load bool, pathImage, pathThumb string) ( | |||||||
| 		return 0, 0, err | 		return 0, 0, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// This is still too much, but it will be effective enough. |  | ||||||
| 	memoryLimit := strconv.FormatInt( |  | ||||||
| 		int64(C.sysconf(C._SC_PHYS_PAGES)*C.sysconf(C._SC_PAGE_SIZE))/ |  | ||||||
| 			int64(len(taskSemaphore)), 10) |  | ||||||
| 
 |  | ||||||
| 	// Create a normalized thumbnail. Since we don't particularly need | 	// Create a normalized thumbnail. Since we don't particularly need | ||||||
| 	// any complex processing, such as surrounding metadata, | 	// any complex processing, such as surrounding of metadata, | ||||||
| 	// simply push it through ImageMagick. | 	// simply push it through ImageMagick. | ||||||
| 	// | 	// | ||||||
| 	//  - http://www.ericbrasseur.org/gamma.html | 	//  - http://www.ericbrasseur.org/gamma.html | ||||||
| @ -2197,17 +2185,8 @@ func makeThumbnail(load bool, pathImage, pathThumb string) ( | |||||||
| 	// | 	// | ||||||
| 	// TODO: See if we can optimize resulting WebP animations. | 	// TODO: See if we can optimize resulting WebP animations. | ||||||
| 	// (Do -layers optimize* apply to this format at all?) | 	// (Do -layers optimize* apply to this format at all?) | ||||||
| 	cmd := exec.Command("magick", "-limit", "thread", "1", | 	cmd := exec.Command("magick", "-limit", "thread", "1", pathImage, | ||||||
| 
 | 		"-coalesce", "-colorspace", "RGB", "-auto-orient", "-strip", | ||||||
| 		// Do not invite the OOM killer, a particularly unpleasant guest. |  | ||||||
| 		"-limit", "memory", memoryLimit, |  | ||||||
| 
 |  | ||||||
| 		// ImageMagick creates files in /tmp, but that tends to be a tmpfs, |  | ||||||
| 		// which is backed by memory. The path could also be moved elsewhere: |  | ||||||
| 		// -define registry:temporary-path=/var/tmp |  | ||||||
| 		"-limit", "map", "0", "-limit", "disk", "0", |  | ||||||
| 
 |  | ||||||
| 		pathImage, "-coalesce", "-colorspace", "RGB", "-auto-orient", "-strip", |  | ||||||
| 		"-resize", "256x128>", "-colorspace", "sRGB", | 		"-resize", "256x128>", "-colorspace", "sRGB", | ||||||
| 		"-format", "%w %h", "+write", pathThumb, "-delete", "1--1", "info:") | 		"-format", "%w %h", "+write", pathThumb, "-delete", "1--1", "info:") | ||||||
| 
 | 
 | ||||||
| @ -2258,10 +2237,7 @@ func cmdThumbnail(fs *flag.FlagSet, args []string) error { | |||||||
| 		w, h, err := makeThumbnail(*load, pathImage, pathThumb) | 		w, h, err := makeThumbnail(*load, pathImage, pathThumb) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			if ee, ok := err.(*exec.ExitError); ok { | 			if ee, ok := err.(*exec.ExitError); ok { | ||||||
| 				if message = string(ee.Stderr); message != "" { | 				return string(ee.Stderr), nil | ||||||
| 					return message, nil |  | ||||||
| 				} |  | ||||||
| 				return ee.String(), nil |  | ||||||
| 			} | 			} | ||||||
| 			return "", err | 			return "", err | ||||||
| 		} | 		} | ||||||
| @ -2414,29 +2390,14 @@ func cmdDhash(fs *flag.FlagSet, args []string) error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Commits are very IO-expensive in both WAL and non-WAL SQLite, | 	stmt, err := db.Prepare(`UPDATE image SET dhash = ? WHERE sha1 = ?`) | ||||||
| 	// so write this in one go. For a middle ground, we could batch the updates. |  | ||||||
| 	tx, err := db.Begin() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	defer tx.Rollback() |  | ||||||
| 
 |  | ||||||
| 	// Mild hack: upgrade the transaction to a write one straight away, |  | ||||||
| 	// in order to rule out deadlocks (preventable failure). |  | ||||||
| 	if _, err := tx.Exec(`END TRANSACTION; |  | ||||||
| 		BEGIN IMMEDIATE TRANSACTION`); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	stmt, err := tx.Prepare(`UPDATE image SET dhash = ? WHERE sha1 = ?`) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	defer stmt.Close() | 	defer stmt.Close() | ||||||
| 
 | 
 | ||||||
| 	var mu sync.Mutex | 	var mu sync.Mutex | ||||||
| 	err = parallelize(hexSHA1, func(sha1 string) (message string, err error) { | 	return parallelize(hexSHA1, func(sha1 string) (message string, err error) { | ||||||
| 		hash, err := makeDhash(sha1) | 		hash, err := makeDhash(sha1) | ||||||
| 		if errors.Is(err, errIsAnimation) { | 		if errors.Is(err, errIsAnimation) { | ||||||
| 			// Ignoring this common condition. | 			// Ignoring this common condition. | ||||||
| @ -2450,10 +2411,6 @@ func cmdDhash(fs *flag.FlagSet, args []string) error { | |||||||
| 		_, err = stmt.Exec(int64(hash), sha1) | 		_, err = stmt.Exec(int64(hash), sha1) | ||||||
| 		return "", err | 		return "", err | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	return tx.Commit() |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // --- Main -------------------------------------------------------------------- | // --- Main -------------------------------------------------------------------- | ||||||
| @ -2495,8 +2452,6 @@ func usage() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
| 	threads := flag.Int("threads", -1, "level of parallelization") |  | ||||||
| 
 |  | ||||||
| 	// This implements the -h switch for us by default. | 	// This implements the -h switch for us by default. | ||||||
| 	// The rest of the handling here closely follows what flag does internally. | 	// The rest of the handling here closely follows what flag does internally. | ||||||
| 	flag.Usage = usage | 	flag.Usage = usage | ||||||
| @ -2522,12 +2477,7 @@ func main() { | |||||||
| 		fs.PrintDefaults() | 		fs.PrintDefaults() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if *threads > 0 { | 	taskSemaphore = newSemaphore(runtime.NumCPU()) | ||||||
| 		taskSemaphore = newSemaphore(*threads) |  | ||||||
| 	} else { |  | ||||||
| 		taskSemaphore = newSemaphore(runtime.NumCPU()) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	err := cmd.handler(fs, flag.Args()[1:]) | 	err := cmd.handler(fs, flag.Args()[1:]) | ||||||
| 
 | 
 | ||||||
| 	// Note that the database object has a closing finalizer, | 	// Note that the database object has a closing finalizer, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user