Пример #1
0
RGB24Buffer * alphaBlend(RGB24Buffer *in1, RGB24Buffer *in2, G8Buffer *alpha)
{

    RGB24Buffer *result = new RGB24Buffer(in1->getSize());

    for (int i = 0; i < result->h; i++)
    {
        for (int j = 0; j < result->w; j++)
        {
            RGBColor maskEl   = in1->element(i,j);
            RGBColor faceEl   = in2->element(i,j);
            int a = alpha->element(i,j);
            int b = 255 - a;

            int r1 = maskEl.r();
            int g1 = maskEl.g();
            int b1 = maskEl.b();

            int r2 = faceEl.r();
            int g2 = faceEl.g();
            int b2 = faceEl.b();

            RGBColor resultEl( (r1 * a + r2 * b) / 255, (g1 * a + g2 * b) / 255, (b1 * a + b2 * b) / 255 );
            result->element(i,j) = resultEl;
        }
    }
    return result;
}
    bool operator()(RGB24Buffer *buffer, int x, int y) {
        if (mMask->element(y,x) == 255)
            return false;

        RGBColor currentColor = buffer->element(y,x);
        int r = (int)currentColor.r() - (int)mStartColor.r();
        int g = (int)currentColor.g() - (int)mStartColor.g();
        int b = (int)currentColor.b() - (int)mStartColor.b();

        int sum = abs(r) + abs(g) + abs(b);
        if (sum > mTolerance) {
           return false;
        }
        return true;
     }
Пример #3
0
void Bitmap::SetPixel(int x, int y, const RGBColor &c)
{
    CheckCoordinates(x, y);
    data_[y * bi_.width + x].red = c.r();
    data_[y * bi_.width + x].green = c.g();
    data_[y * bi_.width + x].blue = c.b();
    return;
}
Пример #4
0
void Bitmap::SetPixelImageCoordinates(int i, int j, const RGBColor &c)
{
    CheckImageCoordinates(i, j);
    const int image_coordinates_i = height_ - i - 1;
    data_[image_coordinates_i * width_ + j].red = c.r();
    data_[image_coordinates_i * width_ + j].green = c.g();
    data_[image_coordinates_i * width_ + j].blue = c.b();
    return;
}
void TestbedMainWindow::recursiveTolerance(RGBColor startColor, int tolerance, int x, int y)
{
    if (!mMask->isValidCoord(y,x))
        return;
    if (mMask->element(y,x))
        return;
    RGBColor currentColor = mImage->element(y,x);
    int r = (int)currentColor.r() - (int)startColor.r();
    int g = (int)currentColor.g() - (int)startColor.g();
    int b = (int)currentColor.b() - (int)startColor.b();

    int sum = abs(r) + abs(g) + abs(b);
    if (sum > tolerance)
        return;

    mMask->element(y,x) = 255;

    recursiveTolerance(startColor, tolerance, x - 1, y    );
    recursiveTolerance(startColor, tolerance, x + 1, y    );
    recursiveTolerance(startColor, tolerance, x    , y + 1);
    recursiveTolerance(startColor, tolerance, x    , y - 1);
}
Пример #6
0
void PaintImageWidget::childRepaint(QPaintEvent *event, QWidget *who)
{
    AdvancedImageWidget::childRepaint(event, who);
    if (mImage.isNull())
    {
        return;
    }

    /* Now the points */
    QPainter painter(who);

    for (unsigned i = 0; i < mFeatures.mPoints.size(); i ++)
    {
        SelectableGeometryFeatures::Vertex *vertex = mFeatures.mPoints[i];
        painter.setPen(vertex->isSelected() ? Qt::red : Qt::green);
        if (vertex->ownerPath == NULL)
        {
            drawCircle(painter, imageToWidgetF(vertex->position), 5);
        }
        else
        {
            drawSquare(painter, imageToWidgetF(vertex->position), 5);
        }

        if (vertex->weight >= 0.0)
        {
            RGBColor color = RGBColor::rainbow1(vertex->weight);
            painter.setPen(QColor(color.r(), color.g(), color.b()));
            drawCircle(painter, imageToWidgetF(vertex->position), 7);
        }

    }

    for (unsigned i = 0; i < mFeatures.mPaths.size(); i++)
    {
        SelectableGeometryFeatures::VertexPath *path = mFeatures.mPaths[i];
        painter.setPen(path->mSelected ? Qt::yellow : Qt::green);
        for (unsigned i = 1; i < path->vertexes.size(); i++)
        {
            Vector2dd point1 = path->vertexes[i    ]->position;
            Vector2dd point2 = path->vertexes[i - 1]->position;
            drawLine(painter, imageToWidgetF(point1), imageToWidgetF(point2));
        }
    }
}
    bool operator()(RGB24Buffer *buffer, int x, int y) {
        if (mMask->element(y,x) == 255)
            return false;

        if (!mLimit.contains(x,y))
            return false;

        RGBColor currentColor = buffer->element(y,x);
        for (unsigned i = 0; i < mStartColor.size(); i++)
        {
            RGBColor &color = mStartColor[i];
            int r = (int)currentColor.r() - (int)color.r();
            int g = (int)currentColor.g() - (int)color.g();
            int b = (int)currentColor.b() - (int)color.b();

            int sum = abs(r) + abs(g) + abs(b);
            if (sum < mTolerance) {
               return true;
            }
        }
        return false;
     }
void TestbedMainWindow::updateViewImage(void)
{
    enum {IMAGE, MASK, HUE, SATURATION, VALUE, EDGES, CANNY, PRINCIPAL, SECONDARY, THIRD};

    switch (mUi->bufferSelectBox->currentIndex()) {
        case IMAGE:
            {
                if (mImage == NULL) {
                    return;
                }

                if (mUi->blendEdgeCheckBox->isChecked())
                {
                    prepareBlendedMask();
                }

                RGB24Buffer *toDraw = new RGB24Buffer(mImage);
                RGBColor maskColor = mUi->maskColorWidget->getColor();
                double alpha = (mUi->maskAlphaSpinBox->value()) / 100.0;
                if (mUi->actionShowMask->isChecked())
                {
                    for (int i = 0; i < toDraw->h; i++)
                    {
                        for (int j = 0; j < toDraw->w; j++)
                        {
                            bool hasmask = false;
                            bool hasnomask = false;
                            /* so far no optimization here */
                            if (mUi->showEdgeCheckBox->isChecked()) {
                                for (int dx = -1; dx <= 1; dx++)
                                {
                                    for (int dy = -1; dy <= 1; dy++)
                                    {
                                        if (!mMask->isValidCoord(i + dy, j + dx))
                                            continue;
                                        if (mMask->element(i + dy, j + dx)) {
                                            hasmask = true;
                                        } else {
                                            hasnomask = true;
                                        }
                                    }
                                }
                            }

                            if (mUi->blendEdgeCheckBox->isChecked())
                            {
                                double scaler = alpha * mMaskBlended->element(i,j) / 255;
                                toDraw->element(i,j).r() += (maskColor.r() - toDraw->element(i,j).r()) * scaler;
                                toDraw->element(i,j).g() += (maskColor.g() - toDraw->element(i,j).g()) * scaler;
                                toDraw->element(i,j).b() += (maskColor.b() - toDraw->element(i,j).b()) * scaler;
                            } else {
                                if (mMask->element(i,j)) {
                                    toDraw->element(i,j).r() += (maskColor.r() - toDraw->element(i,j).r()) * alpha;
                                    toDraw->element(i,j).g() += (maskColor.g() - toDraw->element(i,j).g()) * alpha;
                                    toDraw->element(i,j).b() += (maskColor.b() - toDraw->element(i,j).b()) * alpha;
                                }
                            }


                            if (mMask->element(i,j)) {
                                if (hasmask && hasnomask) {
                                    toDraw->element(i,j) = mUi->edgeColorWidget->getColor();
                                }
                            }

                            if (mUi->levelDebugCheckBox->isChecked() && mMaskStore != NULL && mMaskStore->element(i,j) != 0)
                            {
                                if (mMaskStore->element(i,j) > mUi->levelSpinBox->value())
                                {
                                    toDraw->element(i,j) = RGBColor::Red();
                                } else {
                                    toDraw->element(i,j) = RGBColor::Blue();
                                }

                            }
                        }
                    }
                }

                QImage *qImage = new RGB24Image(toDraw);
                mImageWidget->setImage(QSharedPointer<QImage>(qImage));
                delete_safe(toDraw);
            }
            break;
        case MASK:
                mImageWidget->setImage(QSharedPointer<QImage>(new G8Image(mMask)));
            break;
        case HUE:
                mImageWidget->setImage(QSharedPointer<QImage>(new G8Image(mHComp)));
            break;
        case SATURATION:
                mImageWidget->setImage(QSharedPointer<QImage>(new G8Image(mSComp)));
            break;
        case VALUE:
                mImageWidget->setImage(QSharedPointer<QImage>(new G8Image(mVComp)));
            break;
        case EDGES:
                mImageWidget->setImage(QSharedPointer<QImage>(new G12Image(mEdges)));
            break;
        case CANNY:
                mImageWidget->setImage(QSharedPointer<QImage>(new G12Image(mCannyEdges)));
            break;
        case PRINCIPAL:
                mImageWidget->setImage(QSharedPointer<QImage>(new G8Image(mPrincipal)));
            break;
        case SECONDARY:
                mImageWidget->setImage(QSharedPointer<QImage>(new G8Image(mPrincipal2)));
            break;
        case THIRD:
        default:
                mImageWidget->setImage(QSharedPointer<QImage>(new G8Image(mPrincipal3)));
            break;
    }


}
Пример #9
0
    /**
    * @brief Copy constructor
    * @param val Source RGBA value
    */
    inline Rgba( const RGBColor & val )
      : Base( val.r(), val.g(), val.b(), static_cast<T>( 1 ) )
    {

    }
