diff --git a/android/src/main/java/com/jimmydaddy/imagemarker/ImageMarkerManager.java b/android/src/main/java/com/jimmydaddy/imagemarker/ImageMarkerManager.java index 89f76ef7..a34d1b1c 100644 --- a/android/src/main/java/com/jimmydaddy/imagemarker/ImageMarkerManager.java +++ b/android/src/main/java/com/jimmydaddy/imagemarker/ImageMarkerManager.java @@ -267,6 +267,7 @@ private void markImageByText( String fontName, Integer fontSize, ShadowLayerStyle shadowLayerStyle, + TextBackgroundStyle textBackgroundStyle, Integer X, Integer Y, int quality, @@ -332,25 +333,26 @@ private void markImageByText( textWidth = (int) Math.ceil(Math.max(textWidth, textLayout.getLineWidth(a) + textLayout.getLineLeft(a))); } - float x = 20; - float y = 20; + int margin = 20; + float x = margin; + float y = margin; if (position != null) { if("topCenter".equals(position)) { x = (width - textWidth)/2; } else if("topRight".equals(position)) { - x = (width - textWidth); + x = width - textWidth - margin; } else if("center".equals(position)) { x = (width - textWidth) / 2; y = (height - textHeight) / 2; } else if("bottomLeft".equals(position)) { - y = (height - textHeight); + y = height - textHeight - margin; } else if("bottomCenter".equals(position)) { x = (width - textWidth) / 2; y = (height - textHeight); } else if("bottomRight".equals(position)) { - x = (width - textWidth); - y = (height - textHeight); + x = width - textWidth - margin; + y = height - textHeight - margin; } } else { if (null != X) { @@ -361,6 +363,20 @@ private void markImageByText( } } + // Draw text background + if(null != textBackgroundStyle) { + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG); + paint.setStyle(Paint.Style.FILL); + paint.setColor(textBackgroundStyle.color); + if("stretchX".equals(textBackgroundStyle.type)) { + canvas.drawRect(0, y - textBackgroundStyle.paddingY, width, y + textHeight + textBackgroundStyle.paddingY, paint); + } else if("stretchY".equals(textBackgroundStyle.type)) { + canvas.drawRect(x - textBackgroundStyle.paddingX, 0, x + textWidth + textBackgroundStyle.paddingX, height, paint); + } else { + canvas.drawRect(x - textBackgroundStyle.paddingX, y - textBackgroundStyle.paddingY, + x + textWidth + textBackgroundStyle.paddingX, y + textHeight + textBackgroundStyle.paddingY, paint); + } + } canvas.save(); canvas.translate(x, y); textLayout.draw(canvas); @@ -413,6 +429,7 @@ public void addText( final String fontName, final Integer fontSize, ReadableMap shadowStyle, + ReadableMap textBackgroundStyle, final float scale, final int quality, String filename, @@ -429,6 +446,7 @@ public void addText( final String dest = generateCacheFilePathForMarker(uri, filename); final ShadowLayerStyle myShadowStyle = null != shadowStyle? new ShadowLayerStyle(shadowStyle) : null; + final TextBackgroundStyle myTextBackgroundStyle = null != textBackgroundStyle ? new TextBackgroundStyle(textBackgroundStyle) : null; Log.d(IMAGE_MARKER_TAG, uri); Log.d(IMAGE_MARKER_TAG, src.toString()); @@ -442,7 +460,7 @@ public void addText( public void onNewResultImpl(@Nullable Bitmap bitmap) { if (bitmap != null) { Bitmap bg = Utils.scaleBitmap(bitmap, scale); - markImageByText(bg, mark, null, color, fontName, fontSize, myShadowStyle, X, Y, quality, dest, promise); + markImageByText(bg, mark, null, color, fontName, fontSize, myShadowStyle, myTextBackgroundStyle, X, Y, quality, dest, promise); } else { promise.reject( "marker error","Can't retrieve the file from the src: " + uri); } @@ -473,7 +491,7 @@ public void onFailureImpl(DataSource dataSource) { bitmap.recycle(); System.gc(); } - markImageByText(bg, mark, null, color, fontName, fontSize, myShadowStyle, X, Y, quality, dest, promise); + markImageByText(bg, mark, null, color, fontName, fontSize, myShadowStyle, myTextBackgroundStyle, X, Y, quality, dest, promise); } } } catch (Exception e) { @@ -502,6 +520,7 @@ public void addTextByPostion( final String fontName, final Integer fontSize, ReadableMap shadowStyle, + ReadableMap textBackgroundStyle, final float scale, final Integer quality, String filename, @@ -517,6 +536,7 @@ public void addTextByPostion( final String dest = generateCacheFilePathForMarker(uri, filename); final ShadowLayerStyle myShadowStyle = null != shadowStyle? new ShadowLayerStyle(shadowStyle) : null; + final TextBackgroundStyle myTextBackgroundStyle = null != textBackgroundStyle ? new TextBackgroundStyle(textBackgroundStyle) : null; Log.d(IMAGE_MARKER_TAG, uri); @@ -531,7 +551,7 @@ public void addTextByPostion( public void onNewResultImpl(@Nullable Bitmap bitmap) { if (bitmap != null) { Bitmap bg = Utils.scaleBitmap(bitmap, scale); - markImageByText(bg, mark, position, color, fontName, fontSize, myShadowStyle,null, null, quality, dest, promise); + markImageByText(bg, mark, position, color, fontName, fontSize, myShadowStyle, myTextBackgroundStyle, null, null, quality, dest, promise); } else { promise.reject( "marker error","Can't retrieve the file from the src: " + uri); } @@ -562,7 +582,7 @@ public void onFailureImpl(DataSource dataSource) { bitmap.recycle(); System.gc(); } - markImageByText(bg, mark, position, color, fontName, fontSize, myShadowStyle, null, null, quality, dest, promise); + markImageByText(bg, mark, position, color, fontName, fontSize, myShadowStyle, myTextBackgroundStyle, null, null, quality, dest, promise); } } } catch (Exception e) { diff --git a/android/src/main/java/com/jimmydaddy/imagemarker/TextBackgroundStyle.java b/android/src/main/java/com/jimmydaddy/imagemarker/TextBackgroundStyle.java new file mode 100644 index 00000000..69cffd68 --- /dev/null +++ b/android/src/main/java/com/jimmydaddy/imagemarker/TextBackgroundStyle.java @@ -0,0 +1,77 @@ +package com.jimmydaddy.imagemarker; + +import android.graphics.Color; +import android.util.Log; +import com.facebook.react.bridge.ReadableMap; + +public class TextBackgroundStyle { + public String type = ""; + public float paddingX = 0F; + public float paddingY = 0F; + public int color = Color.TRANSPARENT; + + public TextBackgroundStyle(String type, float paddingX, float paddingY, int color) { + this.type = type; + this.paddingX = paddingX; + this.paddingY = paddingY; + this.color = color; + } + + public TextBackgroundStyle(ReadableMap readableMap) { + if (null != readableMap) { + try { + this.setType(readableMap.getString("type")); + this.setPaddingX((float) readableMap.getDouble("paddingX")); + this.setPaddingY((float) readableMap.getDouble("paddingY")); + this.setColor(readableMap.getString("color")); + } catch (Exception e) { + Log.d(Utils.TAG, "Unknown text background options ", e); + } + + } + } + + public String getType() { + return type; + } + + public float getPaddingX() { + return paddingX; + } + + public float getPaddingY() { + return paddingY; + } + + public int getColor() { + return color; + } + + public void setType(String type) { + this.type = type; + } + + public void setPaddingX(float paddingX) { + this.paddingX = paddingX; + } + + public void setPaddingY(float paddingY) { + this.paddingY = paddingY; + } + + public void setColor(int color) { + this.color = color; + } + + public void setColor(String color) { + try { + Integer parsedColor = Color.parseColor(color); + if (null != parsedColor) { + this.setColor(parsedColor); + } + } catch (Exception e) { + Log.d(Utils.TAG, "Unknown color string ", e); + } + + } +} diff --git a/index.js b/index.js index 29ecf6f1..5e8f650c 100644 --- a/index.js +++ b/index.js @@ -28,6 +28,13 @@ export type ShadowLayerStyle = { 'color': string } +export type TextBackgroundStyle = { + 'paddingX': float, + 'paddingY': float, + 'type': string, + 'color': string +} + type TextMarkOption = { // image src, local image src: string, @@ -45,7 +52,8 @@ type TextMarkOption = { quality: number, position?: Position, filename?: string, - shadowStyle: ShadowLayerStyle + shadowStyle: ShadowLayerStyle, + textBackgroundStyle: TextBackgroundStyle } type ImageMarkOption = { @@ -74,6 +82,7 @@ export default class Marker { fontName, fontSize, shadowStyle, + textBackgroundStyle, scale, quality, position, @@ -93,6 +102,7 @@ export default class Marker { } let mShadowStyle = shadowStyle || {} + let mTextBackgroundStyle = textBackgroundStyle || {} if (!position) { return ImageMarker.addText( @@ -104,6 +114,7 @@ export default class Marker { fontName, fontSize, mShadowStyle, + mTextBackgroundStyle, scale, quality, filename @@ -117,6 +128,7 @@ export default class Marker { fontName, fontSize, mShadowStyle, + mTextBackgroundStyle, scale, quality, filename diff --git a/ios/RCTImageMarker/RCTImageMarker.h b/ios/RCTImageMarker/RCTImageMarker.h index 8792c19c..fb715df6 100644 --- a/ios/RCTImageMarker/RCTImageMarker.h +++ b/ios/RCTImageMarker/RCTImageMarker.h @@ -15,3 +15,10 @@ @interface ImageMarker : NSObject @end + +@interface TextBackground : NSObject +@property (copy) UIColor * colorBg; +@property (copy) NSString * typeBg; +@property (assign) float paddingX; +@property (assign) float paddingY; +@end \ No newline at end of file diff --git a/ios/RCTImageMarker/RCTImageMarker.m b/ios/RCTImageMarker/RCTImageMarker.m index 94d0b1cb..54e2d9e8 100644 --- a/ios/RCTImageMarker/RCTImageMarker.m +++ b/ios/RCTImageMarker/RCTImageMarker.m @@ -23,6 +23,10 @@ Center = 6 } MarkerPosition; +@implementation TextBackground + +@end + @implementation RCTConvert(MarkerPosition) RCT_ENUM_CONVERTER(MarkerPosition, @@ -76,7 +80,7 @@ void saveImageForMarker(NSString * fullPath, UIImage * image, float quality) } } -UIImage * markerImgWithText(UIImage *image, NSString* text, CGFloat X, CGFloat Y, UIColor* color, UIFont* font, CGFloat scale, NSShadow* shadow){ +UIImage * markerImgWithText(UIImage *image, NSString* text, CGFloat X, CGFloat Y, UIColor* color, UIFont* font, CGFloat scale, NSShadow* shadow, TextBackground* textBackground){ int w = image.size.width; int h = image.size.height; @@ -87,6 +91,7 @@ void saveImageForMarker(NSString * fullPath, UIImage * image, float quality) NSForegroundColorAttributeName : color, //设置字体颜色 NSShadowAttributeName : shadow }; + CGRect position = CGRectMake(X, Y, w, h); [text drawInRect:position withAttributes:attr]; UIImage *aimg = UIGraphicsGetImageFromCurrentImageContext(); @@ -188,10 +193,10 @@ void saveImageForMarker(NSString * fullPath, UIImage * image, float quality) } -UIImage * markerImgWithTextByPostion (UIImage *image, NSString* text, MarkerPosition position, UIColor* color, UIFont* font, CGFloat scale, NSShadow* shadow){ +UIImage * markerImgWithTextByPostion (UIImage *image, NSString* text, MarkerPosition position, UIColor* color, UIFont* font, CGFloat scale, NSShadow* shadow, TextBackground* textBackground){ int w = image.size.width; int h = image.size.height; - + NSDictionary *attr = @{ NSFontAttributeName: font, //设置字体 NSForegroundColorAttributeName : color, //设置字体颜色 @@ -203,57 +208,49 @@ void saveImageForMarker(NSString * fullPath, UIImage * image, float quality) // CGSize size = CGSizeMake(fontSize, height); UIGraphicsBeginImageContextWithOptions(image.size, NO, scale); [image drawInRect:CGRectMake(0, 0, w, h)]; - CGRect rect; + + int margin = 20; + int posX = margin; + int posY = margin; + switch (position) { - case TopLeft: - rect = (CGRect){ - CGPointMake(20, 20), - size - }; - break; case TopCenter: - rect = (CGRect){ - CGPointMake((w-(size.width))/2, 20), - size - }; + posX = (w-(size.width))/2; break; case TopRight: - rect = (CGRect){ - CGPointMake((w-size.width-20), 20), - size - }; + posX = (w-size.width) - margin; break; case BottomLeft: - rect = (CGRect){ - CGPointMake(20, h-size.height-20), - size - }; + posY = h-size.height - margin; break; case BottomCenter: - rect = (CGRect){ - CGPointMake((w-(size.width))/2, h-size.height-20), - size - }; + posX = (w-(size.width))/2; + posY = h-size.height; break; case BottomRight: - rect = (CGRect){ - CGPointMake(w-(size.width), h-size.height-20), - size - }; + posX = w-(size.width) - margin; + posY = h-size.height - margin; break; case Center: - rect = (CGRect){ - CGPointMake((w-(size.width))/2, (h-size.height)/2), - size - }; - break; - default: - rect = (CGRect){ - CGPointMake(20, 20), - size - }; + posX = (w-(size.width))/2; + posY = (h-size.height)/2; break; } + + if (textBackground != nil) { + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(context, textBackground.colorBg.CGColor); + if([textBackground.typeBg isEqualToString:@"stretchX"]) { + CGContextFillRect(context, CGRectMake(0, posY - textBackground.paddingY, w, size.height + 2*textBackground.paddingY)); + } else if([textBackground.typeBg isEqualToString:@"stretchY"]) { + CGContextFillRect(context, CGRectMake(posX - textBackground.paddingX, 0, size.width + 2*textBackground.paddingX, h)); + } else { + CGContextFillRect(context, CGRectMake(posX - textBackground.paddingX, posY - textBackground.paddingY, + size.width + 2*textBackground.paddingX, size.height + 2*textBackground.paddingY)); + } + } + + CGRect rect = (CGRect){ CGPointMake(posX, posY), size }; [text drawInRect:rect withAttributes:attr]; UIImage *aimg = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); @@ -313,6 +310,24 @@ -(NSShadow*)getShadowStyle:(NSDictionary *) shadowStyle } } +-(TextBackground*)getTextBackgroundStyle:(NSDictionary *) textBackground +{ + if (textBackground != nil) { + TextBackground *txtBackground = [[TextBackground alloc]init]; + txtBackground.typeBg = textBackground[@"type"]; + txtBackground.paddingX = [RCTConvert CGFloat: textBackground[@"paddingX"]]; + txtBackground.paddingY = [RCTConvert CGFloat: textBackground[@"paddingY"]]; + if([textBackground[@"color"] length] > 1) { + txtBackground.colorBg = [self getColor:textBackground[@"color"]]; + } else { + txtBackground.colorBg = [UIColor clearColor]; + } + return txtBackground; + } else { + return nil; + } +} + RCT_EXPORT_METHOD(addText: (nonnull NSDictionary *)src text:(nonnull NSString*)text X:(CGFloat)X @@ -321,6 +336,7 @@ -(NSShadow*)getShadowStyle:(NSDictionary *) shadowStyle fontName:(NSString*)fontName fontSize:(CGFloat)fontSize shadowStyle:(nullable NSDictionary *)shadowStyle + textBackgroundStyle:(nullable NSDictionary *)textBackgroundStyle scale:(CGFloat)scale quality:(NSInteger) quality filename: (NSString *)filename @@ -344,9 +360,9 @@ -(NSShadow*)getShadowStyle:(NSDictionary *) shadowStyle UIFont* font = [UIFont fontWithName:fontName size:fontSize]; UIColor* uiColor = [self getColor:color]; NSShadow* shadow = [self getShadowStyle: shadowStyle]; - + TextBackground* textBackground = [self getTextBackgroundStyle: textBackgroundStyle]; - UIImage * scaledImage = markerImgWithText(image, text, X, Y , uiColor, font, scale, shadow); + UIImage * scaledImage = markerImgWithText(image, text, X, Y , uiColor, font, scale, shadow, textBackground); if (scaledImage == nil) { NSLog(@"Can't mark the image"); reject(@"error",@"Can't mark the image.", error); @@ -366,6 +382,7 @@ -(NSShadow*)getShadowStyle:(NSDictionary *) shadowStyle fontName:(NSString*)fontName fontSize:(CGFloat)fontSize shadowStyle:(NSDictionary *)shadowStyle + textBackgroundStyle:(NSDictionary *)textBackgroundStyle scale:(CGFloat)scale quality:(NSInteger) quality filename: (NSString *)filename @@ -393,7 +410,9 @@ -(NSShadow*)getShadowStyle:(NSDictionary *) shadowStyle UIFont* font = [UIFont fontWithName:fontName size:fontSize]; UIColor* uiColor = [self getColor:color]; NSShadow* shadow = [self getShadowStyle: shadowStyle]; - UIImage * scaledImage = markerImgWithTextByPostion(image, text, position, uiColor, font, scale, shadow); + TextBackground* textBackground = [self getTextBackgroundStyle: textBackgroundStyle]; + + UIImage * scaledImage = markerImgWithTextByPostion(image, text, position, uiColor, font, scale, shadow, textBackground); if (scaledImage == nil) { NSLog(@"Can't mark the image"); reject(@"error",@"Can't mark the image.", error);