// ****************************************************************************
//  Method: avtImgCommunicator::rleEncodeAll
//
//  Purpose:
//    Encodes an image using RLE: Runlength, R, G, B, A
//
//  Arguments:
//    dimsX & dimsY : width & height of the image
//    imgArray    : array containing all the division composited by this processor
//    numDivs     : number of Z divisions
//
//    encoding      : the image compressed using RLE; it's a float so that it can be sent directly using MPI
//    sizeOfEncoding  : the compressed size of each image
//
//
//  Programmer: Pascal Grosset
//  Creation: August 23, 2013
//
//  Modifications:
//
// ****************************************************************************
int avtImgCommunicator::rleEncodeAll(int dimsX, int dimsY, int numDivs, float *imgArray,  float *& encoding, int *& sizeOfEncoding){
  std::vector<code> encodingVec;
  encodingVec.clear();
  code tempCode;
  sizeOfEncoding = new int[numDivs];
  int prev = 0;

  // Compress the data
  for (int j=0; j<numDivs; j++){
    int offset = dimsX*dimsY*4  *  j; // to get the next image in the array of images

    int i=0;
    tempCode = initCode(1, imgArray[offset + (i*4+0)],imgArray[offset + (i*4+1)],imgArray[offset + (i*4+2)],  imgArray[offset + (i*4+3)]);
    for (i=1; i<dimsX*dimsY; i++){
      if ( compareColor(tempCode, imgArray[offset + (i*4+0)],imgArray[offset + (i*4+1)],imgArray[offset + (i*4+2)],imgArray[offset + (i*4+3)]) )
        tempCode = incrCode(tempCode);
      else{
        encodingVec.push_back(tempCode);
        tempCode = initCode(1, imgArray[offset + (i*4+0)],imgArray[offset + (i*4+1)],imgArray[offset + (i*4+2)],imgArray[offset + (i*4+3)]);
      }
    }
    encodingVec.push_back(tempCode);

    if (j == 0)
      prev = sizeOfEncoding[j] = encodingVec.size();
    else{
      sizeOfEncoding[j] = encodingVec.size() - prev;
      prev = encodingVec.size();
    }

    debug5 <<  my_id << "  ~  encoding.size(): " << sizeOfEncoding[j] << "   offset: " << offset << "    original size: " << (dimsX * dimsY * 4) << "   size: " << encodingVec.size() << std::endl;
  }


  // Transfer the data to the encoding array
  int encSize = encodingVec.size();
  encoding = new float[encSize*5];
  
  int index = 0;
  for (int j=0; j<encSize; j++){
    encoding[index] = encodingVec[j].count; index++;
    encoding[index] = encodingVec[j].color[0];  index++;
    encoding[index] = encodingVec[j].color[1];  index++;
    encoding[index] = encodingVec[j].color[2];  index++;
    encoding[index] = encodingVec[j].color[3];  index++;  
  }
  encodingVec.clear();

  return encSize;   // size of the array
}
Example #2
0
// Flood fill
// ----- http://lodev.org/cgtutor/floodfill.html
void BitmapImage::floodFill(BitmapImage* targetImage,
                            QRect cameraRect,
                            QPoint point,
                            QRgb newColor,
                            int tolerance)
{
    // If the point we are supposed to fill is outside the image and camera bounds, do nothing
    if(!cameraRect.united(targetImage->bounds()).contains(point))
    {
        return;
    }

    // Square tolerance for use with compareColor
    tolerance = static_cast<int>(qPow(tolerance, 2));

    QRgb oldColor = targetImage->pixel(point);
    oldColor = qRgba(qRed(oldColor), qGreen(oldColor), qBlue(oldColor), qAlpha(oldColor));

    // Preparations
    QList<QPoint> queue; // queue all the pixels of the filled area (as they are found)

    BitmapImage* replaceImage = nullptr;
    QPoint tempPoint;
    QRgb newPlacedColor = 0;
    QScopedPointer< QHash<QRgb, bool> > cache(new QHash<QRgb, bool>());

    int xTemp = 0;
    bool spanLeft = false;
    bool spanRight = false;

    // Extend to size of Camera
    targetImage->extend(cameraRect);
    replaceImage = new BitmapImage(cameraRect, Qt::transparent);

    queue.append(point);
    // Preparations END

    while (!queue.empty())
    {
        tempPoint = queue.takeFirst();

        point.setX(tempPoint.x());
        point.setY(tempPoint.y());

        xTemp = point.x();

        newPlacedColor = replaceImage->constScanLine(xTemp, point.y());
        while (xTemp >= targetImage->mBounds.left() &&
               compareColor(targetImage->constScanLine(xTemp, point.y()), oldColor, tolerance, cache.data())) xTemp--;
        xTemp++;

        spanLeft = spanRight = false;
        while (xTemp <= targetImage->mBounds.right() &&
               compareColor(targetImage->constScanLine(xTemp, point.y()), oldColor, tolerance, cache.data()) &&
               newPlacedColor != newColor)
        {

            // Set pixel color
            replaceImage->scanLine(xTemp, point.y(), newColor);

            if (!spanLeft && (point.y() > targetImage->mBounds.top()) &&
                compareColor(targetImage->constScanLine(xTemp, point.y() - 1), oldColor, tolerance, cache.data())) {
                queue.append(QPoint(xTemp, point.y() - 1));
                spanLeft = true;
            }
            else if (spanLeft && (point.y() > targetImage->mBounds.top()) &&
                     !compareColor(targetImage->constScanLine(xTemp, point.y() - 1), oldColor, tolerance, cache.data())) {
                spanLeft = false;
            }

            if (!spanRight && point.y() < targetImage->mBounds.bottom() &&
                compareColor(targetImage->constScanLine(xTemp, point.y() + 1), oldColor, tolerance, cache.data())) {
                queue.append(QPoint(xTemp, point.y() + 1));
                spanRight = true;

            }
            else if (spanRight && point.y() < targetImage->mBounds.bottom() &&
                     !compareColor(targetImage->constScanLine(xTemp, point.y() + 1), oldColor, tolerance, cache.data())) {
                spanRight = false;
            }

            Q_ASSERT(queue.count() < (targetImage->mBounds.width() * targetImage->mBounds.height()));
            xTemp++;
        }
    }

    targetImage->paste(replaceImage);
    targetImage->modification();
    delete replaceImage;
}