[英]Shifting a pixel image left and right
我有一組數組(例如“像素”-RGB表示)
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(1,1,1)(1,1,1)(1,1,1)(1,1,1)
(2,2,2)(2,2,2)(2,2,2)(2,2,2)
我想左右移動列,上/下移動行。 例如:
ShiftCol + 2將產生輸出:
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(0,0,0)(0,0,0)(1,1,1)(1,1,1)
(0,0,0)(0,0,0)(2,2,2)(2,2,2)
ShiftRow-1將產生輸出:(在ShiftCol +2之后)
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(0,0,0)(0,0,0)(1,1,1)(1,1,1)
(在上面的輸出中發生的是:第一行移至第二行,第二行移至第三行,第一行變為黑色(僅為零),第三行僅被第二行替換。
ShiftCol-1將產生輸出:
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(0,0,0)(1,1,1)(1,1,1)(0,0,0)
我只需要您的幫助,向我展示如何“移動”每列到右側,就足夠了。 我設法做到的是,當調用ShiftCol +2時,第一列向右移動2列(並出現在第三列),而前兩列變成(0,0,0)黑色顏色。 問題是我不知道如何根據被稱為向右移動的數字將每列向右移動-例如-如果我調用ShiftCol(2)並且像素圖像數組為3x4,如您在輸出應該發生的結果是:第一列將向右移動兩次-第三列,第一列將變為黑色(0,0,0),第二列也將向右移動兩次並將變為第四欄。 第三和第四列將僅由第一和第二列替換。
如果您僅以某種方式指導我如何進行管理就足夠了,無論如何,您僅可以專注於RGBImage類中的“ ShiftCol”方法,您將在代碼中看到到目前為止我已經完成的工作。 提前謝謝!
*請用代碼保持答案簡單。 我只學習了for循環,while循環,if語句,數組..我不想在該項目中使用任何其他高級材料。
這是我的代碼:
RGBColor類:
public class RGBColor {
/**
* attributes: red, green and blue component of a color.
*/
private int _red,_green,_blue;
/**
* final variables.
*/
private final int MAX_VALUE = 255,MIN_VALUE = 0;
private final double THIRTY_PERCENT = 0.3,FIFTY_NINE_PERCENT = 0.59,ELEVEN_PERCENT = 0.11;
/**
* Consctructor which gets 3 colors (RGB), we check here if their range is valid (0 - 255), if not we assign black to it.
*
* @param red - The red color component value.
* @param green - The green color component value.
* @param blue - The blue color component value
*/
public RGBColor(int red, int green, int blue)
{
if(isValid(red,green,blue))
{
_red = red;
_green = green;
_blue = blue;
}
else
doBlack();
}
/**
* Construct a black RGBColor. i.e. red = green = blue = 0
*/
public RGBColor()
{
doBlack();
}
/**
* Here we check if the color number was entered correctly.
* It has to be an integer (whole number) between 0-255.
*
* @param nums - a component value, should be the number between 1-4
* @param return - return true if the number is between 1-4, false otherwise.
*/
private boolean isValid(int nums)
{
return ((nums >= MIN_VALUE) && (nums <= MAX_VALUE));
}
/**
* Here we check if the color number was entered correctly.
* It has to be an integer (whole number) between 0-255.
*
* @param red - the red component
* @param green - the green component
* @param blue - the red component
* @param return true if values are correct, false otherwise.
*/
private boolean isValid(int red, int green, int blue)
{
return ((red <= MAX_VALUE && red >= MIN_VALUE &&
green <= MAX_VALUE && green >= MIN_VALUE &&
blue <= MAX_VALUE && blue >= MIN_VALUE));
}
/**
* Returns RGB color string triplet with numbers between 0-255, i.e. (0,127,127)
*/
public String toString()
{
return ("(" + _red + "," + _green + "," + _blue + ")");
}
/**
* RGBColor will become the color Black. (0,0,0)
*/
private void doBlack()
{
_red = _green = _blue = 0;
}
}
RGBImage類:
public class RGBImage
{
private int _rows, _cols;
private RGBColor[][] _pixels;
private int _offset = 0;
public RGBImage(int rows, int cols)
{
_rows = rows;
_cols = cols;
_pixels = new RGBColor[_rows][_cols];
for(int i = 0; i < _rows; i++)
for(int j = 0; j < _cols; j++)
_pixels[i][j] = new RGBColor();
}
public RGBImage(RGBColor[][] pixels)
{
_rows = pixels.length;
_cols = pixels[0].length;
_pixels = new RGBColor[_rows][_cols];
for(int i = 0; i < _rows; i++)
for(int j = 0; j < _cols; j++)
_pixels[i][j] = new RGBColor(pixels[i][j]);
}
public void shiftCol (int offset)
{
if(_offset == 0)
_offset = offset;
else
_offset += offset;
int currentShift = 1;
if( (_offset == _cols) || (-_offset == _cols) ){
makeBlack(_rows,_cols); //make black
}
else if( (_offset < _cols) || (-_offset < _cols) )
{
if(_offset > 0){
for(int j = currentShift; j < _cols && j <= _offset; j++){
for(int i = 0; i < _rows; i++){
setPixel(i,j + 1,this._pixels[i][j]);
setPixel(i,j,this._pixels[i][j] = new RGBColor());
}
}
_offset++;
currentShift++;
}
else if(offset < 0){
offset = -offset;
for(int j = currentShift; j < _cols && j <= offset; j++){
for(int i = 0; i < _rows; i++){
setPixel(i,_cols - 1 - j,this._pixels[i][_cols - j]);
setPixel(i,_cols,this._pixels[i][_cols - j] = new RGBColor());
}
currentShift++;
}
}
}
}
public void setPixel(int row, int col, RGBColor pixel)
{
if ((pixel != null) && (row < _pixels.length) && (col < _pixels[0].length))
_pixels[row][col] = new RGBColor(pixel);
}
public String toString()
{
String pixelSet ="";
for (int i = 0; i < _rows; i++){
for(int j = 0; j < _cols; j++){
pixelSet += this._pixels[i][j].toString();
}
pixelSet += "\n";
}
//pixelSet += tester;
return pixelSet;
}
}
和我的輸出測試器類:
StudentTester類:
公共課程StudentTester {
public static void main(String[] args) {
System.out.println("Black Image Constructor:");
RGBImage rgbImg0 = new RGBImage(3,4);
System.out.println(rgbImg0);
System.out.println("Constructor with RGBColor[][] Array Parameter:");
RGBColor[][] rgbArray1 = new RGBColor[5][4];
for (int i=0; i<rgbArray1.length;i++)
for (int j=0; j<rgbArray1[0].length;j++)
rgbArray1[i][j] = new RGBColor(i,i,i);
RGBImage rgbImg1 = new RGBImage(rgbArray1);
System.out.println(rgbImg1);
System.out.println("Copy Constructor:");
RGBImage rgbImg2 = new RGBImage(rgbImg1);
System.out.println(rgbImg2);
System.out.println("flipVertical:");
rgbImg1.flipVertical();
System.out.println(rgbImg1);
System.out.println("rotateClockwise:");
rgbImg1.rotateClockwise();
System.out.println(rgbImg1);
System.out.println("shiftCol 2:");
rgbImg1.shiftCol(3);
System.out.println(rgbImg1);
System.out.println("shiftCol 2:");
rgbImg1.shiftCol(-2);
System.out.println(rgbImg1);
System.out.println("shiftCol 2:");
rgbImg1.shiftCol(1);
System.out.println(rgbImg1);
}
}
首先,您實際上並不需要_offset
字段。 您唯一使用它的地方是shiftCol()
方法,它實際上並不是作為對象的圖像狀態的一部分。 因此,它應該是局部變量。 但是實際上,參數offset
可以很好地完成工作,您不需要額外的變量。 請記住,參數是按值傳遞的,即使您更改offset
的值,也不會更改調用代碼中的任何內容。
其次,您實際上也不需要變量currentShift
。 您要向其中添加一個,但是第一個currentShift++
不在循環中並且沒有進一步的使用,第二個currentShift++
在循環中,但是它不影響循環中的任何內容,並且在循環后不使用。 所以-擺脫它。
現在,您真正的問題了。 首先讓我們看一下正偏移。 您對每列執行的操作是:
_pixels[i][j]
,然后再次通過調用setPixel()
)。 這有幾個問題。 首先,由於使用j
從0
到offset
進行offset
,結果是:
為什么所有這些移動只有一個像素? 並每次創建一個新的像素對象。
您只移動了一個列,就破壞了所有列的值。 這樣做會使您丟失其中所有應該移走的信息!
然后,當然是對新對象的雙重分配,其中之一直接進入垃圾箱。
現在解開這個結。
通常,將數組的一部分復制到自身上時,以正確的順序進行復制總是很重要的。 讓我們看一個簡單的字符數組:
0 1 2 3 4 5 ┌─┬─┬─┬─┬─┬─┐ │A│B│C│D│E│F│ └─┴─┴─┴─┴─┴─┘
假設您想將“ BCD”部分向右移動兩個空格,因此結果將是“ ABCBCD”(目前不關心擦除已移動的部分)。 天真的,你認為移動:
arr[3] = arr[1];
arr[4] = arr[2];
arr[5] = arr[3];
將做正確的事。 但實際上,您得到的是:
0 1 2 3 4 5 ┌─┬─┬─┬─┬─┬─┐ │A│B│C│B│C│B│ └─┴─┴─┴─┴─┴─┘
為什么在位置5出現“ B”? 因為我們已經在第一次分配中更改了arr[3]
。 這樣做破壞了D
,因此當我們將arr[3]
分配給arr[5]
,它已經是“ B”。
因此,正確復制到右側的方法是從右側開始:
arr[5] = arr[3];
arr[4] = arr[2];
arr[3] = arr[1];
但是...如果我們想向左移動,按相反的順序進行操作將無法正常工作。 從我們原始的“ ABCDEF”重新開始。 假設我們想將“ CDE”向左移動2個位置,以獲得“ CDEDEF”。 如果我們相反地做:
arr[2] = arr[4];
arr[1] = arr[3];
arr[0] = arr[2];
再一次,我們得到:
0 1 2 3 4 5 ┌─┬─┬─┬─┬─┬─┐ │E│D│E│D│E│F│ └─┴─┴─┴─┴─┴─┘
因為arr[2]
已經更改。
結論:
還要注意,將塊移動一個位置然后再移動一個位置等等都是沒有意義的-這只會浪費時間(如果創建新對象,則會浪費內存)。 您應該將其直接移動到應有的位置。 如果應該將其移動2,則其新索引為j+2
。
現在,假設我們的數組就像您問題中的行。 我們想轉移所有內容,而不僅僅是部分內容,並用空白填充。
因此,如果我想將此數組向右移動2個位置:
0 1 2 3 4 5 ┌─┬─┬─┬─┬─┬─┐ │A│B│C│D│E│F│ └─┴─┴─┴─┴─┴─┘
我希望得到:
0 1 2 3 4 5 ┌─┬─┬─┬─┬─┬─┐ │ │ │A│B│C│D│ └─┴─┴─┴─┴─┴─┘
我現在知道我必須從正確的位置做起。 我要做的是查看從5到0的每個位置,然后思考:該位置的來源是什么? 應該是這樣的單元格,這樣我當前位於右邊的兩個位置。 也就是說,位於我左邊兩個位置的單元格。 有這樣的牢房嗎? 如果是這樣,請將其值放在當前索引中。 如果不是(因為源位置為負),那么我用空白填充:
for ( i = arr.length - 1; i >= 0; i-- ) {
if ( i - offset >= 0 ) {
arr[i] = arr[i-offset];
} else {
arr[i] = ' ';
}
}
如果您有主意,現在可以將我對字符數組所做的操作應用於像素行。
您的下一個任務應該是將反向邏輯應用於負偏移量(請記住,從左至右!)
最后一點:不要對復制操作使用setPixel()
。 它會創建新的像素對象,這實際上是不必要的(黑色部分除外)。 我想setPixel()
這樣做是因為它是一個公共方法,並提供了像素的保護副本,因此,如果更改其內容,則不會影響我們的圖像。 但是對於內部操作而言,則沒有必要。
試試這個方法:
public void shiftCol (int offset)
{
if(offset > 0){
for(int j = _cols - 1; j >= 0; j--){
for(int i = 0; i < _rows; i++){
if (j - offset >= 0)
_pixels[i][j] = _pixels[i][j-offset];
else
_pixels[i][j] = new RGBColor();
}
}
} else {
for(int j = 0; j <=_cols - 1; j++){
for(int i = 0; i < _rows; i++){
if (j - offset < _cols)
_pixels[i][j] = _pixels[i][j-offset];
else
_pixels[i][j] = new RGBColor();
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.