|
Is that the same day as you saw BOM for the first time?
What is wrong with BOM? That you don't want to see it at all? That for this specific file, it "isn't needed", because all it contains is 7-bit US-ASCII?
You may of course declare that "I handle 7-bit US-ASCII only, so don't disturb me with anything else - Unicode is not my business, even when the characters are limited to US-ASCII. Just bug off with anything else!"
Fair enough, but then the software you produce is not for me. Most likely not for very many people outside the English speaking world. You are most certainly expected to handle BOM and Unicode/UTF8 today. If you are handling CSV, your are supposed to understand that in major parts of the world, it is five comma three, not five point three.
For the other stuff you mention: Fair enough; that should be easy to handle. If you haven't yet discovered that there are lots of variations in CSV formats (e.g. they are certainly not always comma separated, like in cultures where the decimal separator is not the point), take a look at the import options in Excel: It has handled this stuff for at least 15 year - I'd guess a lot more. Accept reality as it is, not as if reality was a problem.
And so on. You are free to put up a sign at your door: "Warning: No non-American data is handled by our software!" Actually, I'd be happy to know in advance, rather than discovering after I have signed a contract.
|
|
|
|
|
Thanks for the reply and for allowing me to realize that I had mis-titled the thread. I understand that the word 'Hate' was inappropriate for a number of reasons, firstly because I despise that word, and secondly because of your point about reality.
In my defense, the 'problem' had already been dealt with, (code fixed, tested, compiled, tested, and deployed) for the two affected imports before I made that post. I was simply annoyed about spending that hour diagnosing and fixing something that I'd never seen before...weird characters trashing the first element in a csv.
Per your post, I had a few ways to deal with it, now having a crash course in BOM:
0: Tell the customer that they would have to change the encoding. (put up a sign) The customer gets these data files from other departments/systems. To change the encoding is would likely be a manual process. Not ideal at all.
1: Be aware that a text/csv file might have those three weird characters at the beginning of the file. If so, disregard the BOM and move on.
2: Go into full research mode and discover all that there is to know about BOM and how it might be needed for all of my non-US customers. (current/future === none)
I chose option 1. The reality is that I have to deal with it. The chances that I get a file from a US customer that is BOM encoded, and that does not have headers, and where the first element of the line is important have become realized. I didn't account for the BOM and got 'bitten'.
Anyhow, my customer is happy again. I've learned something new and improved my software.
One of my favorite things about this profession is the constant learning and improving.
"Go forth into the source" - Neal Morse
"Hope is contagious"
|
|
|
|
|
The only thing to hate is hate itself.
|
|
|
|
|
|
"UTF-8 BOM considered harmful."
I'm assuming you're talking about UTF-8. Including a BOM with UTF-8 is generally unnecessary and frowned upon in most cases.
I'll have to review my latest text file reader to see what I do with them -- one I wrote earlier this year would ignore a UTF-8 BOM if it was the first three bytes of a file.
In general, a file should have only one encoding, but there is no requirement for that to be the case. If a file switches between encoding, then I believe a suitable BOM must be used to indicate that. But good luck finding a reader which will honor such an abomination.
When this sort of thing is more likely to be a concern is when reading from a non-file-backed stream such as a socket -- but I would expect that other controls would be put in place to avoid confusion.
Now I need to go create a CSV file which is UTF-8, but with a UTF-16 Word document as one of its values... (muhahaha!)
|
|
|
|
|
I forget the exact code, but the byte order mark is easy to check for and skip programmatically.
Something like the high bit is set. (I forget the actual details) so you can just check for that, and if you see it, skip that byte and the next. If I got something wrong here, forgive me, it's half remembered from years ago, but the concept is simple enough. Check with a mask, and then skip the mark if the mask is set.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
Yes, I depended upon some code I was writing at jsfiddle.net and suddenly the entire sample code was gone. I had worked on this for a few days. Oy!! PaNIC!! PANIC!!!
Here's a snapshot of the fiddle that exists and doesn't exist[^].
You can see that JSFiddle is generating a snapshot of my original code (on the right).
But, how can I see the code, but it isn't there!?! PanIC! p-p-p-PANIC!!!!!
However, if you click the jsfiddle then the system attempts to load the editor and everything is blank. Here's the link to the fiddle[^] -- which is blank.
!!!!
If you compare the link to the image you can even see that it is referencing the 72gzs94v ID that is supposed to be the code.
The code exists and it doesn't...
Got Very Lucky
I was able to inspect the code from the original snapshot and copy out the code using FireFox web tools so I didn't lose code that I had worked on for quite some time.
I no longer trust jsfiddle (and yes, I was a fool for trusting it in the first place.)
Public Service Announcement
Trust no one! Always save backups!!
I now have a backup of the code on my local machine. Phew...
|
|
|
|
|
You're missing the version suffix on the path. As far as I can see, the last version you saved was #74:
Edit fiddle - JSFiddle - Code Playground[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
So fantastic!!
that's one of the reason I post these crazy things to CP...because there are so many smart and helpful people here.
Absolutely amazing you noticed that!!!
I wonder why that it wouldn't load that from my JSFiddle.net account??
Thanks so much for reading my post and for your help.
I really appreciate it.
EDIT
And I should say this too. I logged into my account from another web browser and it still failed.
Then I logged in on another machine and it failed too.
Must be a crazy bug in the JSfiddle account plugin.
|
|
|
|
|
|
One of the great mysteries of the web:
Once you put something on it, it exists forever... somewhere.
Until of course you need it again, and then it no longer exists anywhere.
Both of these statements are true simultaneously, of course.
Software Zen: delete this;
|
|
|
|
|
It's like the old monkeys on typewriters story. Every document, image, etc is out there somewhere. It just hasn't been indexed yet.
Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
|
|
|
|
|
Gary R. Wheeler wrote: Once you put something on it, it exists forever... somewhere.
Until some suit decides to delete it thinking that will boost their site's SERPs:
CNET Deletes Thousands of Old Articles to Game Google Search[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
JS fiddle is awesome. I use it on the regular, but if you're tinkering with server-side or isomorphic JS it's much, much safer to just run it via node directly on your machine. Even for really simple stuff, its command line interpreter will handle things perfectly. Just as long as you don't need a DOM or styles for your quick and dirty testing.
Jeremy Falcon
modified 27-Sep-23 9:20am.
|
|
|
|
|
Attempting to set up User Isolation on a IIS FTP on Server2022 so I can test a FTP Client I wrote.
I was expecting it to create a new user directory under FTPRoot when I logged in.
No dice.
Found some documentation.
FTP User Isolation <userIsolation> | Microsoft Learn[^]
Then I found this chart. It actually uses SPECIFIC path that must exist or you get the error:
530 User cannot log in, home directory inaccessible.
Login failed.
ftp>
User Account Types Home Directory Syntax
Anonymous users %FtpRoot%\LocalUser\Public
Local Windows user accounts (Requires Basic authentication) %FtpRoot%\LocalUser%UserName%
Windows domain accounts (Requires Basic authentication) %FtpRoot%%UserDomain%%UserName%
IIS Manager or ASP.NET custom authentication user accounts %FtpRoot%\LocalUser%UserName%
See a snapshot of this chart[^].
The 3rd one was the one I needed. It is strictly incorrect.
If you were to expand those environment vars as they are you'd get: MyFtpRootCompanyDomainMyUserName
It is supposed to have directory separators between them.
Like this ==> MyFtpRoot\CompanyDomain\MyUserName
Filed under weird (and annoying / bad documentation).
|
|
|
|
|
I thought FTP died. Wasn't there a memorial service for it in the mid aughts?
*hides*
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
|
|
|
|
|
Forgive me for what I'm about to paste. The whole grotty mess is in the convert<>() function at the bottom of this horrible file: gfx/include/gfx_pixel.hpp[^]
I've omitted several pages of code.
The worst/best part of this is it's all done at compile time, and generates at most several lines of asm, but often a lot less, and in cases where the input values are known at compile time the entire computation is done at compile time and generates exactly no binary code.
Despite that, it is as if it was written at gunpoint.
I could break it up into a ton of nasty routines but that just feels like spreading the mess around.
I'm ready for the flaming.
template<typename PixelTypeLhs, typename PixelTypeRhs>
constexpr static inline gfx_result convert(PixelTypeLhs source,PixelTypeRhs* result,const PixelTypeRhs* background=nullptr) {
static_assert(helpers::is_same<PixelTypeLhs,PixelTypeRhs>::value || !PixelTypeLhs::template has_channel_names<channel_name::index>::value,"left hand pixel must not be indexed");
static_assert(helpers::is_same<PixelTypeLhs,PixelTypeRhs>::value || !PixelTypeRhs::template has_channel_names<channel_name::index>::value,"right hand pixel must not be indexed");
if(nullptr==result) return gfx_result::invalid_argument;
if(helpers::is_same<PixelTypeLhs,PixelTypeRhs>::value) {
if(nullptr==background) {
result->native_value=source.native_value;
return gfx_result::success;
} else {
return gfx_result::invalid_format;
}
}
bool good = false;
PixelTypeRhs tmp;
typename PixelTypeRhs::int_type native_value = tmp.native_value;
using is_rgb = typename PixelTypeLhs::template has_channel_names<channel_name::R,channel_name::G,channel_name::B>;
using is_yuv = typename PixelTypeLhs::template has_channel_names<channel_name::Y,channel_name::U,channel_name::V>;
using is_ycbcr = typename PixelTypeLhs::template has_channel_names<channel_name::Y,channel_name::Cb,channel_name::Cr>;
using is_hsv = typename PixelTypeLhs::template has_channel_names<channel_name::H,channel_name::S,channel_name::V>;
using is_hsl = typename PixelTypeLhs::template has_channel_names<channel_name::H,channel_name::S,channel_name::L>;
using is_cmyk = typename PixelTypeLhs::template has_channel_names<channel_name::C,channel_name::M,channel_name::Y,channel_name::K>;
using trhas_alpha = typename PixelTypeRhs::template has_channel_names<channel_name::A>;
using thas_alpha = typename PixelTypeLhs::template has_channel_names<channel_name::A>;
const bool has_alpha = thas_alpha::value;
const bool is_bw_candidate = 1==PixelTypeLhs::channels || (2==PixelTypeLhs::channels && has_alpha);
using tis_bw_candidate = typename PixelTypeLhs::template has_channel_names<channel_name::L>;
const bool is_bw_candidate2 = tis_bw_candidate::value;
const bool rhas_alpha = trhas_alpha::value;
const bool ris_bw_candidate = 1==PixelTypeRhs::channels || (2==PixelTypeRhs::channels && rhas_alpha);
using tris_bw_candidate = typename PixelTypeRhs::template has_channel_names<channel_name::L>;
const bool ris_bw_candidate2 = tris_bw_candidate::value;
using is_rhs_rgb = typename PixelTypeRhs::template has_channel_names<channel_name::R,channel_name::G,channel_name::B>;
using is_rhs_yuv = typename PixelTypeRhs::template has_channel_names<channel_name::Y,channel_name::U,channel_name::V>;
using is_rhs_ycbcr = typename PixelTypeRhs::template has_channel_names<channel_name::Y,channel_name::Cb,channel_name::Cr>;
using is_rhs_hsv = typename PixelTypeRhs::template has_channel_names<channel_name::H,channel_name::S,channel_name::V>;
using is_rhs_hsl = typename PixelTypeRhs::template has_channel_names<channel_name::H,channel_name::S,channel_name::L>;
using is_rhs_cmyk = typename PixelTypeRhs::template has_channel_names<channel_name::C,channel_name::M,channel_name::Y,channel_name::K>;
if(is_rgb::value && PixelTypeLhs::channels<5) {
using tindexR = typename PixelTypeLhs::template channel_index_by_name<channel_name::R>;
using tchR = typename PixelTypeLhs::template channel_by_index_unchecked<tindexR::value>;
const int chiR = tindexR::value;
using tindexG = typename PixelTypeLhs::template channel_index_by_name<channel_name::G>;
using tchG = typename PixelTypeLhs::template channel_by_index_unchecked<tindexG::value>;
const int chiG = tindexG::value;
using tindexB = typename PixelTypeLhs::template channel_index_by_name<channel_name::B>;
using tchB = typename PixelTypeLhs::template channel_by_index_unchecked<tindexB::value>;
const int chiB = tindexB::value;
if(is_rhs_rgb::value && PixelTypeRhs::channels<5) {
using trindexR = typename PixelTypeRhs::template channel_index_by_name<channel_name::R>;
using trchR = typename PixelTypeRhs::template channel_by_index_unchecked<trindexR::value>;
using trindexG = typename PixelTypeRhs::template channel_index_by_name<channel_name::G>;
using trchG = typename PixelTypeRhs::template channel_by_index_unchecked<trindexG::value>;
using trindexB = typename PixelTypeRhs::template channel_index_by_name<channel_name::B>;
using trchB = typename PixelTypeRhs::template channel_by_index_unchecked<trindexB::value>;
auto chR = source.template channel_unchecked<chiR>();
auto cR = helpers::convert_channel_depth<tchR,trchR>(chR);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexR::value>(native_value,cR);
auto chG = source.template channel_unchecked<chiG>();
auto cG = helpers::convert_channel_depth<tchG,trchG>(chG);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexG::value>(native_value,cG);
auto chB = source.template channel_unchecked<chiB>();
auto cB = helpers::convert_channel_depth<tchB,trchB>(chB);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexB::value>(native_value,cB);
good = true;
} else if(is_rhs_yuv::value && PixelTypeRhs::channels<5) {
using trindexY = typename PixelTypeRhs::template channel_index_by_name<channel_name::Y>;
using trchY = typename PixelTypeRhs::template channel_by_index_unchecked<trindexY::value>;
using trindexU = typename PixelTypeRhs::template channel_index_by_name<channel_name::U>;
using trchU = typename PixelTypeRhs::template channel_by_index_unchecked<trindexU::value>;
using trindexV = typename PixelTypeRhs::template channel_index_by_name<channel_name::V>;
using trchV = typename PixelTypeRhs::template channel_by_index_unchecked<trindexV::value>;
const auto cR = (source.template channel_unchecked<chiR>()*tchR::scaler)*255.0;
const auto cG = (source.template channel_unchecked<chiG>()*tchG::scaler)*255.0;
const auto cB = (source.template channel_unchecked<chiB>()*tchB::scaler)*255.0;
const auto chY = (0.257 * cR + 0.504 * cG + 0.098 * cB + 16)/255.0;
const auto chU = (-0.148 * cR - 0.291 * cG + 0.439 * cB + 128)/255.0;
const auto chV = (0.439 * cR - 0.368 * cG - 0.071 * cB + 128)/255.0;
const typename trchY::int_type cY =chY*trchY::scale+.5;
const typename trchU::int_type cU = chU*trchU::scale+.5;
const typename trchV::int_type cV = chV*trchV::scale+.5;
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexY::value>(native_value,cY);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexU::value>(native_value,cU);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexV::value>(native_value,cV);
good = true;
} else if(is_rhs_ycbcr::value && PixelTypeRhs::channels<5) {
using trindexY = typename PixelTypeRhs::template channel_index_by_name<channel_name::Y>;
using trchY = typename PixelTypeRhs::template channel_by_index_unchecked<trindexY::value>;
using trindexCb = typename PixelTypeRhs::template channel_index_by_name<channel_name::Cb>;
using trchCb = typename PixelTypeRhs::template channel_by_index_unchecked<trindexCb::value>;
using trindexCr = typename PixelTypeRhs::template channel_index_by_name<channel_name::Cr>;
using trchCr = typename PixelTypeRhs::template channel_by_index_unchecked<trindexCr::value>;
const auto cR = source.template channelr_unchecked<chiR>();
const auto cG = source.template channelr_unchecked<chiG>();
const auto cB = source.template channelr_unchecked<chiB>();
const double a = .299,
b=.587,
c=.114,
d=1.772,
e=1.402;
const double y = a * cR + b * cG + c * cB;
const double cb = (cB - y) / d+.5;
const double cr = (cR - y) / e+.5;
const typename trchY::int_type cY =helpers::clamp(typename trchY::int_type(y*trchY::scale+.5),trchY::min,trchY::max);
const typename trchCb::int_type cCb = helpers::clamp(typename trchCb::int_type((cb*trchCb::scale+.5)),trchCb::min,trchCb::max);
const typename trchCr::int_type cCr = helpers::clamp(typename trchCr::int_type((cr*trchCr::scale+.5)),trchCr::min,trchCr::max);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexY::value>(native_value,cY);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexCb::value>(native_value,cCb);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexCr::value>(native_value,cCr);
good = true;
} else if(is_rhs_hsv::value && PixelTypeRhs::channels<5) {
using trindexH = typename PixelTypeRhs::template channel_index_by_name<channel_name::H>;
using trchH = typename PixelTypeRhs::template channel_by_index_unchecked<trindexH::value>;
using trindexS = typename PixelTypeRhs::template channel_index_by_name<channel_name::S>;
using trchS = typename PixelTypeRhs::template channel_by_index_unchecked<trindexS::value>;
using trindexV = typename PixelTypeRhs::template channel_index_by_name<channel_name::V>;
using trchV = typename PixelTypeRhs::template channel_by_index_unchecked<trindexV::value>;
const double cR = source.template channelr_unchecked<chiR>();
const double cG = source.template channelr_unchecked<chiG>();
const double cB = source.template channelr_unchecked<chiB>();
double cmin = cG<cB?cG:cB;
cmin = cR<cmin?cR:cmin;
double cmax = cG>cB?cG:cB;
cmax = cR>cmax?cR:cmax;
double chroma = cmax-cmin;
double v = cmax;
double s = cmax == 0 ? 0 : chroma / cmax;
double h = 0; if(cmax != cmin){
if(cmax==cR) {
h=(cG-cB)/chroma+(cG<cB?6:0);
} else if(cmax==cG) {
h = (cG - cR) / chroma + 2;
} else { h = (cR - cG) / chroma + 4;
}
h /= 6.0;
}
const typename trchH::int_type cH =helpers::clamp(typename trchH::int_type(h*trchH::scale+.5),trchH::min,trchH::max);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexH::value>(native_value,cH);
const typename trchS::int_type cS =helpers::clamp(typename trchS::int_type(s*trchS::scale+.5),trchS::min,trchS::max);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexS::value>(native_value,cS);
const typename trchV::int_type cV =helpers::clamp(typename trchV::int_type(v*trchV::scale+.5),trchV::min,trchV::max);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexV::value>(native_value,cV);
good = true;
} else if(is_rhs_hsl::value && PixelTypeRhs::channels<5) {
using trindexH = typename PixelTypeRhs::template channel_index_by_name<channel_name::H>;
using trchH = typename PixelTypeRhs::template channel_by_index_unchecked<trindexH::value>;
using trindexS = typename PixelTypeRhs::template channel_index_by_name<channel_name::S>;
using trchS = typename PixelTypeRhs::template channel_by_index_unchecked<trindexS::value>;
using trindexL = typename PixelTypeRhs::template channel_index_by_name<channel_name::L>;
using trchL = typename PixelTypeRhs::template channel_by_index_unchecked<trindexL::value>;
const double cR = source.template channelr_unchecked<chiR>();
const double cG = source.template channelr_unchecked<chiG>();
const double cB = source.template channelr_unchecked<chiB>();
double cmin = cG<cB?cG:cB;
cmin = cR<cmin?cR:cmin;
double cmax = cG>cB?cG:cB;
cmax = cR>cmax?cR:cmax;
double h =0, s=0, l = (cmax + cmin) / 2.0;
if(cmax != cmin){
double chroma = cmax - cmin;
s = l > 0.5 ? chroma / (2.0 - cmax - cmin) : chroma / (cmax + cmin);
if(cmax==cR) {
h = (cG - cB) / chroma + (cG < cB ? 6 : 0);
} else if(cmax==cG) {
h = (cB - cG) / chroma + 2.0;
} else { h = (cR - cG) / chroma + 4.0;
}
h /= 6.0;
}
const typename trchH::int_type cH =helpers::clamp(typename trchH::int_type(h*trchH::scale+.5),trchH::min,trchH::max);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexH::value>(native_value,cH);
const typename trchS::int_type cS =helpers::clamp(typename trchS::int_type(s*trchS::scale+.5),trchS::min,trchS::max);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexS::value>(native_value,cS);
const typename trchL::int_type cL =helpers::clamp(typename trchL::int_type(l*trchL::scale+.5),trchL::min,trchL::max);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexL::value>(native_value,cL);
good = true;
} else if(is_rhs_cmyk::value && PixelTypeRhs::channels<6) {
using trindexC = typename PixelTypeRhs::template channel_index_by_name<channel_name::C>;
using trchC = typename PixelTypeRhs::template channel_by_index_unchecked<trindexC::value>;
using trindexM = typename PixelTypeRhs::template channel_index_by_name<channel_name::M>;
using trchM = typename PixelTypeRhs::template channel_by_index_unchecked<trindexM::value>;
using trindexY = typename PixelTypeRhs::template channel_index_by_name<channel_name::Y>;
using trchY = typename PixelTypeRhs::template channel_by_index_unchecked<trindexY::value>;
using trindexK = typename PixelTypeRhs::template channel_index_by_name<channel_name::K>;
using trchK = typename PixelTypeRhs::template channel_by_index_unchecked<trindexK::value>;
const double cR = source.template channelr_unchecked<chiR>();
const double cG = source.template channelr_unchecked<chiG>();
const double cB = source.template channelr_unchecked<chiB>();
double cmax = cR>cG?cR:cG;
cmax = cmax>cB?cmax:cB;
double k = helpers::clampcymk(1 - cmax);
double c = helpers::clampcymk((1 - cR - k) / (1 - k));
double m = helpers::clampcymk((1 - cG - k) / (1 - k));
double y = helpers::clampcymk((1 - cB - k) / (1 - k));
const typename trchC::int_type cC =helpers::clamp(typename trchC::int_type(c*trchC::scale+.5),trchC::min,trchC::max);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexC::value>(native_value,cC);
const typename trchM::int_type cM =helpers::clamp(typename trchM::int_type(m*trchM::scale+.5),trchM::min,trchM::max);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexM::value>(native_value,cM);
const typename trchY::int_type cY =helpers::clamp(typename trchY::int_type(y*trchY::scale+.5),trchY::min,trchY::max);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexY::value>(native_value,cY);
const typename trchK::int_type cK =helpers::clamp(typename trchK::int_type(k*trchK::scale+.5),trchK::min,trchK::max);
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexK::value>(native_value,cK);
good = true;
}
if(ris_bw_candidate && ris_bw_candidate2) {
using trindexL = typename PixelTypeRhs::template channel_index_by_name<channel_name::L>;
using trchL = typename PixelTypeRhs::template channel_by_index_unchecked<trindexL::value>;
auto cR = source.template channel_unchecked<chiR>();
auto cG = source.template channel_unchecked<chiG>();
auto cB = source.template channel_unchecked<chiB>();
double f = (cR*tchR::scaler*.299) +
(cG*tchG::scaler*.587) +
(cB*tchB::scaler*.114);
const size_t scale = trchL::scale;
f=(f*(double)scale)+.5;
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexL::value>(native_value,f);
good = true;
} } else if(is_bw_candidate && is_bw_candidate2) {
using tindexL = typename PixelTypeLhs::template channel_index_by_name<channel_name::L>;
using tchL = typename PixelTypeLhs::template channel_by_index_unchecked<tindexL::value>;
const int chiL = tindexL::value;
if(ris_bw_candidate && ris_bw_candidate2) {
using trindexL = typename PixelTypeRhs::template channel_index_by_name<channel_name::L>;
using trchL = typename PixelTypeRhs::template channel_by_index_unchecked<trindexL::value>;
typename trchL::int_type chL = helpers::convert_channel_depth<tchL,trchL>(source.template channel_unchecked<chiL>());
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexL::value>(native_value,chL);
good = true;
} else if(is_rhs_rgb::value && PixelTypeRhs::channels<5) {
using trindexR = typename PixelTypeRhs::template channel_index_by_name<channel_name::R>;
using trchR = typename PixelTypeRhs::template channel_by_index_unchecked<trindexR::value>;
using trindexG = typename PixelTypeRhs::template channel_index_by_name<channel_name::G>;
using trchG = typename PixelTypeRhs::template channel_by_index_unchecked<trindexG::value>;
using trindexB = typename PixelTypeRhs::template channel_index_by_name<channel_name::B>;
using trchB = typename PixelTypeRhs::template channel_by_index_unchecked<trindexB::value>;
const auto chL = source.template channel_unchecked<chiL>();
... (snip several pages of code)
} else {
if(rhas_alpha) {
using trindexA = typename PixelTypeRhs::template channel_index_by_name<channel_name::A>;
using trchA = typename PixelTypeRhs::template channel_by_index_unchecked<trindexA::value>;
helpers::set_channel_direct_unchecked<PixelTypeRhs,trindexA::value>(native_value,trchA::default_);
}
}
result->native_value = native_value;
return gfx_result::success;
} else {
rgba_pixel<HTCW_MAX_WORD> tmp1;
PixelTypeRhs tmp2;
gfx_result rr = convert(source,&tmp1);
if(gfx_result::success!=rr) {
return rr;
}
rr = convert(tmp1,&tmp2,background);
if(gfx_result::success!=rr) {
return rr;
}
*result=tmp2;
return gfx_result::success;
}
return gfx_result::not_supported;
}
Check out my IoT graphics library here:
https://honeythecodewitch/gfx
|
|
|
|
|
Mind you, I'm not going to talk about the lack of comments. I also freely admit that templates make me uncomfortable, but how in the hell would you debug/test that? If all of that generates a few lines of assembly...
Charlie Gilley
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
Has never been more appropriate.
|
|
|
|
|
By running it through all the supported color models which would require crafting pixels of each different type implicit color models like RGB, Y'CbCr, C'MYk, HSV, grayscale/monochrome etc, and converting them back and forth to other models.
The issue is that it's sometimes a lossy conversion so any test would have to account for that.
I do not have unit tests for this function, but I've used it enough that I am confident in it.
I did run several iterations of its use through godbolt.org to make sure it was producing the ASM i was expecting.
Edit: To my mind the comments aren't all that lacking, at least in context. That functions structure is very simple, and most of the variable names are descriptive if abbreviated.
I can look at it, with the comments that are there and tell
A) exactly what it's doing
and
B) where to add things to get it to do more
Any more than that, and it would create a comment maintenance issue, wherein i'm expressing intent twice, once through comments, and once through code, and creating double the maintenance, and the potential for comments to get out of sync.
The issue is that my metadata functions and helpers aren't documented as much as they need to be
Check out my IoT graphics library here:
https://honeythecodewitch/gfx
|
|
|
|
|
honey the codewitch wrote: I do not have unit tests for this function, but I've used it enough that I am confident in it. I distrust any app in the hospital. If it works, ship it, right?
And then you see a VB6 app starting at the beginning of the colonoscopy. I am pretty sure at that point that the person who wrote it has said that it has been used enough for his or her confidence.
honey the codewitch wrote: The issue is that my metadata functions and helpers aren't documented as much as they need to be Why not?
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Eddy Vluggen wrote: I distrust any app in the hospital. If it works, ship it, right?
This isn't a medical application.
Eddy Vluggen wrote: The issue is that my metadata functions and helpers aren't documented as much as they need to be
Because I am human, mortal, and have finite amounts of time and energy.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
honey the codewitch wrote: Because I am human, mortal, and have finite amounts of time and energy.
What kind of excuse is that?
Seriously, I would mostly prefer to have clear, maintainable code than a tour de force like you wrote, even at the cost of performance. The only exceptions are when the function is the one preventing the program from meeting some performance bar.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
My code is quite extensively documented, just not all the dark corners that only I end up needing anyway. Pixel metadata is one of those things.
People don't really need to know how many bits exist to the left of an arbitrary pixel channel, and if they really do they can look at the comments in the source code.
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|
|
|
|
|
honey the codewitch wrote: Because I am human, mortal, and have finite amounts of time and energy. You, mortal?
Erlkönig: programmer-and-the-devil.shtml[^]
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
It works and has a sole responsibility. If it was to be refactored, you could use chain of responsibility to break it up.
Graeme
"I fear not the man who has practiced ten thousand kicks one time, but I fear the man that has practiced one kick ten thousand times!" - Bruce Lee
|
|
|
|
|