簡體   English   中英

從char *轉換為stringstream然后返回char *時數據損壞

[英]data corruption while converting from char * to stringstream and then back to char*

因此,我嘗試使用XImage,創建了我的第一個屏幕捕獲程序,並且運行良好。 現在,我想通過節儉將該XImage發送到另一台計算機並保存到那里,但是由於客戶端存在一些數據讀取問題,因此我將整個服務器端代碼移到了客戶端(出於測試目的。最終,我會移動它返回到服務器端)

代碼:

transport->open();
Display *display = XOpenDisplay(NULL);
  Window root = DefaultRootWindow(display);
  XWindowAttributes gwa;
  XGetWindowAttributes(display, root, &gwa);

  int width = gwa.width;
  int height = gwa.height;
  XImage *image = XGetImage(display,root, 0,0 , width,height,AllPlanes, ZPixmap);

  char *data    = image->data;
  int imgwidth  = image->width;
  int imgheight = image->height;
  int depth     = image->depth;
  int offset    = 0;
  int xpad = 32; //may be 8 or 16 or 32
  int format = ZPixmap;
  int bytes_per_line = image->bytes_per_line;


  sendImage image_send;

  ostringstream s;
  //s<<image->data;
  s.write(image->data,(width)*(height));
  image_send.width  = imgwidth;
  image_send.height = imgheight;
  image_send.depth  = depth;
  image_send.offset = 2000;
  image_send.data   = s.str();
  image_send.xpad   = xpad;
  image_send.format = format;
  image_send.bytes_per_line = bytes_per_line;

 //server side code 
     int width1  = image_send.width;
     int height1 = image_send.height;
     int depth1  = image_send.depth;
     int offset1 = image_send.offset;
     char* tmp = new char[image_send.data.length() + 1];
     strcpy(tmp,image_send.data.c_str());
     char *data1 = tmp;
     int xpad1  = image_send.xpad;
     int format1 = image_send.format;
     int bytes_per_line1 = image_send.bytes_per_line;

     //Initialising X Operations
     //Display *display = XOpenDisplay(NULL);
     //Window root = DefaultRootWindow(display);
     //XWindowAttributes gwa;
    //XGetWindowAttributes(display, root, &gwa);

   int serverwidth = gwa.width;
   int serverheight = gwa.height;
   XImage *image1 = XCreateImage(display,DefaultVisual(display,DefaultScreen(display)),depth1, format1,offset1,data1,width1,height1,xpad1, bytes_per_line1);



   unsigned char *array = new unsigned char[width * height * 3];

   unsigned long red_mask = image1->red_mask;
   unsigned long green_mask = image1->green_mask;
   unsigned long blue_mask = image1->blue_mask;

   CImg<unsigned char> pic(array,width,height,1,3);

   for (int x = 0; x < width1; x++)
      for (int y = 0; y < height1 ; y++)
      {
         unsigned long pixel = XGetPixel(image1,x,y);

     unsigned char blue = pixel & blue_mask;
     unsigned char green = (pixel & green_mask) >> 8;
     unsigned char red = (pixel & red_mask) >> 16;



     array[(x + width1 * y) * 3] = red;
     array[(x + width1* y) * 3+1] = green;
     array[(x + width1 * y) * 3+2] = blue;

     pic(x,y,0,0) = red;
     pic(x,y,0,1) = green;
     pic(x,y,0,2) = blue;
  }



   pic.save_png("blah1.png");

如您所見,我從圖像指針中獲取了數據部分,將其寫入流中,然后將該值分配給節儉對象(image_send)

對於服務器端。 我使用c_str()將其存儲到data1中,然后使用data1使用XCreateImage

這是我將data1作為XCreateImage中的源傳遞時得到的輸出

在此處輸入圖片說明

這是我使用data(原始XImage的客戶端變量)時得到的輸出

在此處輸入圖片說明

如我們所見,第一張圖片中有很多空白。 在進一步檢查中,我發現data1在開始時包含很多null,而數據沒有

因此,我認為從char *轉換為字符串流然后返回char *時,數據會損壞。

您會提出什么建議來糾正此問題? 更新:

因此,我嘗試了各種嘗試,終於奏效了。 問題原來是緩沖區分配和使用strcpy(我猜),我更改為memcpy

int main() {

Display *display = XOpenDisplay(NULL);
Window root = DefaultRootWindow(display);
XWindowAttributes gwa;
XGetWindowAttributes(display, root, &gwa);

int width = gwa.width;
int height = gwa.height;
XImage *image = XGetImage(display,root, 0,0 , width,height,AllPlanes, ZPixmap);

char *data    = image->data;
int imgwidth  = image->width;
int imgheight = image->height;
int depth     = image->depth;
int offset    = 0;
int xpad = 32; //may be 8 or 16 or 32
int format = ZPixmap;
int bytes_per_line = image->bytes_per_line;


//sendImage image_send;

ostringstream s;
//s<<image->data;
s.write(data,(width)*(height) * 4);

string stemp = s.str(); 
//server side code 
int width1  = width;
int height1 = height;
int depth1  = depth;
int offset1 = offset;
char* tmp = new char[stemp.length()];
//strcpy(tmp,stemp.c_str());
memcpy(tmp,stemp.data(),stemp.length());
char *data1 = tmp;
int xpad1  = 32;
int format1 = ZPixmap;
int bytes_per_line1 = bytes_per_line;

int serverwidth = gwa.width;
int serverheight = gwa.height;
XImage *image1 = XCreateImage(display,DefaultVisual(display,DefaultScreen(display)),depth1, format1,offset1,data1,serverwidth,serverheight,xpad1, bytes_per_line1);

unsigned char *array = new unsigned char[width * height];

unsigned long red_mask = image1->red_mask;
unsigned long green_mask = image1->green_mask;
unsigned long blue_mask = image1->blue_mask;

CImg<unsigned char> pic(array,width,height,1,3);

for (int x = 0; x < width1; x++) {
    for (int y = 0; y < height1 ; y++)
    {
        unsigned long pixel = XGetPixel(image1,x,y);
        unsigned char blue = pixel & blue_mask;
        unsigned char green = (pixel & green_mask) >> 8;
        unsigned char red = (pixel & red_mask) >> 16;

        pic(x,y,0,0) = red;
        pic(x,y,0,1) = green;
        pic(x,y,0,2) = blue;
    }
}

pic.save_png("blah.png");

return 0;
}

但是有些事情我不明白

1)當我將數據寫入流時,為什么必須將緩沖區的大小設置為(width * height * 4)。 少的將按比例裁剪圖像。 如果我理解正確,緩沖區大小不應該等於屏幕的寬度*高度嗎?還是結構更像是紅色,綠色,藍色和深度的數組?

2)我的緩沖區大小約為4MB,但是圖像大小約為150K,這是由於編碼所致

3)是否會連續分配和釋放這么多的緩沖區大小,從而影響性能?

編輯:為了將來的目的

第一個問題的答案是:我們可以使用(bytes_per_line height)得到相同的結果,該結果恰好給出了與width height * 4 相同的結果。

圖像數據是二進制的,您無法像對待C字符串一樣對其進行操作。 第一個零字節將破壞聚會。

使用std::string::data()和/或memcpy ,而不是std::string::str()strcpy

我不知道這是否是唯一的問題。 (width)*(height)對我來說可疑。 您有一個字節的像素嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM