溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

利用java怎么根據(jù)圖片中綠色像素的多少進行排序

發(fā)布時間:2021-03-05 14:38:47 來源:億速云 閱讀:160 作者:Leah 欄目:開發(fā)技術

本篇文章為大家展示了利用java怎么根據(jù)圖片中綠色像素的多少進行排序,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

Java是什么

Java是一門面向對象編程語言,可以編寫桌面應用程序、Web應用程序、分布式系統(tǒng)和嵌入式系統(tǒng)應用程序。

1.先給大家看看主方法里面都有一些什么內容

public static void main(String[] args) {
		HashMap<File, Object> imageMap = new HashMap<File, Object>();//用hashMap將文件和對應的像素點數(shù)量裝到一起
		File fileDir = new File("D:\\Download\\TestFile");//將要進行排序的文件目錄
		File[] listFiles = fileDir.listFiles();
		for (File readFile : listFiles) {
			getImagePixel(readFile, imageMap);//獲取圖片的綠色像素點數(shù)量的多少
		}
		
		HashMapSortUtils hashMapSortUtils = new HashMapSortUtils(imageMap, 1, 3, "Mus");
		LinkedHashMap<File,Object> sortFileMap = hashMapSortUtils.sortFileMap();//將圖片按照像素點的數(shù)量進行排序
		hashMapSortUtils.renameFiles(sortFileMap);//將排好序的文件重命名(不然離開控制臺就看不到文件的排序了>o<)
		
		System.out.println(imageMap);//這里只是用來看具體像素點有多少的,并沒有實際的意義
	}

是不是很簡單呢?跟大象裝冰箱一樣,只有三個步驟:
1.將文件目錄下的所有圖片含有的綠色像素點全部讀取出來,然后將對應的文件名和像素點個數(shù)暫存在HashMap里;
2.將圖片根據(jù)綠色像素點的多少進行排序;
3.將排好序的圖片重命名,然后進行排序輸出(Tips:文件會進行重命名的,所有不要直接在源文件上直接玩喔,注意文件的備份);

好了,那我們就直接開始看每個方法具體是怎樣實現(xiàn)的吧,按順序進行講解?。ㄒ韵麓蠹揖妥⒁饪创a中的注釋了,不再做重復的解釋了)

2.讀取圖片像素點的方法

private static HashMap<File, Object> getImagePixel(File readFile, HashMap<File, Object> imageMap) {
		int red = 0;//記錄像素點的紅色
		int green = 0;//記錄像素點的綠色
		int blue = 0;//記錄像素點的藍色
		int counter = 0;//程序計數(shù)器
		
		BufferedImage bi = null;
		try {
			bi = ImageIO.read(readFile);//通過ImageIO來讀取圖片,以便獲取圖片的RGB信息
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		int width = bi.getWidth();//獲取圖片的寬度
		int height = bi.getHeight();//獲取圖片的高度
		int minx = bi.getMinX();//獲取圖片的坐標起點x軸
		int miny = bi.getMinY();//獲取圖片的坐標起點y軸
		
		for(int i = minx; i < width; i++){
			for(int j = miny; j < height; j++){
				int pixel = bi.getRGB(i, j);
				red = (pixel & 0xff0000) >> 16;//過濾掉圖片的綠色和藍色
				green = (pixel & 0xff00) >> 8;//過濾掉圖片的綠色
				blue = (pixel & 0xff);//最后剩下的就是藍色啦
				
				if(green - red > 30 && green - blue > 30){//綠色的范圍
					counter++;
				}
			}
		}
		imageMap.put(readFile, counter);//將文件和像素點的個數(shù)記錄到HashMap中
		
		return imageMap;
	}

3.將圖片按照像素點的數(shù)量進行排序

由于排序不光在這里可以使用,在其他情況下也可能會使用到(比如說根據(jù)文件的創(chuàng)建時間進行排序,都可以用到排序的)。所以我將排序寫成了一個抽象類,其他情況下只需要繼承這個抽象類,然后具體實現(xiàn)自己想要實現(xiàn)的方法就行了!具體的現(xiàn)如下:

抽象類:

package readcolor;

import java.io.File;
import java.util.HashMap;
import java.util.LinkedHashMap;

public abstract class HashMapSortUtil {
	private HashMap<File, Object> sortMap;//全局變量Map,就是主方法需要傳過來進行排序的Map 
	private String prefix;//前綴,用來命名自己的文件 ==> Mus
	
	public abstract LinkedHashMap<File, Object> sortFileMap();//進行排序的方法
	
	public abstract void renameFiles(LinkedHashMap<File, Object> linkedTimeMap);//重命名的方法

	public HashMap<File, Object> getSortMap() {
		return sortMap;
	}

	public void setSortMap(HashMap<File, Object> sortMap) {
		this.sortMap = sortMap;
	}

	public String getPrefix() {
		return prefix;
	}

	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}
}

子類:

package readcolor;

import java.io.File;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Set;

public class HashMapSortUtils extends HashMapSortUtil{
	private int counter;//計數(shù)器,默認從多少開始進行命名 ==> 1
	private int nameLength;//命名的長度,其實就是計數(shù)器之前需要添加幾個0 ==> 3
	private int nameExpansion = 0;//記錄名字超長了需要進行擴容的次數(shù)
	//prefix(在父類里面),counter,nameLength組成的結果就是對應的Mus001
	private HashMap<File, File> tempFileMap = new HashMap<File, File>();//記錄在進行重命名時,目標文件有重復時,將源文件拷貝出來與將要命名的名字記錄到HashMap里面
	
	public HashMapSortUtils() {//構造方法
		super();
	}
	
	public HashMapSortUtils(HashMap<File, Object> sortMap, Integer counter, Integer nameLength, String prefix) {//構造方法
		super();
		super.setSortMap(sortMap);
		super.setPrefix(prefix);
		this.counter = counter;
		this.nameLength = nameLength;
	}

	/**
	 * 將圖片按照像素點個數(shù)進行排序的方法
	 * 參數(shù):無
	 * 返回值:無
	 * */
	@Override
	public LinkedHashMap<File, Object> sortFileMap() {
		LinkedHashMap<File,Object> linkedHashMap = new LinkedHashMap<File, Object>();
		Set<Entry<File, Object>> mapEntries = super.getSortMap().entrySet();//將傳進來需要進行排序的HashMap獲取到每個節(jié)點
		LinkedList<Entry<File, Object>> timeList = new LinkedList<Entry<File, Object>>(mapEntries);//將每個節(jié)點放到List集合中,方便利用Collections的方法進行排序
		Collections.sort(timeList, new Comparator<Entry<File, Object>>() {//利用Comparator接口進行排序

			@Override
			public int compare(Entry<File, Object> o1, Entry<File, Object> o2) {
				if(o1.getValue() == o2.getValue()){//如果兩個文件的綠色像素點相同,就用文件的名字進行比較
					return o2.getKey().compareTo(o1.getKey());
				}
				return ((Integer) o2.getValue()).compareTo((Integer)o1.getValue());//利用文件的綠色像素點進行比較
			}
		});
		
		
		for (Entry<File, Object> entry : timeList) {//將排好序之后的文件放到LinkedHashMap中,因為如果方法HashMap中的話,你會發(fā)現(xiàn)它的順序又是亂的了-o-
			linkedHashMap.put(entry.getKey(), entry.getValue());
		}
		return linkedHashMap;
	}

	/**
	 * 重命名文件的方法
	 * 參數(shù):linkedTimeMap:需要進行文件重命名的HashMap
	 * 返回值:無
	 * */
	
	@Override
	public void renameFiles(LinkedHashMap<File, Object> linkedTimeMap) {
		Set<Entry<File,Object>> entrySet = linkedTimeMap.entrySet();
		for (Entry<File, Object> entry : entrySet) {
			renameFile(entry.getKey(), createFileName(entry.getKey())/*根據(jù)之前設置文件的名字(counter、nameLength、prefix)生成文件名*/);//重命名文件
		}
		//最后重命名剩下的源文件的備份文件
		renameTempFiles();
	}

	/**
	 * 根據(jù)之前設置文件的名字(counter、nameLength、prefix)生成文件名
	 * 參數(shù):oldFile:源文件
	 * 返回值:生成名字之后的文件
	 * */
	private File createFileName(File oldFile) {
		//通過父類獲取到prefix
		String prefix = super.getPrefix();
		//獲取結束
		String newFileName = "";
		newFileName += prefix;//先將前綴拼接上
		int nameLen = String.valueOf(counter).length();//獲取計數(shù)器的長度
		if(nameLen > nameLength){//如果計數(shù)器超長了,那么命名的長度(nameLength)就需要進行擴容,不然會出現(xiàn)文件名重復的情況
			nameLength++;
			nameExpansion++;//這里記錄是因為,當后面的操作出現(xiàn)錯誤時,這里可能需要將原來的長度進行恢復
		}
		
		if(nameLen <= nameLength){
			int d_Value = String.valueOf(Math.pow(10, nameLength) - 1).length() - String.valueOf(counter).length() - 2;//計算需要填補的0的個數(shù),這里減2是因為去除double數(shù)據(jù)后面的.0
			for (int i = 0; i < d_Value; i++) {
				newFileName += "0";
			}
		}
		newFileName += counter;//將計數(shù)器添加到名字上
		
		String oldFileName = oldFile.getName();//獲取源文件的名字
		String dirName = oldFile.getParentFile().getAbsolutePath();//獲取源文件的上級文件夾的路徑
		File newFile = new File(dirName + File.separator + newFileName + oldFileName.substring(oldFileName.lastIndexOf(".")));//利用新的文件名生成文件
		counter++;//計數(shù)器需要進行+1
		return newFile;
	}
	
	/**
	 * 將源文件重命名為新文件的名字
	 * 參數(shù):oldFile:源文件, newFile:新文件
	 * 返回值:無
	 * */
	private void renameFile(File oldFile, File newFile) {
		//=================如果源文件和新文件都存在,并且源文件和新文件的名字不相同,那么就需要將源文件備份處理,等其他文件重命名完之后再執(zhí)行這類文件的重命名操作=================
		if(oldFile.exists() && oldFile.isFile() && newFile.exists() && newFile.isFile()){
			if(!newFile.getName().equals(oldFile.getName())){
				//===============================將源文件做備份處理===============================
				File oldFileTemp = null;
				int fileTempCounter = 0;
				//使用do...while...循環(huán)確保暫存文件中沒有重復的名字
				do{
					oldFileTemp = new File(oldFile.getAbsolutePath() + fileTempCounter + System.currentTimeMillis());
					fileTempCounter++;
				}while(oldFileTemp.exists() && oldFileTemp.isFile());
				
				//將源文件的內容復制到備份文件中
				try{
					new FileServiceImpl().copyFile(oldFile, oldFileTemp);
				}catch (Exception e){
					e.printStackTrace();
				}
				//刪除源文件
				oldFile.delete();
				//將源文件的備份文件和源文件需要重命名的名字記錄到HashMap里面,最后進行這部分文件的命名操作
				tempFileMap.put(oldFileTemp, newFile);
				return;
			}
		}
		
		//如果目標文件不存在或者目標文件名與源文件名相同,就直接進行重命名的操作
		if(oldFile.exists() && oldFile.isFile()){
			if(oldFile.renameTo(newFile)){
				System.out.println("重命名成功:" + oldFile.getAbsolutePath() + "==>" + newFile.getAbsolutePath());
				return;
			}
		}
		
		//重命名失敗就將計數(shù)器減一,并且將命名的長度還原到原來的長度
		System.out.println("====================================重命名失?。?quot; + oldFile.getAbsolutePath() + "====================================");
		counter--;
		nameLength -= nameExpansion;
	}
	
	/**
	 * 重命名剩下的源文件的備份文件
	 * 參數(shù):無
	 * 返回值:無
	 * */
	private void renameTempFiles() {
		Set<Entry<File, File>> entrySet = tempFileMap.entrySet();
		for (Entry<File, File> entry : entrySet) {
			//調用重命名的方法進行重命名
			renameFile(entry.getKey(), entry.getValue());
		}
	}
	
	public int getCounter() {
		return counter;
	}

	public void setCounter(int counter) {
		this.counter = counter;
	}

	public int getNameLength() {
		return nameLength;
	}

	public void setNameLength(int nameLength) {
		this.nameLength = nameLength;
	}
	
}

由于counter(計數(shù)器)和nameLength(命名的長度)在進行排序和文件重命名的時候會頻繁的使用到,因此我把他們放到了子類里面,避免多次調用父類的getter和setter方法。雖然我代碼里面注釋寫得很清楚,但是還是有一些小伙伴不習慣看注釋,那我稍微做一下解釋,但是代碼的邏輯還是要大家下來看一下!如果在博客上不太方便的話,可以直接copy到eclipse里面或者idea里面進行邏輯的分析!

(1)在主方法或其他方法需要調用到這個類型,可以直接利用該類的構造方法來調用到這個類:

public HashMapSortUtils(HashMap<File, Object> sortMap, Integer counter, Integer nameLength, String prefix){
	......
}

這個構造方法會將需要進行排序和重命名的HashMap加載到該類的成員變量中,該類所有方法都可以調用該HashMap,并且計數(shù)器開始的位置(counter)、命名的長度(nameLength)、命名前綴(prefix)都加載到成員變量中,其中HashMap和前綴屬于父類的變量。(相信大多數(shù)人都知道,我就亂解釋一番了。。。)
(2)將傳進來的HashMap進行排序的方法:

public LinkedHashMap<File, Object> sortFileMap() {
	......
}

該方法就是利用java工具類Collections下面的sort方法進行排序,需要注意的是,最后之所以返回的是一個LinkedHashMap是因為HashMap是無序的,如果排完序還是用HashMap裝排序的結果,那么就有可能沒有達到排序預期的效果

(3)將排好序的HashMap中的文件重命名的方法:

public void renameFiles(LinkedHashMap<File, Object> linkedTimeMap) {
	......
}

該方法主要分為兩個步驟:a.利用createFileName方法將之前設置好的prefix(前綴)、nameLength(命名的長度)、counter(計數(shù)器)組成新的名字;b.將HashMap中所有的entry節(jié)點利用renameFile方法進行判斷是否可以直接重命名,如果可以直接重命名就直接重命名,如果需要重新命名的文件已經存在就將源文件copy一份出來,然后將拷貝文件和新的名字方法一個HashMap中,等到程序的第c步才執(zhí)行這部分文件的重命名!c.將之前未進行重命名的源文件進利用renameTempFiles方法行統(tǒng)一的重命名!

4.文件操作的工具類

文件操作是一個公共的類,進行文件的復制、刪除、獲取所有文件、創(chuàng)建文件夾等等,都可以寫做一個公共的方法,大家可以自行去了解這個類的作用,這里不再過多的贅述(嘻嘻,又可以偷波懶了),不過我這里是錯誤的示范,我用接口的方式來實現(xiàn)的,真正的生產中是不會這樣做的,因為文件操作是基本上不會變的,這里我只是想單純的聯(lián)系一下接口的操做,那么廢話不多說,直接上代碼,都是文件操作的基礎代碼:

文件操作的接口:

package readcolor;

import java.io.File;
import java.util.List;

public interface FileService {
	void copyFile(String sourcePath, String targetPath) throws Exception;
	
