Пример #1
0
QPair<int, int> IndexColorPalette::getNeighbours(int mainClr) const
{
    QVector<float> diffs;
    diffs.resize(numColors());
    for(int i = 0; i < numColors(); ++i)
        diffs[i] = similarity(colors[i], colors[mainClr]);

    int darkerColor = 0;
    int brighterColor = 0;
    for(int i = 0; i < numColors(); ++i)
    {
        if(i != mainClr)
        {
            if(colors[i].L < colors[mainClr].L)
            {
                if(diffs[i] > diffs[darkerColor])
                    darkerColor = i;
            }
            else
            {
                if(diffs[i] > diffs[brighterColor])
                    brighterColor = i;
            }
        }
    }

    return qMakePair(darkerColor, brighterColor);
}
    QwtColorTable colorTable() const
    {
        QwtColorTable table(numColors());
        for ( int i = 0; i < numColors(); i++ )
            table[i] = color(i);

        return table;
    }
Пример #3
0
LabColor IndexColorPalette::getNearestIndex(LabColor clr) const
{
    QVector<float> diffs;
    diffs.resize(numColors());
    for(int i = 0; i < numColors(); ++i)
        diffs[i] = similarity(colors[i], clr);

    int primaryColor = 0;
    for(int i = 0; i < numColors(); ++i)
        if(diffs[i] > diffs[primaryColor])
            primaryColor = i;

    return colors[primaryColor];
}
Пример #4
0
void KIconEditGrid::editPasteAsNew()
{
  bool ok = false;
  const QImage *tmp = clipboardImage(ok);

  if(ok)
  {
    *img = *tmp;
    load(img);
    modified = true;
    //repaint(viewRect(), false);

    p = *img;
    emit changed(QPixmap(p));
    emit sizechanged(numCols(), numRows());
    emit colorschanged(numColors(), data());
    emit newmessage(i18n("Done pasting"));
  }
  else
  {
    QString msg = i18n("Invalid pixmap data in clipboard!\n");
    KMsgBox::message(this, i18n("Warning"), msg.data());
  }
  delete tmp;
}
Пример #5
0
void KIconEditGrid::loadBlank( int w, int h )
{
  img->create(w, h, 32);
  img->fill(TRANSPARENT);
  setNumRows(h);
  setNumCols(w);
  fill(TRANSPARENT);
  emit sizechanged(numCols(), numRows());
  emit colorschanged(numColors(), data());
}
Пример #6
0
void KIconEditGrid::load( QImage *image)
{
  debug("KIconEditGrid::load");

  setUpdatesEnabled(false);

  if(image != 0L)
  {
    *img = *fixTransparence(image);
    //*img = image->convertDepth(32);
    //img->setAlphaBuffer(true);
  }
  else
  {
    QString msg = i18n("There was an error loading a blank image.\n");
    KMsgBox::message (this, i18n("Error"), msg.data());
    return;
  }

  setNumRows(img->height());
  setNumCols(img->width());

  for(int y = 0; y < numRows(); y++)
  {
    uint *l = (uint*)img->scanLine(y);
    for(int x = 0; x < numCols(); x++, l++)
    {
/*
      //uint gray = (qRgb(200, 200, 200) | OPAQUE_MASK);
      //uint bc = (TRANSPARENT | OPAQUE_MASK);
      //if(*l == gray || *l == bc || *l < 0xff000000)  // this is a hack but I couldn't save it as transparent otherwise
      if(*l < 0xff000000 || *l == (TRANSPARENT|OPAQUE_MASK))  // this is a hack but I couldn't save it as transparent otherwise
      {
        *l = TRANSPARENT;
      }
      //debug("KIcnGrid::load: %d %%", (((y*ncols)+x)/imgsize) * 100);
      //debug("KIconEditGrid::load: RGB: %d %d %d", qRed(*l), qGreen(*l), qBlue(*l));
*/
      setColor((y*numCols())+x, *l, false);
    }
    //debug("Row: %d", y);
    kapp->processEvents(200);
  }
  updateColors();
  emit sizechanged(numCols(), numRows());
  emit colorschanged(numColors(), data());
  emit changed(pixmap());
  setUpdatesEnabled(true);
  emit needPainting();
  //repaint(viewRect(), false);
}
Пример #7
0
void IndexColorPalette::mergeMostReduantColors()
{
    QVector<ColorString> colorHood;
    colorHood.resize(numColors());
    for(int i = 0; i < numColors(); ++i)
    {
        colorHood[i].color = i;
        colorHood[i].neighbours = getNeighbours(i);
        float lSimilarity = 0.05f, rSimilarity = 0.05f;
        // There will be exactly 2 colors that have only 1 neighbour, the darkest and the brightest, we don't want to remove those
        if(colorHood[i].neighbours.first  != -1)
            lSimilarity = similarity(colors[colorHood[i].neighbours.first], colors[i]);
        if(colorHood[i].neighbours.second != -1)
            rSimilarity = similarity(colors[colorHood[i].neighbours.second], colors[i]);
        colorHood[i].similarity = (lSimilarity + rSimilarity) / 2;
    }
    int mostSimilarColor = 0;
    for(int i = 0; i < numColors(); ++i)
        if(colorHood[i].similarity > colorHood[mostSimilarColor].similarity)
            mostSimilarColor = i;

    int darkerIndex = colorHood[mostSimilarColor].neighbours.first;
    int brighterIndex = colorHood[mostSimilarColor].neighbours.second;
    if(darkerIndex   != -1 &&
            brighterIndex != -1)
    {
        LabColor clrA = colors[darkerIndex];
        LabColor clrB = colors[mostSimilarColor];
        LabColor clrC = colors[brighterIndex];
        // Remove two, add one = 1 color less
        colors.remove(darkerIndex);
        colors.remove(mostSimilarColor);
        //colors.remove(brighterIndex);
        insertShades(clrA, clrB, 1);
        //insertShades(clrB, clrC, 1);
    }
}
Пример #8
0
QImage *KIconEditGrid::getSelection(bool cut)
{
  const QRect rect = pntarray.boundingRect();
  int nx = 0, ny = 0, nw = 0, nh = 0;
  rect.rect(&nx, &ny, &nw, &nh);

  QImage *tmp = new QImage(nw, nh, 32);
  tmp->fill(TRANSPARENT);

  int s = pntarray.size(); //((rect.size().width()) * (rect.size().height()));
  for(int i = 0; i < s; i++)
  {
    int x = pntarray[i].x();
    int y = pntarray[i].y();
    if(img->valid(x, y) && rect.contains(QPoint(x, y)))
    {
      *((uint*)tmp->scanLine(y-ny) + (x-nx)) = *((uint*)img->scanLine(y) + x);
      if(cut)
      {
        *((uint*)img->scanLine(y) + x) = TRANSPARENT;
        setColor( (y*numCols()) + x, TRANSPARENT, false );
      }
    }
  }

  QPointArray a(pntarray.copy());
  pntarray.resize(0);
  drawPointArray(a, Mark);
  emit selecteddata(false);
  if(cut)
  {
    updateColors();
    repaint(rect.x()*cellSize(), rect.y()*cellSize(),
            rect.width()*cellSize(), rect.height()*cellSize(), false);
    p = *img;
    emit changed(p);
    emit colorschanged(numColors(), data());
    emit newmessage(i18n("Selected area cutted"));
  }
  else
    emit newmessage(i18n("Selected area copied"));

  return tmp;
}
Пример #9
0
void PadConfiguration::drawPicture()
{
  if(_picture == nullptr)
  {
    drawMapping();
    return;
  }

          uint8_t* pointer = _picture;
        uint16_t current(0);
#define READ_8 current = *pointer; ++pointer;
#define READ_16 current = *((uint16_t*)pointer); ++pointer; ++pointer;

        READ_16;
        TFTscreen.fillScreen(current);

        READ_8;
        uint16_t numColors(current);
        for(uint16_t currentColor = 0; currentColor < numColors; ++currentColor)
        {
            READ_16;
            uint16_t color = current;

            READ_16;
            uint32_t numRects(current);
            for(uint16_t currentRect = 0; currentRect < numRects; ++currentRect)
            {
                READ_8;
                int16_t x(current);
                READ_8;
                int16_t y(current);
                READ_8;
                int16_t w(current);
                READ_8;
                int16_t h(current);
                TFTscreen.fillRect(x, y, w, h, color);
            }

            READ_16;
            uint16_t numVLines(current);
            for(uint16_t currentVLine = 0; currentVLine < numVLines; ++currentVLine)
            {
                READ_8;
                int16_t x(current);
                READ_8;
                int16_t y(current);
                READ_8;
                int16_t l(current);

                TFTscreen.drawFastVLine(x, y, l, color);
            }

            READ_16;
            uint16_t numHLines(current);
            for(uint16_t currentHLine = 0; currentHLine < numHLines; ++currentHLine)
            {
                READ_8;
                int16_t x(current);
                READ_8;
                int16_t y(current);
                READ_8;
                int16_t l(current);

                TFTscreen.drawFastHLine(x, y, l, color);
            }

            READ_16;
            uint16_t numPix(current);
            for(uint16_t currentPix = 0; currentPix < numPix; ++currentPix)
            {
                READ_8;
                int16_t x(current);
                READ_8;
                int16_t y(current);

                TFTscreen.drawPixel(x, y, color);
            }
        }

#undef READ_8
#undef READ_16
}
Пример #10
0
void KIconEditGrid::editPaste(bool paste)
{
  bool ok = false;
  const QImage *tmp = clipboardImage(ok);
  fixTransparence((QImage*)tmp);

  Properties *pprops = props(this);

  if(ok)
  {
    if( (tmp->size().width() > img->size().width()) || (tmp->size().height() > img->size().height()) )
    {
      if(KMsgBox::yesNo(this, i18n("Warning"),
          i18n("The clipboard image is larger than the current image!\nPaste as new image?")) == 1)
      {
        editPasteAsNew();
      }
      delete tmp;
      return;
    }
    else if(!paste)
    {
      ispasting = true;
      cbsize = tmp->size();
      //debug("insrect size: %d x %d", insrect.width(), insrect.height());
      return;
      emit newmessage(i18n("Pasting"));
    }
    else
    {
      //debug("KIconEditGrid: Pasting at: %d x %d", insrect.x(), insrect.y());

      QApplication::setOverrideCursor(waitCursor);

      for(int y = insrect.y(), ny = 0; y < numRows(), ny < insrect.height(); y++, ny++)
      {
        uint *l = ((uint*)img->scanLine(y)+insrect.x());
        uint *cl = (uint*)tmp->scanLine(ny);
        for(int x = insrect.x(), nx = 0; x < numCols(), nx < insrect.width(); x++, nx++, l++, cl++)
        {
          if(*cl != TRANSPARENT || pprops->pastetransparent)
          {
            *l = *cl;
            setColor((y*numCols())+x, (uint)*cl, false);
          }
        }
      }
      updateColors();
      repaint(insrect.x()*cellSize(), insrect.y()*cellSize(),
              insrect.width()*cellSize(), insrect.height()*cellSize(), false);

      QApplication::restoreOverrideCursor();

      modified = true;
      p = *img;
      emit changed(QPixmap(p));
      emit sizechanged(numCols(), numRows());
      emit colorschanged(numColors(), data());
      emit newmessage(i18n("Done pasting"));
    }
  }
  else
  {
    QString msg = i18n("Invalid pixmap data in clipboard!\n");
    KMsgBox::message(this, i18n("Warning"), msg.data());
  }
  delete tmp;
}
Пример #11
0
void ColorReducer::reduce(Logger *log, unsigned minColors)
{
    /*
     * This is a median-cut style color reducer. We start with a
     * single box that encloses all pixels in the image, and we
     * iteratively subdivide boxes until we reach the targetted MSE
     * metric.
     */

    if (log)
        log->taskBegin("Optimizing palette");

    if (colors.size() >= 1) {

        // Base case: One single color.
        box root = { 0, (unsigned)colors.size() };
        boxes.clear();
        boxes.push_back(root);
        boxQueue.clear();
        boxQueue.push_back(0);

        /*
         * Keep splitting until all colors are within the acceptable
         * tolerance, or we run out of boxes.
         *
         * It's actually much more expensive to calculate the MSE and the
         * color LUT than it is to perform palette splits. So, we're extra
         * careful here to minimize the overhead of error measurement. The
         * LUT is calculated lazily, and we always avoid error
         * calculations for colors that couldn't possibly contribute to
         * the success or failure of the current iteration: We always stop
         * after finding one color that's out of the acceptable tolerance,
         * and we avoid re-checking colors that have already been solved.
         *
         * The lazy LUT calculations are handled automatically by
         * nearest(), but we use a stack of not-yet-solved colors here in
         * order to reduce the number of LUT entries we ever have to
         * touch.
         */

        std::vector<uint16_t> errorStack;

        for (unsigned i = 0; i < LUT_SIZE; i++)
            errorStack.push_back(i);

        while (!boxQueue.empty()) {
            /*
             * Try to reduce the size of the error stack. Any colors that
             * are now within range can be popped off of it permanently.
             */

            while (errorStack.size()) {
                unsigned v = errorStack.back();
                RGB565 color((uint16_t)v);
                double maxMSE = colorMSE[v];
                double mse = CIELab(nearest(color)).meanSquaredError(CIELab(color));

                if (mse <= maxMSE)
                    errorStack.pop_back();
                else
                    break;
            }

            if (log && (boxes.size() % 64 == 0 || !errorStack.size()))
                log->taskProgress("%d colors in palette", (int)boxes.size());

            if (!errorStack.size() && numColors() >= minColors)
                break;

            /*
             * Perform the next split
             */
        
            unsigned boxIndex = *boxQueue.begin();
            struct box& b = boxes[boxIndex];
            boxQueue.pop_front();

            int major = CIELab::findMajorAxis(&colors[b.begin], b.end - b.begin);

            std::sort(colors.begin() + b.begin,
                      colors.begin() + b.end,
                      CIELab::sortAxis(major));
        
            splitBox(b);

            // Invalidate all inverseLUT entries
            newestLUTStamp++;
        }
    }

    if (log)
        log->taskEnd();
}