/// Find the color of the SfM_Data Landmarks/structure
void ColorizeTracks(
  const SfM_Data & sfm_data,
  std::vector<Vec3> & vec_3dPoints,
  std::vector<Vec3> & vec_tracksColor)
{
  // Colorize each track
  //  Start with the most representative image
  //    and iterate to provide a color to each 3D point

  {
    C_Progress_display my_progress_bar(sfm_data.getLandmarks().size(),
                                       std::cout,
                                       "\nCompute scene structure color\n");

    vec_tracksColor.resize(sfm_data.getLandmarks().size());
    vec_3dPoints.resize(sfm_data.getLandmarks().size());

    //Build a list of contiguous index for the trackIds
    std::map<IndexT, IndexT> trackIds_to_contiguousIndexes;
    IndexT cpt = 0;
    for (Landmarks::const_iterator it = sfm_data.getLandmarks().begin();
      it != sfm_data.getLandmarks().end(); ++it, ++cpt)
    {
      trackIds_to_contiguousIndexes[it->first] = cpt;
      vec_3dPoints[cpt] = it->second.X;
    }

    // The track list that will be colored (point removed during the process)
    std::set<IndexT> remainingTrackToColor;
    std::transform(sfm_data.getLandmarks().begin(), sfm_data.getLandmarks().end(),
      std::inserter(remainingTrackToColor, remainingTrackToColor.begin()),
      RetrieveKey() );

    while( !remainingTrackToColor.empty() )
    {
      // Find the most representative image (for the remaining 3D points)
      //  a. Count the number of observation per view for each 3Dpoint Index
      //  b. Sort to find the most representative view index

      std::map<IndexT, IndexT> map_IndexCardinal; // ViewId, Cardinal
      for (std::set<IndexT>::const_iterator
        iterT = remainingTrackToColor.begin();
        iterT != remainingTrackToColor.end();
        ++iterT)
      {
        const size_t trackId = *iterT;
        const Observations & obs = sfm_data.getLandmarks().at(trackId).obs;
        for( Observations::const_iterator iterObs = obs.begin();
          iterObs != obs.end(); ++iterObs)
        {
          const size_t viewId = iterObs->first;
          if (map_IndexCardinal.find(viewId) == map_IndexCardinal.end())
            map_IndexCardinal[viewId] = 1;
          else
            ++map_IndexCardinal[viewId];
        }
      }

      // Find the View index that is the most represented
      std::vector<IndexT> vec_cardinal;
      std::transform(map_IndexCardinal.begin(),
        map_IndexCardinal.end(),
        std::back_inserter(vec_cardinal),
        RetrieveValue());
      using namespace indexed_sort;
      std::vector< sort_index_packet_descend< IndexT, IndexT> > packet_vec(vec_cardinal.size());
      sort_index_helper(packet_vec, &vec_cardinal[0], 1);

      // First image index with the most of occurence
      std::map<IndexT, IndexT>::const_iterator iterTT = map_IndexCardinal.begin();
      std::advance(iterTT, packet_vec[0].index);
      const size_t view_index = iterTT->first;
      const View * view = sfm_data.getViews().at(view_index).get();
      const std::string sView_filename = stlplus::create_filespec(sfm_data.s_root_path,
        view->s_Img_path);
      Image<RGBColor> image;
      ReadImage(sView_filename.c_str(), &image);

      // Iterate through the remaining track to color
      // - look if the current view is present to color the track
      std::set<IndexT> set_toRemove;
      for (std::set<IndexT>::const_iterator
        iterT = remainingTrackToColor.begin();
        iterT != remainingTrackToColor.end();
        ++iterT)
      {
        const size_t trackId = *iterT;
        const Observations & obs = sfm_data.getLandmarks().at(trackId).obs;
        Observations::const_iterator it = obs.find(view_index);

        if (it != obs.end())
        {
          // Color the track
          const Vec2 & pt = it->second.x;
          const RGBColor color = image(pt.y(), pt.x());

          vec_tracksColor[ trackIds_to_contiguousIndexes[trackId] ] = Vec3(color.r(), color.g(), color.b());
          set_toRemove.insert(trackId);
          ++my_progress_bar;
        }
      }
      // Remove colored track
      for (std::set<IndexT>::const_iterator iter = set_toRemove.begin();
        iter != set_toRemove.end(); ++iter)
      {
        remainingTrackToColor.erase(*iter);
      }
    }
  }
}
Пример #11
0
inline void Convert<RGBColor, unsigned char>(
  const RGBColor& valin, unsigned char& valOut)
{
  valOut = static_cast<unsigned char>(0.3 * valin.r() + 0.59 * valin.g() + 0.11 * valin.b());
}
Пример #12
0
int main (int argc, char **argv)
{
	QCoreApplication app(argc, argv);
	printf("Loading mask...\n");
    QTRGB24Loader  ::registerMyself();
    QTG12Loader    ::registerMyself();
    QTRuntimeLoader::registerMyself();

	QImage imageMask    ("data/adopt/orig.png");
	QImage imageAlpha   ("data/adopt/alpha.bmp");
    QImage imageFace    ("data/adopt/face.png");

    RGB24Buffer *alpha24 = QTFileLoader::RGB24BufferFromQImage(&imageAlpha);
    RGB24Buffer *mask    = QTFileLoader::RGB24BufferFromQImage(&imageMask);
    RGB24Buffer *face    = QTFileLoader::RGB24BufferFromQImage(&imageFace);

    G8Buffer *alpha = alpha24->getChannel(ImageChannel::GRAY);

    Vector3dd meanMask(0.0);
    Vector3dd meanFace(0.0);
    double count = 0;

	/* Get hole statistics */
    for (int i = 0; i < mask->h; i++)
    {
        for (int j = 0; j < mask->w; j++)
        {
            if (alpha->element(i,j) > 10)
                continue;

            count++;
            meanFace += face->element(i,j).toDouble();
            meanMask += mask->element(i,j).toDouble();
        }
    }

    meanFace /= count;
    meanMask /= count;

    cout << "Mean face value is" << meanFace << endl;
    cout << "Mean face value is" << meanMask << endl;

    EllipticalApproximationUnified<Vector3dd> facePrincipal;
    EllipticalApproximationUnified<Vector3dd> maskPrincipal;

    for (int i = 0; i < mask->h; i++)
    {
       for (int j = 0; j < mask->w; j++)
       {
           facePrincipal.addPoint(face->element(i,j).toDouble() - meanFace);
           maskPrincipal.addPoint(mask->element(i,j).toDouble() - meanMask);
       }
    }
    facePrincipal.getEllipseParameters();
    maskPrincipal.getEllipseParameters();

    cout << "Face Principals" << endl;
    cout << facePrincipal.mAxes[0] << "->" << facePrincipal.mValues[0] << endl;
    cout << facePrincipal.mAxes[1] << "->" << facePrincipal.mValues[1] << endl;
    cout << facePrincipal.mAxes[2] << "->" << facePrincipal.mValues[2] << endl;

    cout << "Mask Principals" << endl;
    cout << maskPrincipal.mAxes[0] << "->" << maskPrincipal.mValues[0] << endl;
    cout << maskPrincipal.mAxes[1] << "->" << maskPrincipal.mValues[1] << endl;
    cout << maskPrincipal.mAxes[2] << "->" << maskPrincipal.mValues[2] << endl;

    Vector3dd scalers;
    scalers.x() = sqrt(maskPrincipal.mValues[0]) / sqrt(facePrincipal.mValues[0]);
    scalers.y() = sqrt(maskPrincipal.mValues[1]) / sqrt(facePrincipal.mValues[1]);
    scalers.z() = sqrt(maskPrincipal.mValues[2]) / sqrt(facePrincipal.mValues[2]);

    /* Making correction for face */
    RGB24Buffer *faceCorr = new RGB24Buffer(face->getSize(), false);
    for (int i = 0; i < faceCorr->h; i++)
    {
       for (int j = 0; j < faceCorr->w; j++)
       {
           Vector3dd color = face->element(i,j).toDouble() - meanFace;
           Vector3dd projected(color & facePrincipal.mAxes[0],
                      color & facePrincipal.mAxes[1],
                      color & facePrincipal.mAxes[2]);

           projected = projected * scalers;

           Vector3dd newColor =
                   maskPrincipal.mAxes[0] * projected.x() +
                   maskPrincipal.mAxes[1] * projected.y() +
                   maskPrincipal.mAxes[2] * projected.z() + meanMask;
           RGBColor newrgb;
           double c;
           c = newColor.x();
           if (c <   0) c =   0;
           if (c > 255) c = 255;
           newrgb.r() = c;
           c = newColor.y();
           if (c <   0) c =   0;
           if (c > 255) c = 255;
           newrgb.g() = c;
           c = newColor.z();
           if (c <   0) c =   0;
           if (c > 255) c = 255;
           newrgb.b() = c;

           faceCorr->element(i,j) = newrgb;
       }
    }

    /* With Matrix*/
    Matrix33 scalerM    = Matrix33::Scale3(scalers);
    Matrix33 toUnityM   = Matrix33::FromRows(facePrincipal.mAxes[0], facePrincipal.mAxes[1], facePrincipal.mAxes[2]);
    Matrix33 fromUnityM = Matrix33::FromColumns(maskPrincipal.mAxes[0], maskPrincipal.mAxes[1], maskPrincipal.mAxes[2]);

    Matrix33 transform = fromUnityM * scalerM * toUnityM;

    RGB24Buffer *faceCorr2 = new RGB24Buffer(face->getSize(), false);
    for (int i = 0; i < faceCorr2->h; i++)
    {
       for (int j = 0; j < faceCorr2->w; j++)
       {
           Vector3dd newColor = transform * (face->element(i,j).toDouble() - meanFace) + meanMask;
           RGBColor newrgb;
           double c;
           c = newColor.x();
           if (c <   0) c =   0;
           if (c > 255) c = 255;
           newrgb.r() = c;
           c = newColor.y();
           if (c <   0) c =   0;
           if (c > 255) c = 255;
           newrgb.g() = c;
           c = newColor.z();
           if (c <   0) c =   0;
           if (c > 255) c = 255;
           newrgb.b() = c;

           faceCorr2->element(i,j) = newrgb;
       }
    }


    /* Without roots */
    scalers.x() = maskPrincipal.mValues[0] / facePrincipal.mValues[0];
    scalers.y() = maskPrincipal.mValues[1] / facePrincipal.mValues[1];
    scalers.z() = maskPrincipal.mValues[2] / facePrincipal.mValues[2];


    /* Making correction for face */
    RGB24Buffer *faceCorr1 = new RGB24Buffer(face->getSize(), false);
    for (int i = 0; i < faceCorr1->h; i++)
    {
       for (int j = 0; j < faceCorr1->w; j++)
       {
           Vector3dd color = face->element(i,j).toDouble() - meanFace;
           Vector3dd projected(color & facePrincipal.mAxes[0],
                      color & facePrincipal.mAxes[1],
                      color & facePrincipal.mAxes[2]);

           projected = projected * scalers;

           Vector3dd newColor =
                   maskPrincipal.mAxes[0] * projected.x() +
                   maskPrincipal.mAxes[1] * projected.y() +
                   maskPrincipal.mAxes[2] * projected.z() + meanMask;
           RGBColor newrgb;
           double c;
           c = newColor.x();
           if (c <   0) c =   0;
           if (c > 255) c = 255;
           newrgb.r() = c;
           c = newColor.y();
           if (c <   0) c =   0;
           if (c > 255) c = 255;
           newrgb.g() = c;
           c = newColor.z();
           if (c <   0) c =   0;
           if (c > 255) c = 255;
           newrgb.b() = c;

           faceCorr1->element(i,j) = newrgb;
       }
    }



    /* Make a final blending */
    BMPLoader().save("output0.bmp", mask);


    RGB24Buffer *result = alphaBlend(mask, face, alpha);
	BMPLoader().save("output1.bmp", result);

	RGB24Buffer *result1 = alphaBlend(mask, faceCorr, alpha);
	BMPLoader().save("output2.bmp", result1);

	RGB24Buffer *result2 = alphaBlend(mask, faceCorr1, alpha);
    BMPLoader().save("output3.bmp", result2);

    RGB24Buffer *result3 = alphaBlend(mask, faceCorr2, alpha);
    BMPLoader().save("matrix-out.bmp", result3);


	delete_safe(alpha);
    delete_safe(mask);
    delete_safe(face);
    delete_safe(faceCorr);
    delete_safe(faceCorr1);
    delete_safe(faceCorr2);

    delete_safe(result);
    delete_safe(result1);
    delete_safe(result2);
    delete_safe(result3);
    return 0;
}
Пример #13
0
void OpenGLTools::glColorRGB(const RGBColor &color)
{
    //glColor3f(color.r() / 256.0, color.g() / 256.0, color.b() / 256.0);
    glColor3ub(color.r(), color.g(), color.b());
}
Пример #14
0
/**
 * TODO: Add error handling
 *
 * */
bool BMPLoader::save(string name, RGB24Buffer *buffer)
{
    CORE_ASSERT_TRUE(buffer != NULL, "Null buffer could not be saved");
    FILE *fp = fopen(name.c_str(), "wb");
    if (fp == NULL)
        return false;

    int w = buffer->w;
    int h = buffer->h;

    /*Line length in BMP is always 32bit aligned*/
    int lineLength = w * 3;
    lineLength = (lineLength % 4) ? (lineLength | 0x3) + 1 : lineLength;
    int fileSize = BMPHeader::HEADER_SIZE + h * lineLength;

    uint8_t *data = new uint8_t[fileSize];
    if (!data)
    {
        fclose(fp);
        return false;
    }

    memset(data, 0, BMPHeader::HEADER_SIZE /*fileSize*/);

    data[0x0] = BMPHeader::HEADER_SIGNATURE[0];
    data[0x1] = BMPHeader::HEADER_SIGNATURE[1];
    *((uint32_t *)(data + 0x2)) =  h * lineLength + BMPHeader::HEADER_SIZE;
    data[0x6] = 0;
    data[0x7] = 0;
    *((uint32_t *)(data + 0xA))  = BMPHeader::HEADER_SIZE;
    *((uint32_t *)(data + 0xE))  = 0x28;
    *((uint32_t *)(data + 0x12)) = w;
    *((uint32_t *)(data + 0x16)) = h;
    *((uint16_t *)(data + 0x1A)) = 1;
    *((uint16_t *)(data + 0x1C)) = 24;
    *((uint32_t *)(data + 0x1E)) = 0;
    *((uint32_t *)(data + 0x22)) = lineLength * h;
    *((uint32_t *)(data + 0x26)) = 0x0000B013;
    *((uint32_t *)(data + 0x2A)) = 0x0000B013;
    *((uint32_t *)(data + 0x2E)) = 0x0;
    *((uint32_t *)(data + 0x32)) = 0x0;

    for (int i = 0; i < h; i++)
    {
        uint8_t *offset = data + BMPHeader::HEADER_SIZE + (lineLength * (h - 1 - i));   // lines are flipped vertically there
        int j;
        for (j = 0; j < w; j++)
        {
            RGBColor pixel = buffer->element(i, j);
            *offset++ = pixel.b();
            *offset++ = pixel.g();
            *offset++ = pixel.r();
        }
        // Put in predictable padding values
        for (int k = j * 3; k < lineLength; k++)
        {
            *offset++ = 0;
        }
    }

    fwrite(data, sizeof(uint8_t), fileSize, fp);
    fclose(fp);

    delete[] data;
    return true;
}