	void copyFile(File sourceFile, File targetFile) throws Exception;
	
	void mkDirs(String path) throws Exception;
	
	List<File> getAllFiles(String sourcePath);
	
	void removeFiles(String path);
	
	void removeFiles(File sourceFile);
}

文件操作的實現(xiàn)類:

package readcolor;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

public class FileServiceImpl implements FileService{

	@Override
	public void copyFile(String sourcePath, String targetPath) throws Exception {
		copyFile(new File(sourcePath), new File(targetPath));
		
	}

	@Override
	public void copyFile(File sourceFile, File targetFile) throws Exception {
		FileInputStream fis = new FileInputStream(sourceFile);
		FileOutputStream fos = new FileOutputStream(targetFile);
		
		byte[] buffer = new byte[1024];
		int len = 0;
		
		while((len = fis.read(buffer)) != -1){
			fos.write(buffer, 0, len);
			fos.flush();
		}
		
		fos.close();
		fis.close();
	}

	@Override
	public void mkDirs(String path) throws Exception {
		File destFile = new File(path);
		if(!destFile.exists()){
			destFile.mkdirs();
		}
	}

	@Override
	public List<File> getAllFiles(String sourcePath) {
		ArrayList<File> files = new ArrayList<File>();
		File file = new File(sourcePath);
		if(file.exists() && !file.isHidden()){
			if(file.isFile()){
				files.add(file);
			}
			
			if(file.isDirectory()){
				File[] fs = file.listFiles();
				for (File f : fs) {
					if(!f.isHidden()){
						if(f.isFile()){
							files.add(file);
						}
						
						if(f.isDirectory()){
							files.addAll(getAllFiles(sourcePath + File.separator + f.getName()));
						}
					}
				}
			}
		}
		return files;
	}

	@Override
	public void removeFiles(String path) {
		removeFiles(new File(path));
	}

	@Override
	public void removeFiles(File sourceFile) {
		if (!sourceFile.isDirectory()){
			if(sourceFile.delete()) System.out.println("刪除文件:" + sourceFile.getAbsolutePath() + "成功");
		}else{
			File[] files = sourceFile.listFiles();
			
			for (File file : files) {
				if(file.isDirectory()){
					removeFiles(file);
					if(file.delete()) System.out.println("刪除文件夾:" + file.getAbsolutePath() + "成功");
				}else{
					if(file.delete()) System.out.println("刪除文件:" + file.getAbsolutePath() + "成功");
				}
			}
		}
	}
}

好的,一切準備就緒,那我們直接開始運行代碼,看看效果如何:

先準備好圖片:

利用java怎么根據(jù)圖片中綠色像素的多少進行排序

然后設置好文件的路徑:

利用java怎么根據(jù)圖片中綠色像素的多少進行排序

運行java程序:

利用java怎么根據(jù)圖片中綠色像素的多少進行排序

可以看到所有的文件都已經重新排序,并且已經進行重命名了,看看實際的效果:

利用java怎么根據(jù)圖片中綠色像素的多少進行排序

是不是感覺前面的圖片要稍微綠一點呢?該程序可以進行重復執(zhí)行的,暫時沒有出現(xiàn)命名失敗的情況,如果有小伙伴試了然后報錯了,記得留言喔,我看看是啥問題,然后看看能不能再優(yōu)化一下。。。(聞到了頭發(fā)掉落的氣息)

總結

最后,我們可以稍微改動幾行代碼,然后將所有的圖片只輸出綠色像素點來做一個直觀的感受:

package readcolor;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;

import javax.imageio.ImageIO;

public class ReadColor {
	private static int count = 0;
	public static void main(String[] args) {
		HashMap<File, Object> imageMap = new HashMap<File, Object>();//用hashMap將文件和對應的像素點數(shù)量裝到一起
		File fileDir = new File("D:\\Download\\TestFile");//將要進行排序的文件目錄
		File[] listFiles = fileDir.listFiles();
		for (File readFile : listFiles) {
			getImagePixel(readFile, imageMap);//獲取圖片的綠色像素點數(shù)量的多少
		}
		
		HashMapSortUtils hashMapSortUtils = new HashMapSortUtils(imageMap, 1, 3, "Mus");
		LinkedHashMap<File,Object> sortFileMap = hashMapSortUtils.sortFileMap();//將圖片按照像素點的數(shù)量進行排序
		hashMapSortUtils.renameFiles(sortFileMap);//將排好序的文件重命名(不然離開控制臺就看不到文件的排序了>o<)
		
		System.out.println(imageMap);
	}

	private static HashMap<File, Object> getImagePixel(File readFile, HashMap<File, Object> imageMap) {
		int red = 0;//記錄像素點的紅色
		int green = 0;//記錄像素點的綠色
		int blue = 0;//記錄像素點的藍色
		int counter = 0;//程序計數(shù)器
		
		BufferedImage bi = null;
		try {
			bi = ImageIO.read(readFile);//通過ImageIO來讀取圖片,以便獲取圖片的RGB信息
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		int width = bi.getWidth();//獲取圖片的寬度
		int height = bi.getHeight();//獲取圖片的高度
		int minx = bi.getMinX();//獲取圖片的坐標起點x軸
		int miny = bi.getMinY();//獲取圖片的坐標起點y軸
		
		for(int i = minx; i < width; i++){
			for(int j = miny; j < height; j++){
				int pixel = bi.getRGB(i, j);
				red = (pixel & 0xff0000) >> 16;//過濾掉圖片的綠色和藍色
				green = (pixel & 0xff00) >> 8;//過濾掉圖片的綠色
				blue = (pixel & 0xff);//最后剩下的就是藍色啦
				
				if(green - red > 30 && green - blue > 30){//綠色的范圍
					counter++;
				}else{
					bi.setRGB(i, j, 0xffffff);
				}
			}
		}
		imageMap.put(readFile, counter);//將文件和像素點的個數(shù)記錄到HashMap中
		
		try {
			ImageIO.write(bi, "jpg", new File("D:\\Download\\TestFile1\\" + count +".jpg"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		count++;
		return imageMap;
	}
}

將圖片的非綠色像素點修改為白色,然后存到一個新的文件夾里,看看是什么效果:

利用java怎么根據(jù)圖片中綠色像素的多少進行排序

上述內容就是利用java怎么根據(jù)圖片中綠色像素的多少進行排序,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI