Esempio n. 1
0
    const ColorRanges* meta(Images&, const ColorRanges *srcRanges) {
//        cb->print();
        // in the I buckets, some discrete buckets may have become continuous to keep the colorbucket info small
        // this means some Q buckets are empty, which means that some values from the I buckets can be eliminated
        really_used = true;
        prevPlanes pixelL,pixelU;
        pixelL.push_back(cb->min0);
        pixelU.push_back(cb->min0+CB0b-1);
        pixelL.push_back(cb->min1);
        pixelU.push_back(cb->min1+CB1-1);
        for (auto bv : cb->bucket2) {
                pixelL[1] = cb->min1;
                pixelU[1] = cb->min1+CB1-1;
                for (auto b : bv) {
                        if (b.empty()) {
                                for (ColorVal c=pixelL[1]; c<=pixelU[1]; c++) {
                                  cb->findBucket(1,pixelL).removeColor(c);
                                  cb->findBucket(1,pixelU).removeColor(c);
                                }
                        }
                        pixelL[1] += CB1; pixelU[1] += CB1;
                }
                pixelL[0] += CB0b; pixelU[0] += CB0b;
        }
        cb->bucket0.prepare_snapvalues();
        cb->bucket3.prepare_snapvalues();
        for (auto& b : cb->bucket1) b.prepare_snapvalues();
        for (auto& bv : cb->bucket2) for (auto& b : bv) b.prepare_snapvalues();

        return new ColorRangesCB(srcRanges, cb);
    }
    void save_bucket(const ColorBucket &b, SimpleSymbolCoder<FLIFBitChanceMeta, RacOut<IO>, 18> &coder, const ColorRanges *srcRanges, const int plane, const prevPlanes &pixelL, const prevPlanes &pixelU) const {
        if (plane<3)
        for (int p=0; p<plane; p++) {
                if (!cb->exists(p,pixelL,pixelU)) {
                        if (!b.empty()) {printf("\nBucket does not exist but is not empty!\n"); assert(false);}
                        return;
                }
        }
        ColorVal smin,smax;
        minmax(srcRanges,plane,pixelL,pixelU,smin,smax);

        if (b.min > b.max) {
                coder.write_int(0, 1, 0);  // empty bucket
                return;
        } else coder.write_int(0, 1, 1);  // non-empty bucket
        if (smin==smax) { return;}


        coder.write_int(smin, smax, b.min);
        coder.write_int(b.min, smax, b.max);
        if (b.min == b.max) return;  // singleton bucket
        if (b.min + 1  == b.max) return; // bucket contains two consecutive values
        coder.write_int(0, 1, b.discrete);
        if (b.discrete) {
           assert((int)b.values.size() < b.max-b.min+1); // no discrete buckets that are completely full
           coder.write_int(2, std::min((int)max_per_colorbucket[plane],b.max-b.min), b.values.size());
           ColorVal v=b.min;
           int nb = b.values.size();
           for (int p=1; p < nb - 1; p++) {
               coder.write_int(v+1, b.max+1-nb+p, b.values[p]);
               v = b.values[p];
           }
        }
    }
    const ColorBucket load_bucket(SimpleSymbolCoder<FLIFBitChanceMeta, RacIn<IO>, 18> &coder, const ColorRanges *srcRanges, const int plane, const prevPlanes &pixelL, const prevPlanes &pixelU) const {
        ColorBucket b;
        if (plane<3)
        for (int p=0; p<plane; p++) {
                if (!cb->exists(p,pixelL,pixelU)) return b;
        }
//        SimpleBitCoder<FLIFBitChanceMeta, RacIn> bcoder(rac);

        ColorVal smin,smax;
        minmax(srcRanges,plane,pixelL,pixelU,smin,smax);

        int exists = coder.read_int(0, 1);
        if (exists == 0) {
           return b; // empty bucket
        }
        if (smin == smax) {b.min = b.max = smin; b.discrete=false; return b;}
        b.min = coder.read_int(smin, smax);
        b.max = coder.read_int(b.min, smax);
        if (b.min == b.max) { b.discrete=false; return b; }
        if (b.min + 1 == b.max) { b.discrete=false; return b; }
        b.discrete = coder.read_int(0,1);
        if (b.discrete) {
           int nb = coder.read_int(2, std::min((int)max_per_colorbucket[plane],b.max-b.min));
           b.values.push_back(b.min);
           ColorVal v=b.min;
             for (int p=1; p < nb-1; p++) {
               b.values.push_back(coder.read_int(v+1, b.max+1-nb+p));
               v = b.values[p];
             }
           if (b.min < b.max) b.values.push_back(b.max);
        }
        return b;
    }
    bool process(const ColorRanges *srcRanges, const Images &images) {
            std::vector<ColorVal> pixel(images[0].numPlanes());
            // fill buckets
            for (const Image& image : images)
            for (uint32_t r=0; r<image.rows(); r++) {
                for (uint32_t c=0; c<image.cols(); c++) {
                  int p;
                  for (p=0; p<image.numPlanes(); p++) {
                    ColorVal v = image(p,r,c);
                    pixel[p] = v;
                  }
                  if (image.alpha_zero_special && p>3 && pixel[3]==0) { cb->findBucket(3, pixel).addColor(0,max_per_colorbucket[3]); continue;}
                  cb->addColor(pixel);
                }
            }

            cb->bucket0.simplify_lossless();
            cb->bucket3.simplify_lossless();
            for (auto& b : cb->bucket1) b.simplify_lossless();
            for (auto& bv : cb->bucket2) for (auto& b : bv) b.simplify_lossless();


        // TODO: IMPROVE THESE HEURISTICS!
        // TAKE IMAGE SIZE INTO ACCOUNT!
        // CONSIDER RELATIVE AREA OF BUCKETS / BOUNDS!

//            printf("Filled color buckets with %i discrete colors + %i continous buckets\n",totaldiscretecolors,totalcontinuousbuckets);

            int64_t total_pixels = (int64_t) images.size() * images[0].rows() * images[0].cols();
            v_printf(7,", [D=%i,C=%i,P=%i]",totaldiscretecolors,totalcontinuousbuckets,(int) (total_pixels/100));
            if (totaldiscretecolors < total_pixels/200 && totalcontinuousbuckets < total_pixels/50) return true;
            if (totaldiscretecolors < total_pixels/100 && totalcontinuousbuckets < total_pixels/200) return true;
            if (totaldiscretecolors < total_pixels/40 && totalcontinuousbuckets < total_pixels/500) return true;

            // simplify buckets
            for (int factor = 95; factor >= 35; factor -= 10) {
                for (auto& b : cb->bucket1) b.simplify(factor);
                for (auto& bv : cb->bucket2) for (auto& b : bv) b.simplify(factor-20);
                v_printf(8,"->[D=%i,C=%i]",totaldiscretecolors,totalcontinuousbuckets);
                if (totaldiscretecolors < total_pixels/200 && totalcontinuousbuckets < total_pixels/100) return true;
            }
            return false;
    }
