parent
ed2576f160
commit
b6ce99ca7b
|
@ -180,7 +180,7 @@ void MultiFrameCapture::open(HGScanConfig config, FPGAConfigParam_8478 fpgaparam
|
||||||
// fpgaComm->write(12,0x04e20400); //0x494e491 0x79de496 范围 0-12 16-28 (16-28 > 0-12)
|
// fpgaComm->write(12,0x04e20400); //0x494e491 0x79de496 范围 0-12 16-28 (16-28 > 0-12)
|
||||||
|
|
||||||
fpgaComm->read(10, reg10);
|
fpgaComm->read(10, reg10);
|
||||||
fpgaComm->write(12, 0x00200010); // 58us 300*600 多帧
|
fpgaComm->write(12, 0x00f000e0); // 58us 300*600 多帧
|
||||||
|
|
||||||
fpgaComm->write(10, 0x0150012a); // 58us 300*600 多帧
|
fpgaComm->write(10, 0x0150012a); // 58us 300*600 多帧
|
||||||
|
|
||||||
|
@ -672,7 +672,7 @@ void MultiFrameCapture::openDevice(int dpi, int mode)
|
||||||
// }
|
// }
|
||||||
// else
|
// else
|
||||||
{
|
{
|
||||||
fpgaComm->write(12, 0x00200010); // 58us 300*600 多帧
|
fpgaComm->write(12, 0x00f000e0); // 58us 300*600 多帧
|
||||||
fpgaComm->write(10, 0x0150012a); // 58us 300*600 多帧
|
fpgaComm->write(10, 0x0150012a); // 58us 300*600 多帧
|
||||||
}
|
}
|
||||||
configFPGAParam(mode, dpi);
|
configFPGAParam(mode, dpi);
|
||||||
|
@ -1436,7 +1436,7 @@ void MultiFrameCapture::set_pixel_count_8478(int val, bool is_gray)
|
||||||
{
|
{
|
||||||
|
|
||||||
val = val - 10;
|
val = val - 10;
|
||||||
//fpgaComm->write(20, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3);
|
fpgaComm->write(21, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3);
|
||||||
fpgaComm->write(19, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3);
|
fpgaComm->write(19, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3);
|
||||||
|
|
||||||
write_adc_8478(bank_change[1], 1, (val & 0x7f00) / 0x100, (val & 0x7f00) / 0x100); // count0 -A
|
write_adc_8478(bank_change[1], 1, (val & 0x7f00) / 0x100, (val & 0x7f00) / 0x100); // count0 -A
|
||||||
|
|
|
@ -1383,7 +1383,7 @@ void MultiFrameCapture_8478_HL::set_pixel_count_8478(int val, bool is_gray)
|
||||||
{
|
{
|
||||||
|
|
||||||
val = val - 10;
|
val = val - 10;
|
||||||
//fpgaComm->write(20, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3);
|
fpgaComm->write(21, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3);
|
||||||
fpgaComm->write(19, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3);
|
fpgaComm->write(19, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3);
|
||||||
|
|
||||||
write_adc_8478(bank_change[1], 1, (val & 0x7f00) / 0x100, true); // count0 -A
|
write_adc_8478(bank_change[1], 1, (val & 0x7f00) / 0x100, true); // count0 -A
|
||||||
|
|
|
@ -39,7 +39,7 @@ MemoryPtr JpegImageEncode::encode(cv::Mat &image)
|
||||||
VectorMemroyPtr mem = VectorMemroyPtr(new VectorMemroy());
|
VectorMemroyPtr mem = VectorMemroyPtr(new VectorMemroy());
|
||||||
// StopWatch sw;
|
// StopWatch sw;
|
||||||
cv::imencode(m_bwimg ? ".png" : ".jpg", image, mem->buf(), compression_params);
|
cv::imencode(m_bwimg ? ".png" : ".jpg", image, mem->buf(), compression_params);
|
||||||
// printf("encode time = %0.2f \n", sw.elapsed_ms());
|
// printf("!!!!!!!!!!encode time = %0.2f \n", sw.elapsed_ms());
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
#define G200
|
#define G200
|
||||||
|
|
||||||
#ifdef G200
|
#ifdef G200
|
||||||
#define FWVersion "G2393D0228"
|
#define FWVersion "G2393D0311"
|
||||||
#define SERIALNUM "G2396021071101"
|
#define SERIALNUM "G2396021071101"
|
||||||
#else
|
#else
|
||||||
#define FWVersion "G1393D0228"
|
#define FWVersion "G1393D0311"
|
||||||
#define SERIALNUM "G1396021071101"
|
#define SERIALNUM "G1396021071101"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ public:
|
||||||
cv::Mat HG_RGA_Resize(cv::Mat& srcMat, cv::Size dsize, double fx = 0, double fy = 0,
|
cv::Mat HG_RGA_Resize(cv::Mat& srcMat, cv::Size dsize, double fx = 0, double fy = 0,
|
||||||
int interpolation = cv::INTER_LINEAR)
|
int interpolation = cv::INTER_LINEAR)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(srcMat.channels() == 3)
|
if(srcMat.channels() == 3)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -87,6 +88,25 @@ public:
|
||||||
cv::resize(srcMat,srcMat,dsize,fx,fy,interpolation);
|
cv::resize(srcMat,srcMat,dsize,fx,fy,interpolation);
|
||||||
return srcMat;
|
return srcMat;
|
||||||
}
|
}
|
||||||
|
// int rows = srcMat.rows / 2;
|
||||||
|
// cv::Mat dst(rows, srcMat.cols, srcMat.type());
|
||||||
|
// int step = srcMat.step;
|
||||||
|
// uchar* ptr1 = srcMat.data;
|
||||||
|
// uchar* ptr2 = srcMat.data + step;
|
||||||
|
// uchar* ptr = dst.data;
|
||||||
|
// ushort pix;
|
||||||
|
// for (size_t i = 0; i < rows; i++)
|
||||||
|
// {
|
||||||
|
// for (size_t j = 0; j < step; j++)
|
||||||
|
// {
|
||||||
|
// pix = (ptr1[j] + ptr2[j]) >> 1;
|
||||||
|
// ptr[j] = pix;
|
||||||
|
// }
|
||||||
|
// ptr1 += step + step;
|
||||||
|
// ptr2 += step + step;
|
||||||
|
// ptr += step;
|
||||||
|
// }
|
||||||
|
// return dst;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
RockchipRga m_rkrga;
|
RockchipRga m_rkrga;
|
||||||
|
@ -108,6 +128,7 @@ ImageUsbHandler::ImageUsbHandler(std::shared_ptr<UsbImageProcQueue> images)
|
||||||
H_ratio =*((float*)(&info.H_ratio));
|
H_ratio =*((float*)(&info.H_ratio));
|
||||||
V_ratio =*((float*)(&info.V_ratio));
|
V_ratio =*((float*)(&info.V_ratio));
|
||||||
m_rga.reset(new HG_RGA_());
|
m_rga.reset(new HG_RGA_());
|
||||||
|
cv::setNumThreads(1);
|
||||||
}
|
}
|
||||||
ImageUsbHandler::~ImageUsbHandler()
|
ImageUsbHandler::~ImageUsbHandler()
|
||||||
{
|
{
|
||||||
|
@ -431,14 +452,36 @@ void ImageUsbHandler::add_image(void *data, int width, int height, int type, int
|
||||||
if(m_scanconfig.g200params.dpi == 3)
|
if(m_scanconfig.g200params.dpi == 3)
|
||||||
cv::resize(saveMat,saveMat,cv::Size(0,0),H_ratio,V_ratio); // 600 dpi <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ600<30>ɼ<EFBFBD>
|
cv::resize(saveMat,saveMat,cv::Size(0,0),H_ratio,V_ratio); // 600 dpi <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ600<30>ɼ<EFBFBD>
|
||||||
|
|
||||||
|
// if(m_scanconfig.g200params.dpi==1)
|
||||||
|
// {
|
||||||
|
// #ifdef G100
|
||||||
|
// if(slow_moire) saveMat = m_rga->HG_RGA_Resize(saveMat,cv::Size(0,0),H_ratio,V_ratio*0.482,cv::InterpolationFlags::INTER_AREA);
|
||||||
|
// #else
|
||||||
|
// if(slow_moire) saveMat = m_rga->HG_RGA_Resize(saveMat,cv::Size(0,0),H_ratio,V_ratio*0.517,cv::InterpolationFlags::INTER_AREA);
|
||||||
|
// #endif
|
||||||
|
// else saveMat = m_rga->HG_RGA_Resize(saveMat,cv::Size(0,0),H_ratio,V_ratio);
|
||||||
|
// }
|
||||||
|
// if(m_scanconfig.g200params.dpi == 2)
|
||||||
|
// {
|
||||||
|
// #ifdef G100
|
||||||
|
// if(slow_moire) saveMat = m_rga->HG_RGA_Resize(saveMat,cv::Size(0,0),H_ratio,V_ratio*0.7241);
|
||||||
|
// #else
|
||||||
|
// if(slow_moire) saveMat = m_rga->HG_RGA_Resize(saveMat,cv::Size(0,0),H_ratio,V_ratio*0.7699);
|
||||||
|
// #endif
|
||||||
|
// else if((H_ratio != 1.0f) || (V_ratio != 1.0f))
|
||||||
|
// saveMat = m_rga->HG_RGA_Resize(saveMat,cv::Size(0,0),H_ratio,V_ratio);
|
||||||
|
// }
|
||||||
|
// if(m_scanconfig.g200params.dpi == 3)
|
||||||
|
// saveMat = m_rga->HG_RGA_Resize(saveMat,cv::Size(0,0),H_ratio,V_ratio); // 600 dpi <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ600<30>ɼ<EFBFBD>
|
||||||
|
|
||||||
cv::Mat imageMat;
|
cv::Mat imageMat;
|
||||||
std::vector<cv::Mat> imgs;
|
std::vector<cv::Mat> imgs;
|
||||||
int actwidth = saveMat.cols / 2;
|
int actwidth = saveMat.cols / 2;
|
||||||
int actheight = saveMat.rows;
|
int actheight = saveMat.rows;
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
// imageMat = saveMat(cv::Rect(i * actwidth, 0, actwidth, actheight))
|
imageMat = saveMat(cv::Rect(i * actwidth, 0, actwidth, actheight));
|
||||||
imageMat = saveMat(cv::Rect(i * actwidth, 0, actwidth, actheight)).clone();
|
// imageMat = saveMat(cv::Rect(i * actwidth, 0, actwidth, actheight)).clone();
|
||||||
// cv::imwrite("/root/img/"+std::to_string(num++)+".jpg",imageMat);
|
// cv::imwrite("/root/img/"+std::to_string(num++)+".jpg",imageMat);
|
||||||
// if(m_scanconfig.g200params.dpi == 3) imageMat = interpolation_600dpi(imageMat,false);
|
// if(m_scanconfig.g200params.dpi == 3) imageMat = interpolation_600dpi(imageMat,false);
|
||||||
|
|
||||||
|
@ -560,12 +603,12 @@ bool ImageUsbHandler::is_limit(uint32_t type){
|
||||||
if (m_hgimgconfig.resolution_dst > 200.0 || m_hgimgconfig.papertype == 52 || m_hgimgconfig.papertype == 54 ||
|
if (m_hgimgconfig.resolution_dst > 200.0 || m_hgimgconfig.papertype == 52 || m_hgimgconfig.papertype == 54 ||
|
||||||
m_hgimgconfig.papertype == 131)
|
m_hgimgconfig.papertype == 131)
|
||||||
{
|
{
|
||||||
while (results.size() >= (m_scanconfig.g200params.dpi == 3 ? 1 : 2))
|
while (results.size() >= (m_scanconfig.g200params.dpi == 3 ? 1 : 3))
|
||||||
{
|
{
|
||||||
results.front().get();
|
results.front().get();
|
||||||
results.pop();
|
results.pop();
|
||||||
}
|
}
|
||||||
if (encodeimgs.size() >= (m_scanconfig.g200params.dpi == 3 ? 1 : 2))
|
if (encodeimgs.size() >= (m_scanconfig.g200params.dpi == 3 ? 1 : 3))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -807,6 +807,9 @@ bool Scanner::ExceptionCheck()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
uint reg5 =0;
|
||||||
|
mb->read(5,reg5);
|
||||||
|
printf("!!!!! motorboard regs 5 : 0x%x \n",reg5);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -538,8 +538,8 @@ int main(int argc,char *argv[])
|
||||||
//fpgaparam.Sp = 4680;
|
//fpgaparam.Sp = 4680;
|
||||||
printf(" ----- set SP = %d ----\n",fpgaparam.Sp);
|
printf(" ----- set SP = %d ----\n",fpgaparam.Sp);
|
||||||
cap->open(config,fpgaparam);
|
cap->open(config,fpgaparam);
|
||||||
// cap->write_adc_8478(bank_change[0],0x22,0x8A,true);
|
// cap->write_adc_8478(bank_change[0],0x22,0x84,true);
|
||||||
// cap->write_adc_8478(bank_change[0],0x22,0x8A,false);
|
// cap->write_adc_8478(bank_change[0],0x22,0x84,false);
|
||||||
cap->init_imagedatabuffer();
|
cap->init_imagedatabuffer();
|
||||||
uint32_t reg4 = 0;
|
uint32_t reg4 = 0;
|
||||||
regs->read(5,reg4);
|
regs->read(5,reg4);
|
||||||
|
@ -548,10 +548,18 @@ int main(int argc,char *argv[])
|
||||||
regs->read(15, fpgaversion);
|
regs->read(15, fpgaversion);
|
||||||
std::cout <<std::hex<<"fpgaversion:0x" << fpgaversion << std::endl;
|
std::cout <<std::hex<<"fpgaversion:0x" << fpgaversion << std::endl;
|
||||||
int ix = 0;
|
int ix = 0;
|
||||||
|
// for(int channel_ = 0;channel_<9;channel_++)
|
||||||
|
// {
|
||||||
|
// int i = 120*channel_;
|
||||||
|
// cap->write_adc_8478(bank_change[0],7+channel_*2,(i/0x100)&0x3,true);
|
||||||
|
// cap->write_adc_8478(bank_change[0],7+1+channel_*2,i&0xff,true);
|
||||||
|
// cap->write_adc_8478(bank_change[0],7+channel_*2,(i/0x100)&0x3,false);
|
||||||
|
// cap->write_adc_8478(bank_change[0],7+1+channel_*2,i&0xff,false);
|
||||||
|
// }
|
||||||
|
|
||||||
//bos cl1 cl0 en ch
|
//bos cl1 cl0 en ch
|
||||||
|
// for (size_t i = 0; true/*i < 6*/ ;i++)
|
||||||
for (size_t i = 0; i <6 ;i++)
|
for (size_t i = 0; i <6 ;i++)
|
||||||
//for (size_t i = 0; ;i++)
|
|
||||||
{
|
{
|
||||||
// config.g200params.dpi = i%3+1;
|
// config.g200params.dpi = i%3+1;
|
||||||
// config.g200params.color = i<3;
|
// config.g200params.color = i<3;
|
||||||
|
@ -571,6 +579,7 @@ int main(int argc,char *argv[])
|
||||||
size_t width_mat = cap->width()*(config.g200params.color == 1 ? 3:1)*2;
|
size_t width_mat = cap->width()*(config.g200params.color == 1 ? 3:1)*2;
|
||||||
std::cout << "get img width : " << width_mat << " \t img height : " << buf.img_h << "\n";
|
std::cout << "get img width : " << width_mat << " \t img height : " << buf.img_h << "\n";
|
||||||
cv::Mat mat(buf.img_h,width_mat,CV_8UC1,buf.pdata);
|
cv::Mat mat(buf.img_h,width_mat,CV_8UC1,buf.pdata);
|
||||||
|
|
||||||
// cv::imwrite("/root/img/"+std::to_string(i)+"BRG.bmp",mat);
|
// cv::imwrite("/root/img/"+std::to_string(i)+"BRG.bmp",mat);
|
||||||
|
|
||||||
auto merge = cap->merge_8478(mat,config.g200params.color,0);
|
auto merge = cap->merge_8478(mat,config.g200params.color,0);
|
||||||
|
@ -580,6 +589,22 @@ int main(int argc,char *argv[])
|
||||||
// cv::imwrite("/root/img/"+std::to_string(i)+"src.bmp",mat_rgb);
|
// cv::imwrite("/root/img/"+std::to_string(i)+"src.bmp",mat_rgb);
|
||||||
//std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
//std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||||
|
|
||||||
|
// double max,min;
|
||||||
|
// cv::Point maxidx,minidx;
|
||||||
|
// bool need_save = false;
|
||||||
|
// int col = mat.cols /102;
|
||||||
|
// for(int j=0;j<102;j++)
|
||||||
|
// {
|
||||||
|
// cv::minMaxLoc(mat(cv::Rect(col*j,0,col,mat.rows)),&min,&max,&minidx,&maxidx);
|
||||||
|
// std::cout<< std::dec << "["<<col*j<<","<<col*(j+1)<<"] min:"<< min << " max:" << max <<std::endl;
|
||||||
|
// if(max != min){
|
||||||
|
// need_save = true;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if(need_save)
|
||||||
|
// cv::imwrite("/root/"+std::to_string(i) +"_.bmp",mat);
|
||||||
|
|
||||||
// double max,min;
|
// double max,min;
|
||||||
// cv::Point maxidx,minidx;
|
// cv::Point maxidx,minidx;
|
||||||
// cv::minMaxLoc(mat(cv::Rect(mat.cols /2 + 10,0,mat.cols /2 - 10 ,mat.rows)),&min,&max,&minidx,&maxidx);
|
// cv::minMaxLoc(mat(cv::Rect(mat.cols /2 + 10,0,mat.cols /2 - 10 ,mat.rows)),&min,&max,&minidx,&maxidx);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "imageencode.h"
|
#include "imageencode.h"
|
||||||
#include "ImageApply.h"
|
#include "ImageApply.h"
|
||||||
#include "ImageApplyHeaders.h"
|
#include "ImageApplyHeaders.h"
|
||||||
|
#include "ThreadPool.h"
|
||||||
|
|
||||||
|
|
||||||
std::vector<double> caculate(const std::vector<double>& points_x, const std::vector<double>& points_y)
|
std::vector<double> caculate(const std::vector<double>& points_x, const std::vector<double>& points_y)
|
||||||
|
@ -292,9 +293,28 @@ int main()
|
||||||
// }
|
// }
|
||||||
// mean = std::accumulate(v.begin(),v.end(),0.0) / v.size() /1000.0;
|
// mean = std::accumulate(v.begin(),v.end(),0.0) / v.size() /1000.0;
|
||||||
// printf("interpolation_600dpi mean time = %f \n",mean*2);
|
// printf("interpolation_600dpi mean time = %f \n",mean*2);
|
||||||
for(int i =0;i<52;i++)
|
|
||||||
|
ThreadPool pool(5);
|
||||||
|
cv::Mat mat = cv::imread("/root/img/rga.png",cv::IMREAD_ANYCOLOR);
|
||||||
|
std::queue<std::future<void>> fus;
|
||||||
|
for(int i=0;i<5000;i++)
|
||||||
{
|
{
|
||||||
cv::imwrite("/root/img/rga_"+std::to_string(i)+".jpg",HG_RGA_Resize(cv::imread("/root/img/"+std::to_string(i)+".jpg",cv::IMREAD_COLOR),cv::Size(0,0),1.0,0.517));
|
while(fus.size()>30)
|
||||||
|
{
|
||||||
|
fus.front().get();
|
||||||
|
fus.pop();
|
||||||
|
}
|
||||||
|
fus.push(pool.enqueue([i](cv::Mat mat){
|
||||||
|
StopWatch sw;
|
||||||
|
HG_RGA_Resize(mat,cv::Size(0,0),1.0,0.517);
|
||||||
|
std::cout<< "rga "<<i<< "times : "<< sw.elapsed_ms() <<std::endl;
|
||||||
|
},
|
||||||
|
mat.clone()));
|
||||||
|
}
|
||||||
|
while (fus.size())
|
||||||
|
{
|
||||||
|
fus.front().get();
|
||||||
|
fus.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "imageusbtesthandler.h"
|
#include "imageusbtesthandler.h"
|
||||||
#include "applog.h"
|
#include "applog.h"
|
||||||
#include "jsonconfig.h"
|
#include "jsonconfig.h"
|
||||||
|
#include "imageencode.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ int menu()
|
||||||
cout << "(2) clear notify. " << endl;
|
cout << "(2) clear notify. " << endl;
|
||||||
cout << "(3/4) autocorrect " << endl;
|
cout << "(3/4) autocorrect " << endl;
|
||||||
cout << "(5) color mode change test " << endl;
|
cout << "(5) color mode change test " << endl;
|
||||||
|
cout << "(6) test usb transmit "<< endl;
|
||||||
cout << "(0) Quit. " << endl
|
cout << "(0) Quit. " << endl
|
||||||
<< endl;
|
<< endl;
|
||||||
cout << ": ";
|
cout << ": ";
|
||||||
|
@ -102,6 +104,22 @@ int main()
|
||||||
std::cout << "Please select again! " << std::endl;
|
std::cout << "Please select again! " << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 6:
|
||||||
|
{
|
||||||
|
std::vector<std::uint8_t> buf;
|
||||||
|
buf.resize(3762*3200*3);
|
||||||
|
for(int i =0;i<(3762*3200*3);i++)
|
||||||
|
buf.push_back(i%256);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
cv::Mat mat(3672,rand()%1000+500,CV_8UC3,buf.data());
|
||||||
|
usbImage->push(BmpImageEncode().encode(mat),true);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
while(usbImage->size() > 30)
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
std::cout << "Please select again! " << std::endl;
|
std::cout << "Please select again! " << std::endl;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue