Welcome, Guest.
Username: Password: Remember me

TOPIC: xy Primaries Adjuster

xy Primaries Adjuster 1 month 4 days ago #1

After doing my white point shader I knew that the primaries defined the colour space too, but I hadn't got around to doing anything with them, until I made this shader. So, this one lets you change the primaries.


https://en.wikipedia.org/wiki/RGB_color_space

Just to demo, you could change the Red in RGB to an orange.

#include "ReShadeUI.fxh"

uniform float2 Red < __UNIFORM_DRAG_FLOAT2
	ui_min = 0.0; ui_step=0.000001; ui_max = 1.0;
> =float2(0.64,0.33);

uniform float2 Green < __UNIFORM_DRAG_FLOAT2
	ui_min = 0.0; ui_step=0.000001; ui_max = 1.0;
> =float2(0.3,0.6);

uniform float2 Blue < __UNIFORM_DRAG_FLOAT2
	ui_min = 0.0; ui_step=0.000001; ui_max = 1.0;
> =float2(0.15,0.06);

uniform bool Two_dimensional_input <> = false;

uniform int Two_dimensional_input_primary <__UNIFORM_COMBO_INT1
    ui_items = "Red\0Green\0Blue\0";
	> = 0;

uniform int Two_dimensional_input_type <__UNIFORM_COMBO_INT1
    ui_items = "Crosshairs on\0Crosshairs off\0Direct point-based\0";
	> = 0;

uniform float Two_dimensional_input_Range < __UNIFORM_SLIDER_FLOAT1
	ui_min = 2; ui_max = 0.0;
> = 1.89;

uniform bool Debug <> = false;

uniform int Debug_type <__UNIFORM_COMBO_INT1
    ui_items = "Distance from pure primary\0Colour bars\0";
	> = 0;

uniform float Debug_amplification < __UNIFORM_DRAG_FLOAT1
	ui_min = 0.0000001; ui_max =2;
	ui_tooltip = "A lower value exaggerates small differences more";
> = 0.5;
uniform bool Split <> = false;

uniform bool Flip_split <> = false;

uniform float Split_position < __UNIFORM_SLIDER_FLOAT1
	ui_min = 0; ui_max =1;
	ui_tooltip = "0 is on the far left, 1 on the far right.";
> = 0.5;

#include "ReShade.fxh"
#include "DrawText_mod.fxh"

uniform bool buttondown < source = "mousebutton"; keycode = 0; mode = ""; >;

uniform float2 mousepoint < source = "mousepoint"; >;

float3x3 invThreeByThreeMatrix(float3x3 mtx){

float el_A=mtx[1][1]*mtx[2][2]-mtx[1][2]*mtx[2][1];
float el_B=-(mtx[1][0]*mtx[2][2]-mtx[1][2]*mtx[2][0]);
float el_C=mtx[1][0]*mtx[2][1]-mtx[1][1]*mtx[2][0];
float el_D=-(mtx[0][1]*mtx[2][2]-mtx[0][2]*mtx[2][1]);
float el_E=mtx[0][0]*mtx[2][2]-mtx[0][2]*mtx[2][0];
float el_F=-(mtx[0][0]*mtx[2][1]-mtx[0][1]*mtx[2][0]);
float el_G=mtx[0][1]*mtx[1][2]-mtx[0][2]*mtx[1][1];
float el_H=-(mtx[0][0]*mtx[1][2]-mtx[0][2]*mtx[1][0]);
float el_I=mtx[0][0]*mtx[1][1]-mtx[0][1]*mtx[1][0];

float det=mtx[0][0]*el_A+mtx[0][1]*el_B+mtx[0][2]*el_C;

float invDet=1/det;

float3x3 outp=invDet*float3x3(el_A,el_D,el_G,
el_B,el_E,el_H,
el_C,el_F,el_I);

    return outp;
}

float3 Primaryconv(float2 red, float2 green, float2 blue, float3 XYZ){

float3 XYZ_r=float3(red.xy,1-red.x-red.y);
float3 XYZ_g=float3(green.xy,1-green.x-green.y);
float3 XYZ_b=float3(blue.xy,1-blue.x-blue.y);

float3x3 XYX_rgb=float3x3(XYZ_r.x,XYZ_g.x,XYZ_b.x,
XYZ_r.y,XYZ_g.y,XYZ_b.y,
XYZ_r.z,XYZ_g.z,XYZ_b.z);

float3x3 inv_XYZ_rgb=invThreeByThreeMatrix(XYX_rgb);

float3 s_XYZ=mul(inv_XYZ_rgb,float3(0.95047,1,1.08883));

float3x3 s_mat=float3x3(s_XYZ.x,0,0,
0,s_XYZ.y,0,
0,0,s_XYZ.z);

float3x3 inv_s_mat=invThreeByThreeMatrix(mul(XYX_rgb,s_mat));

float3 rgb=mul(inv_s_mat,XYZ);
rgb=( rgb > 0.00313066844250063 )?1.055 * pow(abs(rgb),1/2.4) - 0.055:12.92 *rgb;
return rgb;

}
//Source: http://www.ryanjuckett.com/programming/rgb-color-space-conversion/


float3 rgb2xyY(float3 rgb){

    float3 rgbNew=float3(rgb.r,rgb.g,rgb.b); 

	float3 XYZ;

	rgbNew=(rgbNew > 0.0404482362771082)?pow(abs((rgbNew+0.055)/1.055),2.4):rgbNew/12.92;

		XYZ.x = dot(float3(0.4124564,0.3575761, 0.1804375), rgbNew);
		XYZ.y = dot(float3(0.2126729,0.7151522,0.072175), rgbNew);
		XYZ.z = dot(float3(0.0193339,0.119192,0.9503041), rgbNew);

	float XYZtot=XYZ.x+XYZ.y+XYZ.z;
	
	float x=XYZ.x/XYZtot;
	float y=XYZ.y/XYZtot;
	
	return float3(x,y,XYZ.y);

}

//Source: https://stackoverflow.com/a/45263428; http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html


float3 xyY2XYZ(float3 xyY){
	float X=(xyY.z/xyY.y)*xyY.x;
	float Z=(xyY.z/xyY.y)*(1-xyY.x-xyY.y);
	
	return float3(X,xyY.z,Z);
}

float3 XYZ2xyY(float3 XYZ){
	float XYZtot=XYZ.x+XYZ.y+XYZ.z;
	
	float x=XYZ.x/XYZtot;
	float y=XYZ.y/XYZtot;
	return float3(x,y,XYZ.y);
}

float3 XYZ2xyY_Grey(float3 XYZ){
	float XYZtot=XYZ.x+XYZ.y+XYZ.z;
	
	float x=XYZ.x/XYZtot;
	float y=XYZ.y/XYZtot;
	return float3(x,y,XYZ.y);
}


float3 xyY2rgb(float3 xyY){

float Y=xyY.z;
float X=(Y/xyY.y)*xyY.x;
float Z=(Y/xyY.y)*(1-xyY.x-xyY.y);

float3 RGB;

 RGB.r = dot(float3(3.2404542,-1.5371385,-0.4985314),float3(X,Y,Z));
 RGB.g = dot(float3(-0.969266,1.8760108,0.041556),float3(X,Y,Z));
 RGB.b = dot(float3(0.0556434,-0.2040259,1.0572252),float3(X,Y,Z));

	RGB=( RGB > 0.00313066844250063 )?1.055 * pow(abs(RGB),1/2.4) - 0.055:12.92 *RGB;

return RGB;

}
//Source: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html


float3 xy2XYZ(float2 xyCoord){

return float3((1/xyCoord.y)*xyCoord.x,1,(1/xyCoord.y)*(1-xyCoord.x-xyCoord.y));
}