Esempio n. 5
0
    void save_bucket(const ColorBucket &b, SimpleSymbolCoder<FLIFBitChanceMeta, RacOut<IO>, 24> &coder, const ColorRanges *srcRanges, const int plane, const prevPlanes &pixelL, const prevPlanes &pixelU) const {
        if (plane<3)
        for (int p=0; p<plane; p++) {
                if (!cb->exists(p,pixelL,pixelU)) {
                        if (!b.empty()) {printf("\nBucket does not exist but is not empty!\n"); assert(false);}
                        return;
                }
        }
//        SimpleBitCoder<FLIFBitChanceMeta, RacOut> bcoder(rac);
//        if (b.min > b.max) printf("SHOULD NOT HAPPEN!\n");

        ColorVal smin,smax;
        minmax(srcRanges,plane,pixelL,pixelU,smin,smax);
        if (smin==smax) { return;}

//        b.printshort();
//        b.print();

        if (b.min > b.max) {
                coder.write_int(0, 1, 0);  // empty bucket
                return;
        } else coder.write_int(0, 1, 1);  // non-empty bucket


        coder.write_int(smin, smax, b.min);
        coder.write_int(b.min, smax, b.max);
        if (b.min == b.max) return;  // singleton bucket
        if (b.min + 1  == b.max) return; // bucket contains two consecutive values
        coder.write_int(0, 1, b.discrete);
        if (b.discrete) {
           coder.write_int(2, max_per_colorbucket[plane], b.values.size());
           ColorVal v=b.min;
/*           if (b.values.size() > 10) {
             v++;
             bcoder.set( 0x1000 * (b.values.size()-2) / (b.max-b.min-1) );
             for (unsigned int p=1; p < b.values.size() - 1; p++) {
               while (v<b.values[p]) { bcoder.write(0); v++; }
               bcoder.write(1); v++;
             }
           } else   */
             for (unsigned int p=1; p < b.values.size() - 1; p++) {
               coder.write_int(v+1, b.max-1, b.values[p]);
//               coder.write_int(0, b.max-v-2, b.values[p]-v-1);
               v = b.values[p];
             }
        }
    }
Esempio n. 6
0
    ColorBucket load_bucket(SimpleSymbolCoder<FLIFBitChanceMeta, RacIn<IO>, 24> &coder, const ColorRanges *srcRanges, const int plane, const prevPlanes &pixelL, const prevPlanes &pixelU) {
        ColorBucket b;
        if (plane<3)
        for (int p=0; p<plane; p++) {
                if (!cb->exists(p,pixelL,pixelU)) return b;
        }
//        SimpleBitCoder<FLIFBitChanceMeta, RacIn> bcoder(rac);

        ColorVal smin,smax;
        minmax(srcRanges,plane,pixelL,pixelU,smin,smax);
        if (smin == smax) {b.min = b.max = smin; b.discrete=false; return b;}

        int exists = coder.read_int(0, 1);
        if (exists == 0) {
           return b; // empty bucket
        }
        b.min = coder.read_int(smin, smax);
        b.max = coder.read_int(b.min, smax);
        if (b.min == b.max) { b.discrete=false; return b; }
        if (b.min + 1 == b.max) { b.discrete=false; return b; }
        b.discrete = coder.read_int(0,1);
        if (b.discrete) {
           int nb = coder.read_int(2, max_per_colorbucket[plane]);
           b.values.push_back(b.min);
           ColorVal v=b.min;
/*           if (nb > 10) {
             v++;
             bcoder.set( 0x1000 * (nb-2) / (b.max-b.min-1) );
             for (int p=1; p < nb - 1; p++) {
               while (bcoder.read() == 0) { v++; }
               b.values.push_back(v); v++;
             }
           } else */
             for (int p=1; p < nb-1; p++) {
               b.values.push_back(coder.read_int(v+1, b.max-1));
//               b.values.push_back(v+1+coder.read_int(0, b.max-v-2));
//               printf("val %i\n",b.values[p]);
               v = b.values[p];
             }
           if (b.min < b.max) b.values.push_back(b.max);
        }
//        b.print();
        return b;
    }
Esempio n. 7
0
 void print() {
     buckets->print();
 }
Esempio n. 8
0
 ColorBucket bucket(const int p, const prevPlanes &pp) const { return buckets->findBucket(p,pp); }