DEF_TEST(Image_NewRasterCopy, reporter) { const SkPMColor red = SkPackARGB32(0xFF, 0xFF, 0, 0); const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0); const SkPMColor blue = SkPackARGB32(0xFF, 0, 0, 0xFF); SkPMColor colors[] = { red, green, blue, 0 }; SkAutoTUnref<SkColorTable> ctable(new SkColorTable(colors, SK_ARRAY_COUNT(colors))); // The colortable made a copy, so we can trash the original colors memset(colors, 0xFF, sizeof(colors)); const SkImageInfo srcInfo = SkImageInfo::Make(2, 2, kIndex_8_SkColorType, kPremul_SkAlphaType); const size_t srcRowBytes = 2 * sizeof(uint8_t); uint8_t indices[] = { 0, 1, 2, 3 }; SkAutoTUnref<SkImage> image(SkImage::NewRasterCopy(srcInfo, indices, srcRowBytes, ctable)); // The image made a copy, so we can trash the original indices memset(indices, 0xFF, sizeof(indices)); const SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(2, 2); const size_t dstRowBytes = 2 * sizeof(SkPMColor); SkPMColor pixels[4]; memset(pixels, 0xFF, sizeof(pixels)); // init with values we don't expect image->readPixels(dstInfo, pixels, dstRowBytes, 0, 0); REPORTER_ASSERT(reporter, red == pixels[0]); REPORTER_ASSERT(reporter, green == pixels[1]); REPORTER_ASSERT(reporter, blue == pixels[2]); REPORTER_ASSERT(reporter, 0 == pixels[3]); }
// https://bug.skia.org/4390 DEF_TEST(ImageFromIndex8Bitmap, r) { SkPMColor pmColors[1] = {SkPreMultiplyColor(SK_ColorWHITE)}; SkBitmap bm; SkAutoTUnref<SkColorTable> ctable( new SkColorTable(pmColors, SK_ARRAY_COUNT(pmColors))); SkImageInfo info = SkImageInfo::Make(1, 1, kIndex_8_SkColorType, kPremul_SkAlphaType); bm.allocPixels(info, nullptr, ctable); SkAutoLockPixels autoLockPixels(bm); *bm.getAddr8(0, 0) = 0; SkAutoTUnref<SkImage> img(SkImage::NewFromBitmap(bm)); REPORTER_ASSERT(r, img.get() != nullptr); }
static void make_bitmap(SkBitmap* bitmap, const SkImageInfo& info, SkBitmap::Allocator* allocator) { if (info.colorType() == kIndex_8_SkColorType) { bitmap->setInfo(info); SkPMColor ctStorage[256]; memset(ctStorage, 0xFF, sizeof(ctStorage)); // init with opaque-white for the moment SkAutoTUnref<SkColorTable> ctable(new SkColorTable(ctStorage, 256)); bitmap->allocPixels(allocator, ctable); } else if (allocator) { bitmap->setInfo(info); allocator->allocPixelRef(bitmap, 0); } else { bitmap->allocPixels(info); } }
static SkBitmap indexed_bitmap() { SkBitmap n32bitmap; n32bitmap.allocN32Pixels(SCALE, SCALE); n32bitmap.eraseColor(SK_ColorTRANSPARENT); SkCanvas canvas(n32bitmap); color_wheel_native(&canvas); const SkColor colors[] = { SK_ColorTRANSPARENT, SK_ColorWHITE, SK_ColorBLACK, SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW, }; SkPMColor pmColors[SK_ARRAY_COUNT(colors)]; for (size_t i = 0; i < SK_ARRAY_COUNT(colors); ++i) { pmColors[i] = premultiply_color(colors[i]); } SkBitmap bm; SkAutoTUnref<SkColorTable> ctable(new SkColorTable(pmColors, SK_ARRAY_COUNT(pmColors))); SkImageInfo info = SkImageInfo::Make(SCALE, SCALE, kIndex_8_SkColorType, kPremul_SkAlphaType); bm.allocPixels(info, nullptr, ctable); SkAutoLockPixels autoLockPixels1(n32bitmap); SkAutoLockPixels autoLockPixels2(bm); for (int y = 0; y < SCALE; ++y) { for (int x = 0; x < SCALE; ++x) { SkPMColor c = *n32bitmap.getAddr32(x, y); int idx = find(pmColors, SK_ARRAY_COUNT(pmColors), c); *bm.getAddr8(x, y) = SkClampMax(idx, SK_ARRAY_COUNT(pmColors) - 1); } } return bm; }
bool SkImageGenerator::tryGenerateBitmap(SkBitmap* bitmap, const SkImageInfo* infoPtr, SkBitmap::Allocator* allocator) { SkImageInfo info = infoPtr ? *infoPtr : this->getInfo(); if (0 == info.getSafeSize(info.minRowBytes())) { return false; } if (!bitmap->setInfo(info)) { return reset_and_return_false(bitmap); } SkPMColor ctStorage[256]; memset(ctStorage, 0xFF, sizeof(ctStorage)); // init with opaque-white for the moment SkAutoTUnref<SkColorTable> ctable(new SkColorTable(ctStorage, 256)); if (!bitmap->tryAllocPixels(allocator, ctable)) { // SkResourceCache's custom allcator can'thandle ctables, so it may fail on // kIndex_8_SkColorTable. // skbug.com/4355 #if 1 // ignroe the allocator, and see if we can succeed without it if (!bitmap->tryAllocPixels(nullptr, ctable)) { return reset_and_return_false(bitmap); } #else // this is the up-scale technique, not fully debugged, but we keep it here at the moment // to remind ourselves that this might be better than ignoring the allocator. info = SkImageInfo::MakeN32(info.width(), info.height(), info.alphaType()); if (!bitmap->setInfo(info)) { return reset_and_return_false(bitmap); } // we pass nullptr for the ctable arg, since we are now explicitly N32 if (!bitmap->tryAllocPixels(allocator, nullptr)) { return reset_and_return_false(bitmap); } #endif } bitmap->lockPixels(); if (!bitmap->getPixels()) { return reset_and_return_false(bitmap); } int ctCount = 0; if (!this->getPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), ctStorage, &ctCount)) { return reset_and_return_false(bitmap); } if (ctCount > 0) { SkASSERT(kIndex_8_SkColorType == bitmap->colorType()); // we and bitmap should be owners SkASSERT(!ctable->unique()); // Now we need to overwrite the ctable we built earlier, with the correct colors. // This does mean that we may have made the table too big, but that cannot be avoided // until we can change SkImageGenerator's API to return us the ctable *before* we have to // allocate space for all the pixels. ctable->dangerous_overwriteColors(ctStorage, ctCount); } else { SkASSERT(kIndex_8_SkColorType != bitmap->colorType()); // we should be the only owner SkASSERT(ctable->unique()); } return true; }
int fagzToCompact4(libmaus2::util::ArgInfo const & arginfo) { bool const rc = arginfo.getValue<unsigned int>("rc",1); bool const gz = arginfo.getValue<unsigned int>("gz",1); std::vector<std::string> inputfilenames; inputfilenames = arginfo.restargs; if ( arginfo.hasArg("inputfilenames") ) { std::string const inf = arginfo.getUnparsedValue("inputfilenames",std::string()); libmaus2::aio::InputStream::unique_ptr_type Pinf(libmaus2::aio::InputStreamFactoryContainer::constructUnique(inf)); while ( *Pinf ) { std::string line; std::getline(*Pinf,line); if ( line.size() ) inputfilenames.push_back(line); } } std::string const inlcp = libmaus2::util::OutputFileNameTools::lcp(inputfilenames); std::string defout = inlcp; defout = libmaus2::util::OutputFileNameTools::clipOff(defout,".gz"); defout = libmaus2::util::OutputFileNameTools::clipOff(defout,".fasta"); defout = libmaus2::util::OutputFileNameTools::clipOff(defout,".fa"); std::string const outputfilename = arginfo.getUnparsedValue("outputfilename",defout + ".compact"); std::string const metaoutputfilename = outputfilename + ".meta"; int const verbose = arginfo.getValue<int>("verbose",1); libmaus2::autoarray::AutoArray<char> B(8*1024,false); libmaus2::bitio::CompactArrayWriterFile compactout(outputfilename,2 /* bits per symbol */); if ( ! rc ) std::cerr << "[V] not storing reverse complements" << std::endl; // forward mapping table libmaus2::autoarray::AutoArray<uint8_t> ftable(256,false); // rc mapping for mapped symbols libmaus2::autoarray::AutoArray<uint8_t> ctable(256,false); std::fill(ftable.begin(),ftable.end(),4); std::fill(ctable.begin(),ctable.end(),4); ftable['a'] = ftable['A'] = 0; ftable['c'] = ftable['C'] = 1; ftable['g'] = ftable['G'] = 2; ftable['t'] = ftable['T'] = 3; uint64_t insize = 0; ctable[0] = 3; // A->T ctable[1] = 2; // C->G ctable[2] = 1; // G->C ctable[3] = 0; // T->A libmaus2::aio::OutputStreamInstance::unique_ptr_type metaOut(new libmaus2::aio::OutputStreamInstance(metaoutputfilename)); libmaus2::util::NumberSerialisation::serialiseNumber(*metaOut,0); uint64_t nseq = 0; std::vector<uint64_t> lvec; for ( uint64_t i = 0; i < inputfilenames.size(); ++i ) { std::string const fn = inputfilenames[i]; libmaus2::aio::InputStreamInstance CIS(fn); libmaus2::lz::BufferedGzipStream::unique_ptr_type BGS; std::istream * istr = 0; if ( gz ) { libmaus2::lz::BufferedGzipStream::unique_ptr_type tBGS( new libmaus2::lz::BufferedGzipStream(CIS)); BGS = UNIQUE_PTR_MOVE(tBGS); istr = BGS.get(); } else { istr = &CIS; } libmaus2::fastx::StreamFastAReaderWrapper fain(*istr); libmaus2::fastx::StreamFastAReaderWrapper::pattern_type pattern; while ( fain.getNextPatternUnlocked(pattern) ) { if ( verbose ) std::cerr << (i+1) << " " << stripAfterDot(basename(fn)) << " " << pattern.sid << "..."; libmaus2::util::NumberSerialisation::serialiseNumber(*metaOut,pattern.spattern.size()); lvec.push_back(pattern.spattern.size()); libmaus2::util::NumberSerialisation::serialiseNumber(*metaOut,0); // map symbols for ( uint64_t j = 0; j < pattern.spattern.size(); ++j ) pattern.spattern[j] = ftable[static_cast<uint8_t>(pattern.spattern[j])]; // replace blocks of N symbols by random bases uint64_t l = 0; // number of replaced blocks uint64_t nr = 0; while ( l < pattern.spattern.size() ) { // skip regular bases while ( l < pattern.spattern.size() && pattern.spattern[l] < 4 ) ++l; assert ( l == pattern.spattern.size() || pattern.spattern[l] == 4 ); // go to end of non regular bases block uint64_t h = l; while ( h < pattern.spattern.size() && pattern.spattern[h] == 4 ) ++h; // if non regular block is not empty if ( h-l ) { // replace by random bases for ( uint64_t j = l; j < h; ++j ) pattern.spattern[j] = (libmaus2::random::Random::rand8() & 3); // write bounds libmaus2::util::NumberSerialisation::serialiseNumber(*metaOut,l); libmaus2::util::NumberSerialisation::serialiseNumber(*metaOut,h); // add to interval counter nr += 1; } l = h; } // make sure there are no more irregular bases for ( uint64_t j = 0; j < pattern.spattern.size(); ++j ) assert ( pattern.spattern[j] < 4 ); // go back to start of meta data metaOut->seekp( - static_cast<int64_t>(2*nr+1)*sizeof(uint64_t), std::ios::cur ); // write number of intervals replaced libmaus2::util::NumberSerialisation::serialiseNumber(*metaOut,nr); // skip interval bounds already written metaOut->seekp( static_cast<int64_t>(2*nr )*sizeof(uint64_t), std::ios::cur ); // write bases compactout.write(pattern.spattern.c_str(),pattern.spattern.size()); // write reverse complement if requested if ( rc ) { // reverse complement std::reverse(pattern.spattern.begin(),pattern.spattern.end()); for ( uint64_t j = 0; j < pattern.spattern.size(); ++j ) pattern.spattern[j] = ctable[static_cast<uint8_t>(pattern.spattern[j])]; // write compactout.write(pattern.spattern.c_str(),pattern.spattern.size()); } insize += pattern.spattern.size()+1; nseq += 1; if ( verbose ) std::cerr << "done, input size " << formatBytes(pattern.spattern.size()+1) << " acc " << formatBytes(insize) << std::endl; } } metaOut->seekp(0); libmaus2::util::NumberSerialisation::serialiseNumber(*metaOut,nseq); metaOut->flush(); metaOut.reset(); libmaus2::aio::InputStreamInstance::unique_ptr_type metaISI(new libmaus2::aio::InputStreamInstance(metaoutputfilename)); // number of sequences uint64_t const rnseq = libmaus2::util::NumberSerialisation::deserialiseNumber(*metaISI); assert ( nseq == rnseq ); for ( uint64_t i = 0; i < nseq; ++i ) { // length of sequence uint64_t const l = libmaus2::util::NumberSerialisation::deserialiseNumber(*metaISI); assert ( l == lvec[i] ); uint64_t const nr = libmaus2::util::NumberSerialisation::deserialiseNumber(*metaISI); // skip replaced intervals metaISI->ignore(2*nr*sizeof(uint64_t)); } assert ( metaISI->peek() == std::istream::traits_type::eof() ); std::cerr << "Done, total input size " << insize << std::endl; compactout.flush(); return EXIT_SUCCESS; }