float4 PrimariesChangePass2D(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{

float4 c0 = tex2D(ReShade::BackBuffer, texcoord);

float2 Customxy;

float2 Red=Red;
float2 Green=Green;
float2 Blue=Blue;

[flatten]if(Two_dimensional_input_primary==0){
Customxy=Red;
}else if(Two_dimensional_input_primary==1){
Customxy=Green;
}else if(Two_dimensional_input_primary==2){
Customxy=Blue;
}

float x_Range=(BUFFER_WIDTH>=BUFFER_HEIGHT)?Two_dimensional_input_Range*(BUFFER_RCP_HEIGHT/BUFFER_RCP_WIDTH):Two_dimensional_input_Range;

float y_Range=(BUFFER_WIDTH>=BUFFER_HEIGHT)?Two_dimensional_input_Range:Two_dimensional_input_Range*(BUFFER_RCP_WIDTH/BUFFER_RCP_HEIGHT);

Customxy.x= ((Two_dimensional_input==1 && Debug_type==1 && buttondown==1)||(buttondown==0 && Two_dimensional_input==1))?  mousepoint.x*ReShade::PixelSize.x*((Customxy.x+0.5*x_Range)-(Customxy.x-0.5*x_Range))+(Customxy.x-0.5*x_Range):Customxy.x;

float xCoord_Pos=((Two_dimensional_input==1 && Debug_type==1 && buttondown==1)||(buttondown==1 && Two_dimensional_input==1))?(Customxy.x-(Customxy.x-0.5*x_Range))/((Customxy.x+0.5*x_Range)-(Customxy.x-0.5*x_Range)):mousepoint.x*ReShade::PixelSize.x;

Customxy.y= ((Two_dimensional_input==1 && Debug_type==1 && buttondown==1)||(buttondown==0 && Two_dimensional_input==1))?mousepoint.y*ReShade::PixelSize.y*((Customxy.y+0.5*y_Range)-(Customxy.y-0.5*y_Range))+(Customxy.y-0.5*y_Range):Customxy.y;

float yCoord_Pos=(buttondown==1 && Two_dimensional_input==1)?(Customxy.y-(Customxy.y-0.5*y_Range))/((Customxy.y+0.5*y_Range)-(Customxy.y-0.5*y_Range)):mousepoint.y*ReShade::PixelSize.y;

float4 c1=c0;

Customxy=(Two_dimensional_input==1 && Two_dimensional_input_type==2)?rgb2xyY(tex2D(ReShade::BackBuffer, mousepoint*ReShade::PixelSize).rgb).xy:Customxy;

[flatten]if(Two_dimensional_input==1 && Two_dimensional_input_primary==0){
Red=Customxy;
}else if(Two_dimensional_input==1 && Two_dimensional_input_primary==1){
Green=Customxy;
}else if(Two_dimensional_input==1 && Two_dimensional_input_primary==2){
Blue=Customxy;
}

c1.rgb=Primaryconv(Red,Green,Blue,xyY2XYZ(rgb2xyY(c0.rgb)));

float3 dbgCol=float3(0,0,0);

[flatten]if(Debug==1){

dbgCol=(texcoord.x<=pow(3,-1))?float3(1,0,0):dbgCol;
dbgCol=(texcoord.x>pow(3,-1) && texcoord.x<=2*pow(3,-1))?float3(0,1,0):dbgCol;
dbgCol=(texcoord.x>2*pow(3,-1))?float3(0,0,1):dbgCol;

float2 OGxy=rgb2xyY(c0.rgb).xy;
float2 Currxy=rgb2xyY(c1.rgb).xy;

[flatten]if(Two_dimensional_input_primary==0){

[flatten]if(Debug_type==0){
c1.rgb=pow(min(1,sqrt(pow(0.64-Currxy.x,2)+pow(0.33-Currxy.y,2))),Debug_amplification);
c0.rgb=(Split==1)?pow(min(1,sqrt(pow(0.64-OGxy.x,2)+pow(0.33-OGxy.y,2))),Debug_amplification):c0.rgb;
}else{
c1.rgb=(buttondown==1)?c1.rgb:Primaryconv(Red,Green,Blue,xyY2XYZ(rgb2xyY(dbgCol)));
c0.rgb=c1.rgb;
}

}else if(Two_dimensional_input_primary==1){

[flatten]if(Debug_type==0){
c1.rgb=pow(min(1,sqrt(pow(0.3-Currxy.x,2)+pow(0.6-Currxy.y,2))),Debug_amplification);
c0.rgb=(Split==1)?pow(min(1,sqrt(pow(0.3-OGxy.x,2)+pow(0.6-OGxy.y,2))),Debug_amplification):c0.rgb;
}else{
c1.rgb=(buttondown==1)?c1.rgb:Primaryconv(Red,Green,Blue,xyY2XYZ(rgb2xyY(dbgCol)));
c0.rgb=c1.rgb;
}

}else if(Two_dimensional_input_primary==2){

[flatten]if(Debug_type==0){
c1.rgb=pow(min(1,sqrt(pow(0.15-Currxy.x,2)+pow(0.06-Currxy.y,2))),Debug_amplification);
c0.rgb=(Split==1)?pow(min(1,sqrt(pow(0.15-OGxy.x,2)+pow(0.06-OGxy.y,2))),Debug_amplification):c0.rgb;
}else{
c1.rgb=(buttondown==1)?c1.rgb:Primaryconv(Red,Green,Blue,xyY2XYZ(rgb2xyY(dbgCol)));
c0.rgb=c1.rgb;
}

}
}

float4 c2=(texcoord.x>=Split_position*Split)?c1:c0;
float4 c3=(texcoord.x<=Split_position*Split)?c1:c0;

float4 c4=(Flip_split==1 && Split==1)?c3:c2;

float divLine = abs(texcoord.x - Split_position) < BUFFER_RCP_WIDTH;
c4 =(Split==0 || (Debug==1 && Debug_type==1))?c4: c4*(1.0 - divLine); //invert divline

c4.rgb =(Two_dimensional_input==1 && Two_dimensional_input_type==0 && (abs(texcoord.x-xCoord_Pos)<BUFFER_RCP_WIDTH || abs(texcoord.y-yCoord_Pos)<BUFFER_RCP_HEIGHT))?float3(0.369,0.745,0):c4.rgb;

c4.rgb =((Two_dimensional_input==1 && Two_dimensional_input_type==1 && (abs(texcoord.x-xCoord_Pos)<3*BUFFER_RCP_WIDTH && abs(texcoord.y-yCoord_Pos)<3*BUFFER_RCP_HEIGHT))||(Two_dimensional_input==1 && buttondown==1 && Debug==1 && Debug_type==1)&& (abs(texcoord.x-mousepoint.x*ReShade::PixelSize.x)<3*BUFFER_RCP_WIDTH && abs(texcoord.y-mousepoint.y*ReShade::PixelSize.y)<3*BUFFER_RCP_HEIGHT) && Two_dimensional_input_type!=2)?float3(0.498,1,0):c4.rgb;

float4 res =float4(c4.rgb,0);

float textSize=25;

[flatten]if(Two_dimensional_input==1){
    DrawText_Digit(   DrawText_Shift(DrawText_Shift(float2(0.5*BUFFER_WIDTH,0), int2(-14, 0), textSize, 1), int2(8, 0), textSize, 1) , 
						textSize, 1, texcoord,  3, Customxy.x, res,0);
						
						    DrawText_Digit(   DrawText_Shift(DrawText_Shift(float2(0.5*BUFFER_WIDTH,0), int2(-5, 0), textSize, 1), int2(8, 0), textSize, 1) , 
						textSize, 1, texcoord,  3,  Customxy.y, res,0);
}

c4.rgb=res.rgb;

return c4;

}

technique xy_Primaries_2D
{
	pass
	{
		VertexShader = PostProcessVS;
		PixelShader = PrimariesChangePass2D;
	}
}

Requires a modded DrawText header file as well, for the new 2D input (call it "DrawText_mod.fxh"!):
//Original by kingeric1992, modded by crabshank 08/10/2019

#ifndef _DRAWTEXT_H_
#define _DRAWTEXT_H_

#define _DRAWTEXT_GRID_X 14.0
#define _DRAWTEXT_GRID_Y 7.0

///////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                   //
//  Available functions:                                                                             //
//      DrawText_String( offset, text size, xy ratio, input coord, string array, array size, output) //
//          float2 offset       = top left corner of string, screen hight pixel unit.                //
//          float  text size    = text size, screen hight pixel unit.                                //
//          float  xy ratio     = xy ratio of text.                                                  //
//          float2 input coord  = current texture coord.                                             //
//          int    string array = string data in float2 array format, ex: "Demo Text"                //
//              int String0[9] = { __D, __e, __m, __o, __Space, __T, __e, __x, __t};                 //
//          int    string size  = size of the string array.                                          //
//          float  output       = output.                                                            //
//                                                                                                   //
//      DrawText_Digit( offset, text size, xy ratio, input coord, precision after dot, data, output) //
//          float2 offset       = same as DrawText_String.                                           //
//          float  text size    = same as DrawText_String.                                           //
//          float  xy ratio     = same as DrawText_String.                                           //
//          float2 input coord  = same as DrawText_String.                                           //
//          int    precision    = digits after dot.                                                  //
//          float  data         = input float.                                                       //
//          float  output       = output.                                                            //
//                                                                                                   //
//      float2 DrawText_Shift(shift, text size, xy ratio)                                            //
//          float2 shift        = shift line(y) and column.                                          //
//          float text size     = same as DrawText_String.                                           //
//          float xy ratio      = same as DrawText_String.                                           //
//                                                                                                   //
///////////////////////////////////////////////////////////////////////////////////////////////////////


//Sample Usage

/*
float4 main_fragment( float4 position : POSITION,
                      float2 txcoord  : TEXCOORD) : COLOR {
    float res = 0.0;

    int line0[9]  = { __D, __e, __m, __o, __Space, __T, __e, __x, __t };   //Demo Text
    int line1[15] = { __b, __y, __Space, __k, __i, __n, __g, __e, __r, __i, __c, __1, __9, __9, __2 }; //by kingeric1992
    int line2[6]  = { __S, __i, __z, __e, __Colon, __Space }; // Size: %d.

    DrawText_String(float2(100.0 , 100.0), 32, 1, txcoord,  line0, 9, res);
    DrawText_String(float2(100.0 , 134.0), textSize, 1, txcoord,  line1, 15, res);
    DrawText_String(DrawText_Shift(float2(100.0 , 134.0), int2(0, 1), textSize, 1), 18, 1, txcoord,  line2, 6, res);
    DrawText_Digit(DrawText_Shift(DrawText_Shift(float2(100.0 , 134.0), int2(0, 1), textSize, 1), int2(8, 0), 18, 1),
                    18, 1, txcoord,  0, textSize, res);

    return res;
}

*/

//Text display
//Character indexing
#define __Space       0 //  (space)
#define __Exclam      1 //  !
#define __Quote       2 //  "
#define __Pound       3 //  #
#define __Dollar      4 //  $
#define __Percent     5 //  %
#define __And         6 //  &
#define __sQuote      7 //  '
#define __rBrac_O     8 //  (
#define __rBrac_C     9 //  )
#define __Asterisk   10 //  *
#define __Plus       11 //  +
#define __Comma      12 //  ,
#define __Minus      13 //  -

#define __Dot        14 //  .
#define __Slash      15 //  /
#define __0          16 //  0
#define __1          17 //  1
#define __2          18 //  2
#define __3          19 //  3
#define __4          20 //  4
#define __5          21 //  5
#define __6          22 //  6
#define __7          23 //  7
#define __8          24 //  8
#define __9          25 //  9
#define __Colon      26 //  :
#define __sColon     27 //  ;

#define __Less       28 //  <
#define __Equals     29 //  =
#define __Greater    30 //  >
#define __Question   31 //  ?
#define __at         32 //  @
#define __A          33 //  A
#define __B          34 //  B
#define __C          35 //  C
#define __D          36 //  D
#define __E          37 //  E
#define __F          38 //  F
#define __G          39 //  G
#define __H          40 //  H
#define __I          41 //  I

#define __J          42 //  J
#define __K          43 //  K
#define __L          44 //  L
#define __M          45 //  M
#define __N          46 //  N
#define __O          47 //  O
#define __P          48 //  P
#define __Q          49 //  Q
#define __R          50 //  R
#define __S          51 //  S
#define __T          52 //  T
#define __U          53 //  U
#define __V          54 //  V
#define __W          55 //  W

#define __X          56 //  X
#define __Y          57 //  Y
#define __Z          58 //  Z
#define __sBrac_O    59 //  [
#define __Backslash  60 //  \..
#define __sBrac_C    61 //  ]
#define __Caret      62 //  ^
#define __Underscore 63 //  _
#define __Punc       64 //  `
#define __a          65 //  a
#define __b          66 //  b
#define __c          67 //  c
#define __d          68 //  d
#define __e          69 //  e

#define __f          70 //  f
#define __g          71 //  g
#define __h          72 //  h
#define __i          73 //  i
#define __j          74 //  j
#define __k          75 //  k
#define __l          76 //  l
#define __m          77 //  m
#define __n          78 //  n
#define __o          79 //  o
#define __p          80 //  p
#define __q          81 //  q
#define __r          82 //  r
#define __s          83 //  s

#define __t          84 //  t
#define __u          85 //  u
#define __v          86 //  v
#define __w          87 //  w
#define __x          88 //  x
#define __y          89 //  y
#define __z          90 //  z
#define __cBrac_O    91 //  {
#define __vBar       92 //  |
#define __cBrac_C    93 //  }
#define __Tilde      94 //  ~
#define __tridot     95 // (...)
#define __empty0     96 // (null)
#define __empty1     97 // (null)
//Character indexing ends

texture Texttex < source = "FontAtlas.png"; > {
    Width  = 512;
    Height = 512;
};

sampler samplerText {
    Texture = Texttex;
};

//accomodate for undef array size.
#define DrawText_String(  pos, size, ratio, tex, array, arrSize, output ) \
    {   float  text = 0.0; \
        float2 uv = (tex * float2(BUFFER_WIDTH, BUFFER_HEIGHT) - pos) / size; \
        uv.y      = saturate(uv.y); \
        uv.x     *= ratio * 2.0; \
        float  id = array[int(trunc(uv.x))]; \
        if(uv.x  <= arrSize && uv.x >= 0.0) \
            text  = tex2D(samplerText, (frac(uv) + float2( id % 14.0, trunc(id / 14.0))) \
            / float2( _DRAWTEXT_GRID_X, _DRAWTEXT_GRID_Y) ).x; \
        output += text;  }

float2 DrawText_Shift( float2 pos, int2 shift, float size, float ratio ) {
    return pos + size * shift * float2(0.5, 1.0) / ratio;
}


	float mulTenIntPow(float number,float power){
float sign=(power>=0)?1:-1;
int pwr=uint(round(abs(power)));
[flatten]if(pwr>1){
for(int i=0; i<pwr;i++){
number=(sign==1)?number*10:number/10;
}
}else{
number=(sign==1)?number*10:number/10;
}

return number;
}

float rounder (float places,float number){
float sign=(number>=0)?1:-1;
int integer=int(round(mulTenIntPow(abs(number),places)));

return sign*(mulTenIntPow(float(round(integer)),-places));
}



void DrawText_Digit( float2 pos, float size, float ratio, float2 tex, int digit, float data, inout float4 res,float textGrey) {
    int digits[13] = {
        __0, __1, __2, __3, __4, __5, __6, __7, __8, __9, __Minus, __Space, __Dot
    };

    float2 uv = (tex * float2(BUFFER_WIDTH, BUFFER_HEIGHT) - pos) / size;
    uv.y      = saturate(uv.y);
    uv.x     *= ratio * 2.0;

data=rounder(digit,data);
    float  t  = abs(data);
    int numDigits = max(ceil(log2(t)/3.32192809),1);

    //early exit:
   if(uv.x <-numDigits-1 || uv.x > digit+1) return;

int index = 0;

[flatten]if(int(uv.x)==0){
index=round(trunc(frac(mulTenIntPow(t,-1))*10));
}else if(int(uv.x)<=-1){
index=round(trunc(frac(trunc(mulTenIntPow(t,uv.x))/10)*10));
}else if(int(uv.x)>=1){
index=round(frac(trunc(mulTenIntPow(t,int(uv.x)))/10)*10);
}

index=(int(uv.x)==0&&int(ceil(uv.x))==1)?12:index;

[flatten]if(int(uv.x)==-numDigits){
if(data>=0){
index=11;
}else{
index=10;
}
}

index=digits[int(index)];

    res  +=(textGrey*2-1)*tex2D(samplerText, (frac(uv) + float2( index % 14.0, trunc(index / 14.0))) /
               float2( _DRAWTEXT_GRID_X, _DRAWTEXT_GRID_Y)).x;
}

#endif

Video shader version here
Last Edit: 1 month 3 days ago by crabshank.
The administrator has disabled public write access.
The following user(s) said Thank You: jas01

xy Primaries Adjuster 1 month 4 days ago #2

All my shaders that use my modded DrawText header have been updated, so make sure to grab the new versions.
The administrator has disabled public write access.