Copy link to clipboard
Copied
I've created a event that will transform a layer by an amount of pixels:
error = sPSActionDescriptor->PutUnitFloat(desc, keyHeight, unitPixels, 100);
if (error) goto returnError;
Though, when applying the transform it seem the actual value (in my case the 100) the value seems to be applied exponentially. From what I can see around .35 units so that value of 100 turns into 103 for the width in PS.
Is this a issue with the Dom? or am I doing something wrong in this case? Full code:
error = sPSActionReference->PutEnumerated(ref0000000000000068, classLayer, typeOrdinal, enumTarget);
if (error) goto returnError;
error = sPSActionDescriptor->PutReference(desc0000000000000188, keyNull, ref0000000000000068);
if (error) goto returnError;
error = sPSActionDescriptor->PutEnumerated(desc0000000000000188, keyFreeTransformCenterState, typeQuadCenterState, enumQCSAverage);
if (error) goto returnError;
error = sPSActionDescriptor->PutObject(desc0000000000000188, keyOffset, classOffset, desc0000000000000190);
if (error) goto returnError;
error = sPSActionDescriptor->PutUnitFloat(desc0000000000000188, eventKeyID, unitPixels, value);
if (error) goto returnError;
error = sPSActionDescriptor->PutEnumerated(desc0000000000000188, keyInterfaceIconFrameDimmed, typeInterpolation, enumBicubic);
if (error) goto returnError;
Copy link to clipboard
Copied
What do you have in your keyOffset descriptor?
Copy link to clipboard
Copied
Full code of Action:
static SPErr EventLayerTransform(string selectedLayer, int eventKeyID, real64 value)
{
char* layerName = (char*)selectedLayer.c_str();
EventSelectLayer(layerName);
PIActionDescriptor result = NULL;
DescriptorTypeID runtimeKeyID;
DescriptorTypeID runtimeTypeID;
DescriptorTypeID runtimeObjID;
DescriptorTypeID runtimeEnumID;
DescriptorTypeID runtimeClassID;
DescriptorTypeID runtimePropID;
DescriptorTypeID runtimeUnitID;
SPErr error = kSPNoError;
PIActionDescriptor desc0000000000000188 = NULL;
PIActionReference ref0000000000000068 = NULL;
PIActionDescriptor desc0000000000000190 = NULL;
error = sPSActionDescriptor->Make(&desc0000000000000188);
if (error) goto returnError;
error = sPSActionReference->Make(&ref0000000000000068);
if (error) goto returnError;
error = sPSActionDescriptor->Make(&desc0000000000000190);
if (error) goto returnError;
error = sPSActionReference->PutEnumerated(ref0000000000000068, classLayer, typeOrdinal, enumTarget);
if (error) goto returnError;
error = sPSActionDescriptor->PutReference(desc0000000000000188, keyNull, ref0000000000000068);
if (error) goto returnError;
error = sPSActionDescriptor->PutEnumerated(desc0000000000000188, keyFreeTransformCenterState, typeQuadCenterState, enumQCSAverage);
if (error) goto returnError;
error = sPSActionDescriptor->PutUnitFloat(desc0000000000000188, keyHorizontal, unitDistance, 0.0);
if (error) goto returnError;
error = sPSActionDescriptor->PutUnitFloat(desc0000000000000188, keyVertical, unitDistance, 0.0);
if (error) goto returnError;
error = sPSActionDescriptor->PutObject(desc0000000000000188, keyOffset, classOffset, desc0000000000000190);
if (error) goto returnError;
error = sPSActionDescriptor->PutUnitFloat(desc0000000000000188, eventKeyID, unitPixels, value);
if (error) goto returnError;
error = sPSActionDescriptor->PutEnumerated(desc0000000000000188, keyInterfaceIconFrameDimmed, typeInterpolation, enumBicubic);
if (error) goto returnError;
error = sPSActionControl->Play(&result, eventTransform, desc0000000000000188, plugInDialogSilent);
if (error) goto returnError;
returnError:
if (result != NULL) sPSActionDescriptor->Free(result);
if (desc0000000000000188 != NULL) sPSActionDescriptor->Free(desc0000000000000188);
if (desc0000000000000190 != NULL) sPSActionDescriptor->Free(desc0000000000000190);
return error;
}
Copy link to clipboard
Copied
What is the original size and what is your target size?
Here are two JavaScript versions. One makes a 100x100 transform on a 103x103 layer. The other makes a 100x100 transform on a 102x102 layer. Note the offset is needed on the “odd” bounds change.
Also note that mine are using percentages to transform and not pixels.
I think the key is “Am I landing on ½ pixel. If so, I need to adjust accordingly.”
// 102x102 to 100x100 no offset needed as it is even
var idtransform = stringIDToTypeID( "transform" );
var desc532 = new ActionDescriptor();
var idnull = stringIDToTypeID( "null" );
var ref136 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
ref136.putEnumerated( idlayer, idordinal, idtargetEnum );
desc532.putReference( idnull, ref136 );
var idfreeTransformCenterState = stringIDToTypeID( "freeTransformCenterState" );
var idquadCenterState = stringIDToTypeID( "quadCenterState" );
var idQCSAverage = stringIDToTypeID( "QCSAverage" );
desc532.putEnumerated( idfreeTransformCenterState, idquadCenterState, idQCSAverage );
var idoffset = stringIDToTypeID( "offset" );
var desc533 = new ActionDescriptor();
var idhorizontal = stringIDToTypeID( "horizontal" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc533.putUnitDouble( idhorizontal, idpixelsUnit, 0.000000 );
var idvertical = stringIDToTypeID( "vertical" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc533.putUnitDouble( idvertical, idpixelsUnit, 0.000000 );
var idoffset = stringIDToTypeID( "offset" );
desc532.putObject( idoffset, idoffset, desc533 );
var idwidth = stringIDToTypeID( "width" );
var idpercentUnit = stringIDToTypeID( "percentUnit" );
desc532.putUnitDouble( idwidth, idpercentUnit, 98.039216 );
var idheight = stringIDToTypeID( "height" );
var idpercentUnit = stringIDToTypeID( "percentUnit" );
desc532.putUnitDouble( idheight, idpercentUnit, 98.039216 );
var idinterfaceIconFrameDimmed = stringIDToTypeID( "interfaceIconFrameDimmed" );
var idinterpolationType = stringIDToTypeID( "interpolationType" );
var idbicubic = stringIDToTypeID( "bicubic" );
desc532.putEnumerated( idinterfaceIconFrameDimmed, idinterpolationType, idbicubic );
executeAction( idtransform, desc532, DialogModes.NO );
// this will translate a 103x103 to 100x100
var idtransform = stringIDToTypeID( "transform" );
var desc506 = new ActionDescriptor();
var idnull = stringIDToTypeID( "null" );
var ref128 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
ref128.putEnumerated( idlayer, idordinal, idtargetEnum );
desc506.putReference( idnull, ref128 );
var idfreeTransformCenterState = stringIDToTypeID( "freeTransformCenterState" );
var idquadCenterState = stringIDToTypeID( "quadCenterState" );
var idQCSAverage = stringIDToTypeID( "QCSAverage" );
desc506.putEnumerated( idfreeTransformCenterState, idquadCenterState, idQCSAverage );
var idoffset = stringIDToTypeID( "offset" );
var desc507 = new ActionDescriptor();
var idhorizontal = stringIDToTypeID( "horizontal" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc507.putUnitDouble( idhorizontal, idpixelsUnit, 0.500000 );
var idvertical = stringIDToTypeID( "vertical" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
desc507.putUnitDouble( idvertical, idpixelsUnit, 0.500000 );
var idoffset = stringIDToTypeID( "offset" );
desc506.putObject( idoffset, idoffset, desc507 );
var idwidth = stringIDToTypeID( "width" );
var idpercentUnit = stringIDToTypeID( "percentUnit" );
desc506.putUnitDouble( idwidth, idpercentUnit, 97.087379 );
var idheight = stringIDToTypeID( "height" );
var idpercentUnit = stringIDToTypeID( "percentUnit" );
desc506.putUnitDouble( idheight, idpercentUnit, 97.087379 );
var idinterfaceIconFrameDimmed = stringIDToTypeID( "interfaceIconFrameDimmed" );
var idinterpolationType = stringIDToTypeID( "interpolationType" );
var idbicubic = stringIDToTypeID( "bicubic" );
desc506.putEnumerated( idinterfaceIconFrameDimmed, idinterpolationType, idbicubic );
executeAction( idtransform, desc506, DialogModes.NO );
Copy link to clipboard
Copied
All I'm trying to do is add 1 pixel to the layer transform bounds (If the layer is not even, so funny enough It should always be divisible by 2).
But since I need to add 1 pixel I don't want to have to do a bunch of logic to convert the percent to pixel.
If you can tell me any way how to do this with the C++ API then I'm fine, and I can move on and push this tool.
I'm using the action that was directly output from the Listener log plugin (Other than changing the units from Percent to Pixel) .
I'm going to just post the Email that I've sent to Adobe:
Before I show the steps I'd like to say I'm not 100% sure that this is a bug, since I'm following the example of a listener log, I don't have any other resources that show me how to transform the layer VRect(). If there is another way or the proper way to perform an action or change the layer descriptor that will allow me to add one pixel to the layer vrect please tell me, as that will solve my problem.
1. I'll create a layer and set the pixel size / layer size to 201x201 pixels
2. Then I'll add one pixel to the Dom width or Height in the document (I changed the 201 to 20 in this case for the listener log)
2.1 Then the listener plugin I have will output this code:
//Listener.log *****Output from the listener plugin
SPErr PlayeventTransform(/*your parameters go here*/void)
{
PIActionDescriptor result = NULL;
DescriptorTypeID runtimeKeyID;
DescriptorTypeID runtimeTypeID;
DescriptorTypeID runtimeObjID;
DescriptorTypeID runtimeEnumID;
DescriptorTypeID runtimeClassID;
DescriptorTypeID runtimePropID;
DescriptorTypeID runtimeUnitID;
SPErr error = kSPNoError;
// Move this to the top of the routine!
PIActionDescriptor desc0000000000000148 = NULL;
error = sPSActionDescriptor->Make(&desc0000000000000148);
if (error) goto returnError;
// Move this to the top of the routine!
PIActionReference ref0000000000000058 = NULL;
error = sPSActionReference->Make(&ref0000000000000058);
if (error) goto returnError;
error = sPSActionReference->PutEnumerated(ref0000000000000058, classLayer, typeOrdinal, enumTarget);
if (error) goto returnError;
error = sPSActionDescriptor->PutReference(desc0000000000000148, keyNull, ref0000000000000058);
if (error) goto returnError;
error = sPSActionDescriptor->PutEnumerated(desc0000000000000148, keyFreeTransformCenterState, typeQuadCenterState, enumQCSAverage);
if (error) goto returnError;
// Move this to the top of the routine!
PIActionDescriptor desc0000000000000150 = NULL;
error = sPSActionDescriptor->Make(&desc0000000000000150);
if (error) goto returnError;
error = sPSActionDescriptor->PutUnitFloat(desc0000000000000150, keyHorizontal, unitDistance, 0.5);
if (error) goto returnError;
error = sPSActionDescriptor->PutUnitFloat(desc0000000000000150, keyVertical, unitDistance, 0);
if (error) goto returnError;
error = sPSActionDescriptor->PutObject(desc0000000000000148, keyOffset, classOffset, desc0000000000000150);
if (error) goto returnError;
error = sPSActionDescriptor->PutUnitFloat(desc0000000000000148, keyWidth, unitPercent, 105);
if (error) goto returnError;
error = sPSActionDescriptor->PutEnumerated(desc0000000000000148, keyInterfaceIconFrameDimmed, typeInterpolation, enumBicubic);
if (error) goto returnError;
error = sPSActionControl->Play(&result, eventTransform, desc0000000000000148, plugInDialogSilent);
if (error) goto returnError;
returnError:
if (result != NULL) sPSActionDescriptor->Free(result);
if (desc0000000000000148 != NULL) sPSActionDescriptor->Free(desc0000000000000148);
if (ref0000000000000058 != NULL) sPSActionReference->Free(ref0000000000000058);
if (desc0000000000000150 != NULL) sPSActionDescriptor->Free(desc0000000000000150);
return error;
}
3. I take that action and re write it (The only change being the unit percent to unit pixel):
static SPErr EventLayerTransform(string selectedLayer, int eventKeyID, real64 value)
{
char* layerName = (char*)selectedLayer.c_str();
EventSelectLayer(layerName);
PIActionDescriptor result = NULL;
DescriptorTypeID runtimeKeyID;
DescriptorTypeID runtimeTypeID;
DescriptorTypeID runtimeObjID;
DescriptorTypeID runtimeEnumID;
DescriptorTypeID runtimeClassID;
DescriptorTypeID runtimePropID;
DescriptorTypeID runtimeUnitID;
SPErr error = kSPNoError;
PIActionDescriptor desc0000000000000188 = NULL;
PIActionReference ref0000000000000068 = NULL;
PIActionDescriptor desc0000000000000190 = NULL;
error = sPSActionDescriptor->Make(&desc0000000000000188);
if (error) goto returnError;
error = sPSActionReference->Make(&ref0000000000000068);
if (error) goto returnError;
error = sPSActionDescriptor->Make(&desc0000000000000190);
if (error) goto returnError;
error = sPSActionReference->PutEnumerated(ref0000000000000068, classLayer, typeOrdinal, enumTarget);
if (error) goto returnError;
error = sPSActionDescriptor->PutReference(desc0000000000000188, keyNull, ref0000000000000068);
if (error) goto returnError;
error = sPSActionDescriptor->PutEnumerated(desc0000000000000188, keyFreeTransformCenterState, typeQuadCenterState, enumQCSAverage);
if (error) goto returnError;
error = sPSActionDescriptor->PutUnitFloat(desc0000000000000188, keyHorizontal, unitDistance, -0.5);
if (error) goto returnError;
error = sPSActionDescriptor->PutUnitFloat(desc0000000000000188, keyVertical, unitDistance, -0.5);
if (error) goto returnError;
error = sPSActionDescriptor->PutObject(desc0000000000000188, keyOffset, classOffset, desc0000000000000190);
if (error) goto returnError;
error = sPSActionDescriptor->PutUnitFloat(desc0000000000000188, eventKeyID, unitPixels, value);
if (error) goto returnError;
error = sPSActionDescriptor->PutEnumerated(desc0000000000000188, keyInterfaceIconFrameDimmed, typeInterpolation, enumBicubic);
if (error) goto returnError;
error = sPSActionControl->Play(&result, eventTransform, desc0000000000000188, plugInDialogSilent);
if (error) goto returnError;
returnError:
if (result != NULL) sPSActionDescriptor->Free(result);
if (desc0000000000000188 != NULL) sPSActionDescriptor->Free(desc0000000000000188);
if (desc0000000000000190 != NULL) sPSActionDescriptor->Free(desc0000000000000190);
return error;
}
Copy link to clipboard
Copied
I updated my header of my reply to reflect your 'key' idea: "All I'm trying to do is add 1 pixel to the layer transform bounds (only if the layer is not currently even, so funny enough It should always be divisible by 2)."
Copy link to clipboard
Copied
Screenshots in your post are not displayed - could you repost them?
Did you report this bug by some dedicated site, can you leave a link?
Copy link to clipboard
Copied
@Kukurykusthe images are just showing that I'm starting with a uneven number and after running the action (To make the number even) how the new set transforms are still uneven.
This bug has been directly reported to Adobe other than this thread.
Copy link to clipboard
Copied
Well okey, images were to better imagine the problem. Regarding report, what is direct way to Adobe? That I know there is some site to report bugs, but I did not know I can do it directly, so what route / email you used, where have you got it?
I guess it's Photoshop bug, so did you use Photoshop Family Customer Community site?
I never got back nothing like Adobe Case or CRM, was that phone conversation with support or something else?
Copy link to clipboard
Copied
Hope these images show now.
Copy link to clipboard
Copied
I think sometimes I have similar problem when I'm resizing image. It some cases it have 1px too many for width or height. But when I crop it, it always have expected width and height. I can't remian now when it happens but that caused some problem for me when I experienced it. Anyway that was some time ago I don't remember it well now.
So is there some better way to contact Adobe than via Photoshop Family site that I noticed isn't best way to report bugs?
Copy link to clipboard
Copied
@Tom,
Just messaging back to see if you have any advice, I know one of your ideas was that when the layer is un even, the pixel could try and be setting in a half pixel.
This would be awesome if that was the solution but the fact that I am trying to set my layer bounds to be divisible by 2 in the first place tells me that's not the case. Also, I'd like to stay way from setting the size from a percentage.
Any other suggestions, this is holding back the team from using the plugin at the moment, (no fast way to set 100's of layers to be divisible by 2 if they're not)
Thanks!
Copy link to clipboard
Copied
This is the only workaround I could come up with.
Copy link to clipboard
Copied
Thanks so much for your time, Can I just ask one last thing, if you change it to `pixelUnit` instead of `percentUnit` would that still produce the same thing? I'm concerned pixelUnit has a bug in it.
var idpercentUnit = stringIDToTypeID( "percentUnit" );
Copy link to clipboard
Copied
Specifying pixelUnit does sound like a bug to me. Photoshop is pretty good at pixels! We have cases where you have to use one and only one unit type and those are bugs in my opinion as well. I'll write it up and see if we can fix.
Copy link to clipboard
Copied
Thank you so much tom, I am in conversation with Adobe about this: Adobe Case ADB-2742472-S3V7 CRM:01211000000465
Have a great weekend!